/* ==================================================================
   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.AppUI;

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.AppApi.get("/admin/subjects").then(setSubjects)
      .catch((e) => setSubjectsErr(String(e.message || e)));
  }, []);
  React.useEffect(() => {
    setClassErr(null);
    window.AppApi.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.AppApi.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 className="cx-page" style={{ maxWidth: 1100 }}>
      <window.AppUI.PageHeader
        eyebrow="Admin · catalog"
        title="Topics"
        meta={["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."]}
      />

      <div className="cx-catalog-split" style={{ gap: 20 }}>
        <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 className="ui-alert red" style={{
    margin: "10px 0", display: "flex", justifyContent: "space-between", alignItems: "center", gap: 10,
  }}>
    <span>{err}</span>
    {onClear && <button className="btn ghost xs icon-only" onClick={onClear} aria-label="Dismiss" title="Dismiss"><TIcon name="x" size={13}/></button>}
  </div>
) : null;

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

      <div className="field" style={{ margin: 0 }}>
        <label className="label">Class</label>
        <select className="select" value={pickedClass} onChange={(e) => onPickClass(e.target.value)} style={{ width: "100%" }}>
          <option value="">— pick a class —</option>
          {classLevels.map((cl) => <option key={cl} value={cl}>Class {cl}</option>)}
        </select>
      </div>

      <div className="field" style={{ margin: 0 }}>
        <label className="label">Subject</label>
        <select className="select" value={pickedSubjectId} onChange={(e) => onPickSubject(e.target.value)}
          disabled={!pickedClass} style={{ width: "100%" }}>
          <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 className="field" style={{ margin: 0 }}>
        <label className="label">Chapter</label>
        <select className="select" value={pickedChapterId} onChange={(e) => onPickChapter(e.target.value)}
          disabled={!pickedSubjectId || chapters.length === 0}
          style={{ width: "100%" }}>
          {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.AppApi.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.AppApi.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.AppApi.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.AppApi.del(`/admin/topics/${row.id}`); await refresh(); }
    catch (e) { setActionErr(String(e.message || e)); }
  };

  if (!chapter) {
    return (
      <window.AppUI.Card title="Topics">
        <window.AppUI.EmptyState compact icon="list" title="No chapter selected"
          hint="Pick a chapter on the left to manage its topics."/>
      </window.AppUI.Card>
    );
  }

  return (
    <div className="cx-card flush">
      <div className="cx-card-head" style={{ padding: "18px 20px", margin: 0, borderBottom: "1px solid var(--line)" }}>
        <div style={{ display: "flex", alignItems: "center", gap: 8, minWidth: 0 }}>
          <span className="cx-card-title">Topics · Ch {chapter.chapter_number}. {chapter.chapter_name}</span>
          <span className="ui-tab-count">{items.length}</span>
        </div>
        <button className="btn sm primary" onClick={() => setAdding(true)} disabled={adding}>
          <TIcon name="plus" size={14}/>Add topic
        </button>
      </div>
      <div>
        <div style={{ padding: actionErr || err ? "0 16px" : 0 }}><ErrBanner err={actionErr} onClear={() => setActionErr(null)}/></div>
        {adding && (
          <TopicEditor onCancel={() => setAdding(false)} onSave={create}
            suggestedNumber={(items[items.length - 1]?.topic_number ?? 0) + 1}/>
        )}
        {loading && <div style={{ padding: "16px 20px", color: "var(--ink-3)", fontSize: 13 }}>Loading…</div>}
        <div style={{ padding: err ? "0 16px" : 0 }}><ErrBanner err={err}/></div>
        {!loading && items.length === 0 && !adding && (
          <window.AppUI.EmptyState compact icon="list" title="No topics yet" hint="No topics under this chapter yet."/>
        )}
        {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 className="ui-row" style={{ padding: "12px 20px", gap: 12 }}>
    <div className="tabular" style={{ color: "var(--accent)", fontSize: 13, fontWeight: 600, minWidth: 28, textAlign: "right" }}>
      {row.topic_number}.
    </div>
    <div className="ui-row-main">
      <div className="ui-row-title">{row.topic_name}</div>
    </div>
    <window.AppUI.IconButton icon="edit" label="Rename" size={15} className="sm" onClick={onEdit}/>
    <window.AppUI.IconButton icon="trash" label="Delete" size={15} className="sm" onClick={onDelete} style={{ color: "var(--red)" }}/>
  </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: "16px 20px", borderBottom: "1px solid var(--line)", background: "var(--surface-hover)" }}>
      <div style={{ display: "grid", gridTemplateColumns: "80px minmax(0, 1fr)", gap: 10 }}>
        <div className="field" style={{ margin: 0 }}>
          <label className="label">Number *</label>
          <input className="input" type="number" min="1" value={topicNumber}
            onChange={(e) => setTopicNumber(e.target.value)} style={{ width: "100%" }}/>
        </div>
        <div className="field" style={{ margin: 0 }}>
          <label className="label">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: 12 }}>
        <button className="btn sm" 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;
})();
