/* ==================================================================
   Admin → Topics
   ------------------------------------------------------------------
   Curate the topic catalog teachers pick from when authoring a test.
   Topics are nested under chapters: pick class → subject → chapter
   on the left, then manage that chapter's topic list on the right.
   No FK from tests → topics today (tests store the topic name as
   TEXT), so deletes are unconditional.

   IIFE wrap — see the matching note in screen-admin-chapters.jsx.
   babel-standalone transpiles `const` to `var` in the global scope,
   so without this wrapper helpers like `ErrBanner` collide with the
   identically-named locals in chapters + taxonomy.
   ================================================================== */

(() => {
const { Icon: TIcon } = window.KXUI;

const TopicsScreen = () => {
  const [subjects, setSubjects] = React.useState([]);
  const [subjectsErr, setSubjectsErr] = React.useState(null);
  const [classLevels, setClassLevels] = React.useState([]);
  const [classErr, setClassErr] = React.useState(null);

  // Three-step picker: class → subject → chapter. Each narrows the next.
  const [pickedClass, setPickedClass] = React.useState("");
  const [pickedSubjectId, setPickedSubjectId] = React.useState("");
  const [chapters, setChapters] = React.useState([]);
  const [chaptersErr, setChaptersErr] = React.useState(null);
  const [chaptersLoading, setChaptersLoading] = React.useState(false);
  const [pickedChapterId, setPickedChapterId] = React.useState("");

  // Bootstrap — subjects + distinct class levels.
  React.useEffect(() => {
    setSubjectsErr(null);
    window.KXApi.get("/admin/subjects").then(setSubjects)
      .catch((e) => setSubjectsErr(String(e.message || e)));
  }, []);
  React.useEffect(() => {
    setClassErr(null);
    window.KXApi.get("/admin/class-sections")
      .then((sections) => {
        const uniq = Array.from(new Set((sections || []).map((s) => s.class_level).filter(Boolean))).sort();
        setClassLevels(uniq);
      })
      .catch((e) => setClassErr(String(e.message || e)));
  }, []);

  // Whenever the (class × subject) pair becomes resolvable, fetch the chapter
  // list it contains. Clears the previously-picked chapter if it no longer
  // appears in the new list so the right panel doesn't show stale topics.
  React.useEffect(() => {
    if (!pickedClass || !pickedSubjectId) { setChapters([]); setPickedChapterId(""); return; }
    setChaptersLoading(true); setChaptersErr(null);
    const q = new URLSearchParams({ subject_id: pickedSubjectId, class_level: pickedClass });
    window.KXApi.get(`/admin/chapters?${q.toString()}`)
      .then((rows) => {
        setChapters(rows);
        if (pickedChapterId && !rows.some((r) => r.id === pickedChapterId)) setPickedChapterId("");
      })
      .catch((e) => setChaptersErr(String(e.message || e)))
      .finally(() => setChaptersLoading(false));
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [pickedClass, pickedSubjectId]);

  return (
    <div style={{ padding: "24px 28px", maxWidth: 1100, margin: "0 auto" }}>
      <div style={{ display: "flex", alignItems: "center", gap: 12, marginBottom: 4 }}>
        <span style={{ color: "var(--accent)" }}><TIcon name="list" size={18}/></span>
        <div className="muted" style={{ fontSize: 11, letterSpacing: ".08em", textTransform: "uppercase" }}>Admin · Catalog</div>
      </div>
      <h1 style={{ margin: "4px 0 6px", color: "var(--ink-0)", fontFamily: "'Instrument Serif', serif", fontWeight: 400, fontSize: 32, letterSpacing: "-0.01em" }}>
        Topics
      </h1>
      <p className="muted" style={{ margin: 0, fontSize: 13.5, maxWidth: 720 }}>
        Topics are the finer-grained tag under each chapter — what a teacher reaches for when "Chapter 4: Stoichiometry" is too broad. Pick a class, subject and chapter on the left to manage that chapter's topics on the right.
      </p>

      <div className="cx-catalog-split" style={{ marginTop: 22 }}>
        <PickerPanel
          classLevels={classLevels} classErr={classErr}
          subjects={subjects} subjectsErr={subjectsErr}
          chapters={chapters} chaptersErr={chaptersErr} chaptersLoading={chaptersLoading}
          pickedClass={pickedClass} onPickClass={setPickedClass}
          pickedSubjectId={pickedSubjectId} onPickSubject={setPickedSubjectId}
          pickedChapterId={pickedChapterId} onPickChapter={setPickedChapterId}/>
        <TopicsPanel chapter={chapters.find((c) => c.id === pickedChapterId) || null}/>
      </div>
    </div>
  );
};

const ErrBanner = ({ err, onClear }) => err ? (
  <div style={{
    margin: "8px 0", padding: "8px 10px",
    background: "rgba(255,107,107,0.08)", border: "1px solid var(--red)",
    borderRadius: 6, color: "var(--red)", fontSize: 12,
    display: "flex", justifyContent: "space-between", gap: 10,
  }}>
    <span>{err}</span>
    {onClear && <button className="btn ghost sm" onClick={onClear} style={{ padding: 2 }}><TIcon name="x" size={11}/></button>}
  </div>
) : null;

const PickerPanel = ({
  classLevels, classErr,
  subjects, subjectsErr,
  chapters, chaptersErr, chaptersLoading,
  pickedClass, onPickClass,
  pickedSubjectId, onPickSubject,
  pickedChapterId, onPickChapter,
}) => (
  <div className="card">
    <div className="card-head"><span className="card-title">Pick a chapter</span></div>
    <div className="card-body" style={{ padding: 14, display: "grid", gap: 12 }}>
      <ErrBanner err={classErr}/>
      <ErrBanner err={subjectsErr}/>

      <div>
        <label className="muted" style={{ fontSize: 11 }}>Class</label>
        <select className="input" value={pickedClass} onChange={(e) => onPickClass(e.target.value)} style={{ width: "100%", marginTop: 4 }}>
          <option value="">— pick a class —</option>
          {classLevels.map((cl) => <option key={cl} value={cl}>Class {cl}</option>)}
        </select>
      </div>

      <div>
        <label className="muted" style={{ fontSize: 11 }}>Subject</label>
        <select className="input" value={pickedSubjectId} onChange={(e) => onPickSubject(e.target.value)}
          disabled={!pickedClass} style={{ width: "100%", marginTop: 4 }}>
          <option value="">{pickedClass ? "— pick a subject —" : "pick a class first"}</option>
          {subjects.map((s) => <option key={s.id} value={s.id}>{s.name}</option>)}
        </select>
      </div>

      <div>
        <label className="muted" style={{ fontSize: 11 }}>Chapter</label>
        <select className="input" value={pickedChapterId} onChange={(e) => onPickChapter(e.target.value)}
          disabled={!pickedSubjectId || chapters.length === 0}
          style={{ width: "100%", marginTop: 4 }}>
          {chaptersLoading ? (
            <option value="">Loading…</option>
          ) : !pickedSubjectId ? (
            <option value="">pick a subject first</option>
          ) : chapters.length === 0 ? (
            <option value="">no chapters in this class+subject</option>
          ) : (
            <>
              <option value="">— pick a chapter —</option>
              {chapters.map((c) => (
                <option key={c.id} value={c.id}>Ch {c.chapter_number}. {c.chapter_name}</option>
              ))}
            </>
          )}
        </select>
        <ErrBanner err={chaptersErr}/>
      </div>
    </div>
  </div>
);

const TopicsPanel = ({ chapter }) => {
  const [items, setItems] = React.useState([]);
  const [loading, setLoading] = React.useState(false);
  const [err, setErr] = React.useState(null);
  const [actionErr, setActionErr] = React.useState(null);
  const [adding, setAdding] = React.useState(false);
  const [editingId, setEditingId] = React.useState(null);

  const refresh = React.useCallback(async () => {
    if (!chapter) { setItems([]); return; }
    setLoading(true); setErr(null);
    try { setItems(await window.KXApi.get(`/admin/topics?chapter_id=${encodeURIComponent(chapter.id)}`)); }
    catch (e) { setErr(String(e.message || e)); }
    finally { setLoading(false); }
  }, [chapter]);

  React.useEffect(() => { refresh(); }, [refresh]);

  const create = async (draft) => {
    setActionErr(null);
    try {
      await window.KXApi.post("/admin/topics", { chapter_id: chapter.id, ...draft });
      setAdding(false); await refresh();
    } catch (e) { setActionErr(String(e.message || e)); }
  };
  const update = async (id, draft) => {
    setActionErr(null);
    try {
      await window.KXApi.patch(`/admin/topics/${id}`, draft);
      setEditingId(null); await refresh();
    } catch (e) { setActionErr(String(e.message || e)); }
  };
  const remove = async (row) => {
    if (!window.confirm(`Delete topic "${row.topic_number}. ${row.topic_name}"?`)) return;
    setActionErr(null);
    try { await window.KXApi.del(`/admin/topics/${row.id}`); await refresh(); }
    catch (e) { setActionErr(String(e.message || e)); }
  };

  if (!chapter) {
    return (
      <div className="card">
        <div className="card-head"><span className="card-title">Topics</span></div>
        <div className="card-body">
          <div style={{ padding: 28, textAlign: "center", color: "var(--ink-3)", fontSize: 12 }}>
            Pick a chapter on the left to manage its topics.
          </div>
        </div>
      </div>
    );
  }

  return (
    <div className="card">
      <div className="card-head" style={{ gap: 10 }}>
        <span className="card-title">Topics · Ch {chapter.chapter_number}. {chapter.chapter_name}</span>
        <span className="muted" style={{ fontSize: 11 }}>{items.length}</span>
        <button className="btn sm primary" style={{ marginLeft: "auto" }} onClick={() => setAdding(true)} disabled={adding}>
          <TIcon name="plus" size={11}/> Add topic
        </button>
      </div>
      <div className="card-body" style={{ padding: 0 }}>
        <ErrBanner err={actionErr} onClear={() => setActionErr(null)}/>
        {adding && (
          <TopicEditor onCancel={() => setAdding(false)} onSave={create}
            suggestedNumber={(items[items.length - 1]?.topic_number ?? 0) + 1}/>
        )}
        {loading && <div style={{ padding: 16, color: "var(--ink-3)", fontSize: 12 }}>Loading…</div>}
        <ErrBanner err={err}/>
        {!loading && items.length === 0 && !adding && (
          <div style={{ padding: 28, textAlign: "center", color: "var(--ink-3)", fontSize: 12 }}>
            No topics under this chapter yet.
          </div>
        )}
        {items.map((row) =>
          editingId === row.id
            ? <TopicEditor key={row.id} initial={row} onCancel={() => setEditingId(null)} onSave={(d) => update(row.id, d)}/>
            : <TopicRow key={row.id} row={row} onEdit={() => setEditingId(row.id)} onDelete={() => remove(row)}/>
        )}
      </div>
    </div>
  );
};

const TopicRow = ({ row, onEdit, onDelete }) => (
  <div style={{
    padding: "10px 14px", borderBottom: "1px solid var(--line-soft)",
    display: "grid", gridTemplateColumns: "auto 1fr auto auto", gap: 12, alignItems: "center",
  }}>
    <div className="mono" style={{ color: "var(--accent)", fontSize: 12, minWidth: 26, textAlign: "right" }}>
      {row.topic_number}.
    </div>
    <div>
      <div style={{ color: "var(--ink-0)", fontSize: 13, fontWeight: 500 }}>{row.topic_name}</div>
    </div>
    <button className="btn ghost sm" title="Rename" onClick={onEdit}><TIcon name="edit" size={11}/></button>
    <button className="btn ghost sm" title="Delete" onClick={onDelete} style={{ color: "var(--red)" }}>
      <TIcon name="trash" size={11}/>
    </button>
  </div>
);

const TopicEditor = ({ initial, suggestedNumber, onCancel, onSave }) => {
  const [topicNumber, setTopicNumber] = React.useState(
    String(initial?.topic_number ?? suggestedNumber ?? 1),
  );
  const [topicName, setTopicName] = React.useState(initial?.topic_name || "");
  const [busy, setBusy] = React.useState(false);

  const submit = async () => {
    const n = parseInt(topicNumber, 10);
    if (!Number.isFinite(n) || n < 1) return;
    if (!topicName.trim()) return;
    setBusy(true);
    try {
      await onSave({ topic_number: n, topic_name: topicName.trim() });
    } finally { setBusy(false); }
  };

  return (
    <div style={{ padding: "10px 14px", borderBottom: "1px solid var(--line-soft)", background: "var(--bg-2)" }}>
      <div style={{ display: "grid", gridTemplateColumns: "80px 1fr", gap: 8 }}>
        <div>
          <label className="muted" style={{ fontSize: 10 }}>Number *</label>
          <input className="input" type="number" min="1" value={topicNumber}
            onChange={(e) => setTopicNumber(e.target.value)} style={{ width: "100%" }}/>
        </div>
        <div>
          <label className="muted" style={{ fontSize: 10 }}>Topic name *</label>
          <input className="input" autoFocus value={topicName}
            onChange={(e) => setTopicName(e.target.value)}
            placeholder="e.g. Mole concept" style={{ width: "100%" }}/>
        </div>
      </div>
      <div style={{ display: "flex", justifyContent: "flex-end", gap: 6, marginTop: 8 }}>
        <button className="btn sm ghost" onClick={onCancel} disabled={busy}>Cancel</button>
        <button className="btn sm primary" onClick={submit} disabled={busy || !topicName.trim() || !topicNumber.trim()}>
          {busy ? "Saving…" : initial ? "Save" : "Add topic"}
        </button>
      </div>
    </div>
  );
};

window.TopicsScreen = TopicsScreen;
})();
