/* =====================================================================
   memory.jsx — 长期记忆面板
   MemoryPanel（浮层：我的画像 + 记忆，查看/编辑/新增/删除）
   依赖：React, bandu.chat（getProfile/putProfile/listAllMemories/addMemory/removeMemory）
   导出：bandu.MemoryPanel
   ===================================================================== */

window.bandu = window.bandu || {};

(function (bandu) {

const { useState, useEffect, useCallback } = React;

const FIELD_LABEL = {
  occupation: "职业背景", education: "教育背景", foundation: "当前基础",
  habit: "学习习惯", goal: "学习目标", style: "偏好风格",
};
const SINGLE_FIELDS = ["occupation", "education", "habit", "goal", "style"];
const SOURCE_LABEL = { user: "手动", inferred: "AI 推断" };
const CATEGORY_ZH = {
  misconception: "误解", mastery: "掌握", habit: "习惯",
  preference: "偏好", emotion: "情绪", fact: "事实", other: "其他",
};
const KIND_LABEL = { summary: "概要", fragment: "碎片" };

// 一行画像：值文本 + 来源徽标，点击进入行内编辑；失焦/回车保存；清空保存＝删除该行
function ProfileRow({ field, domain, value, source, onSave }) {
  const [editing, setEditing] = useState(false);
  const [draft, setDraft] = useState(value);
  const [busy, setBusy] = useState(false);
  const [err, setErr] = useState(null);

  useEffect(() => { if (!editing) setDraft(value); }, [value, editing]);

  const commit = async () => {
    if (busy) return;
    if (draft === value) { setEditing(false); return; }
    setBusy(true);
    try {
      await onSave(field, domain, draft);
      setEditing(false);
      setErr(null);
    } catch (e) {
      setErr(e.message);
    } finally {
      setBusy(false);
    }
  };

  if (editing) {
    return (
      <React.Fragment>
        <input
          className="memory-field-input"
          autoFocus
          value={draft}
          disabled={busy}
          onChange={(e) => setDraft(e.target.value)}
          onBlur={commit}
          onKeyDown={(e) => {
            if (e.key === "Enter") { e.preventDefault(); commit(); }
            if (e.key === "Escape") { setDraft(value); setEditing(false); }
          }}
        />
        {err && <div className="memory-err">保存失败：{err}</div>}
      </React.Fragment>
    );
  }

  return (
    <div className="memory-field-row" onClick={() => setEditing(true)}>
      {domain && <span className="memory-field-domain">{domain}</span>}
      <span className="memory-field-value">{value || "点击填写…"}</span>
      {source && <span className={`memory-badge ${source}`}>{SOURCE_LABEL[source] || source}</span>}
    </div>
  );
}

// 「当前基础」：可有多行（每行一个 domain），另外提供「+ 添加领域」的小表单
function FoundationField({ rows, onSave }) {
  const [adding, setAdding] = useState(false);
  const [domain, setDomain] = useState("");
  const [value, setValue] = useState("");
  const [busy, setBusy] = useState(false);
  const [err, setErr] = useState(null);

  const submit = async () => {
    const d = domain.trim(), v = value.trim();
    if (!d || !v || busy) return;
    setBusy(true);
    try {
      await onSave("foundation", d, v);
      setDomain(""); setValue(""); setAdding(false);
      setErr(null);
    } catch (e) {
      setErr(e.message);
    } finally {
      setBusy(false);
    }
  };

  return (
    <div className="memory-field">
      <span className="memory-field-label">{FIELD_LABEL.foundation}</span>
      <div className="memory-foundation">
        {rows.map((row) => (
          <ProfileRow
            key={row.domain}
            field="foundation"
            domain={row.domain}
            value={row.value}
            source={row.source}
            onSave={onSave}
          />
        ))}
        {adding ? (
          <div className="memory-foundation-add">
            <input
              autoFocus
              placeholder="领域，如：Python"
              value={domain}
              disabled={busy}
              onChange={(e) => setDomain(e.target.value)}
            />
            <input
              placeholder="当前基础"
              value={value}
              disabled={busy}
              onChange={(e) => setValue(e.target.value)}
              onKeyDown={(e) => { if (e.key === "Enter") submit(); }}
            />
            <button className="btn" disabled={busy} onClick={submit}>保存</button>
            <button className="btn" disabled={busy} onClick={() => { setAdding(false); setDomain(""); setValue(""); setErr(null); }}>取消</button>
            {err && <div className="memory-err">保存失败：{err}</div>}
          </div>
        ) : (
          <button type="button" className="memory-add-domain" onClick={() => setAdding(true)}>+ 添加领域</button>
        )}
      </div>
    </div>
  );
}

function ProfileSection({ fields, err, onSave }) {
  return (
    <section className="memory-section">
      <h3 className="memory-section-title">我的画像</h3>
      {err && <div className="memory-err">画像加载失败：{err}</div>}
      {fields === null ? (
        !err && <div className="memory-loading">加载中…</div>
      ) : (
        <React.Fragment>
          {fields.length === 0 && (
            <div className="memory-empty">还没有画像。伴读会随着对话逐渐了解你，你也可以直接填写。</div>
          )}
          {SINGLE_FIELDS.map((field) => {
            const row = fields.find((r) => r.field === field);
            return (
              <div key={field} className="memory-field">
                <span className="memory-field-label">{FIELD_LABEL[field]}</span>
                <ProfileRow
                  field={field}
                  domain=""
                  value={row ? row.value : ""}
                  source={row ? row.source : null}
                  onSave={onSave}
                />
              </div>
            );
          })}
          <FoundationField rows={fields.filter((r) => r.field === "foundation")} onSave={onSave} />
        </React.Fragment>
      )}
    </section>
  );
}

// 一条记忆：类别 + 日期 + 归属 + 正文，删除二段确认（同 NoteBubble 的删除交互）
function MemoryRow({ memory, onRemove }) {
  const [confirm, setConfirm] = useState(false);
  const [err, setErr] = useState(null);

  const del = async () => {
    if (!confirm) { setConfirm(true); setErr(null); return; }
    try {
      await onRemove(memory.id);
    } catch (e) {
      setErr(e.message); setConfirm(false);
    }
  };

  return (
    <div className="memory-row">
      <div className="memory-row-head">
        <span className="memory-cat">{CATEGORY_ZH[memory.category] || memory.category}</span>
        <span className="memory-date">{(memory.occurred_at || "").slice(0, 10)}</span>
        {memory.book_id == null && <span className="memory-scope">全书通用</span>}
        <button
          type="button"
          className={`memory-del ${confirm ? "confirm" : ""}`}
          onClick={del}
          onMouseLeave={() => setConfirm(false)}
        >
          {confirm ? "确认删除？" : "删"}
        </button>
      </div>
      <div className="memory-row-text">{memory.text}</div>
      {err && <div className="memory-err">{err}</div>}
    </div>
  );
}

function MemorySection({ memories, err, onAdd, onRemove }) {
  const [draft, setDraft] = useState("");
  const [busy, setBusy] = useState(false);
  const [addErr, setAddErr] = useState(null);

  const submit = async () => {
    const t = draft.trim();
    if (!t || busy) return;
    setBusy(true); setAddErr(null);
    try {
      await onAdd(t);
      setDraft("");
    } catch (e) {
      setAddErr(e.message);
    }
    setBusy(false);
  };

  const summaries = memories ? memories.filter((m) => m.kind === "summary") : [];
  const fragments = memories ? memories.filter((m) => m.kind === "fragment") : [];

  return (
    <section className="memory-section">
      <h3 className="memory-section-title">记忆</h3>
      {err && <div className="memory-err">记忆加载失败：{err}</div>}
      {memories === null ? (
        !err && <div className="memory-loading">加载中…</div>
      ) : (
        <React.Fragment>
          {memories.length === 0 && (
            <div className="memory-empty">还没有记忆。多聊几轮，伴读会自动整理；也可以点下面记一条。</div>
          )}
          {summaries.length > 0 && (
            <div className="memory-kind-group">
              <div className="memory-kind-label">{KIND_LABEL.summary}</div>
              {summaries.map((m) => <MemoryRow key={m.id} memory={m} onRemove={onRemove} />)}
            </div>
          )}
          {fragments.length > 0 && (
            <div className="memory-kind-group">
              <div className="memory-kind-label">{KIND_LABEL.fragment}</div>
              {fragments.map((m) => <MemoryRow key={m.id} memory={m} onRemove={onRemove} />)}
            </div>
          )}
        </React.Fragment>
      )}
      <div className="memory-add">
        <textarea
          className="memory-add-input"
          rows={2}
          placeholder="记一条…"
          value={draft}
          disabled={busy}
          onChange={(e) => setDraft(e.target.value)}
        />
        {addErr && <div className="memory-err">{addErr}</div>}
        <button className="btn primary" disabled={busy || !draft.trim()} onClick={submit}>
          {busy ? "…" : "+ 记一条"}
        </button>
      </div>
    </section>
  );
}

function MemoryPanel({ bookId, onClose }) {
  // null = 加载中；后续用数组承载
  const [fields, setFields] = useState(null);
  const [memories, setMemories] = useState(null);
  const [profileErr, setProfileErr] = useState(null);
  const [memErr, setMemErr] = useState(null);

  const loadProfile = useCallback(() => {
    bandu.chat.getProfile().then(setFields).catch((e) => setProfileErr(e.message));
  }, []);
  const loadMemories = useCallback(() => {
    bandu.chat.listAllMemories(bookId).then(setMemories).catch((e) => setMemErr(e.message));
  }, [bookId]);

  // 打开面板时并行拉两块；互不阻塞，各自失败各自报错，不拖垮另一块
  useEffect(() => {
    setFields(null); setMemories(null); setProfileErr(null); setMemErr(null);
    loadProfile();
    loadMemories();
  }, [loadProfile, loadMemories]);

  const saveField = async (field, domain, value) => {
    await bandu.chat.putProfile([{ field, domain, value }]);
    loadProfile();
  };

  const addMemoryEntry = async (text) => {
    await bandu.chat.addMemory({ text, bookId, category: "other" });
    loadMemories();
  };

  const removeMemoryEntry = async (id) => {
    await bandu.chat.removeMemory(id);
    loadMemories();
  };

  return (
    <div className="memory-overlay" onClick={onClose}>
      <div className="memory-panel" onClick={(e) => e.stopPropagation()}>
        <div className="memory-head">
          <span className="memory-title">画像与记忆</span>
          <button type="button" className="memory-close" onClick={onClose} title="关闭">×</button>
        </div>
        <div className="memory-body">
          <ProfileSection fields={fields} err={profileErr} onSave={saveField} />
          <MemorySection memories={memories} err={memErr} onAdd={addMemoryEntry} onRemove={removeMemoryEntry} />
        </div>
      </div>
    </div>
  );
}

bandu.MemoryPanel = MemoryPanel;

})(window.bandu);
