/* ==================================================================
   AI Test Review — admin / HoD moderation surface
   ------------------------------------------------------------------
   An AI practice-test generator mints tests in real time on student
   request (the generator lives outside this panel).
   "Approve before student takes" was rejected (latency). Instead the
   student takes immediately; teachers and admins sign off afterwards.

   This screen is the admin counterpart to the Teacher app's
   AiReviewListPage / AiReviewDetailPage. Admins see ALL practice tests
   in the school (the visibility model treats role!=='teacher' as
   privileged) and get two extra controls teachers don't have:
     • Reopen — flip a reviewed test back to 'pending' for fresh review.
     • Delete — wipe a hallucination beyond recovery.
   ================================================================== */

const { Icon: AiIcon } = window.AppUI;

const AI_STATUS_LABEL = { pending: "Pending", reviewed: "Reviewed", needs_revision: "Needs work" };
const AI_STATUS_CLS   = { pending: "amber",   reviewed: "green",   needs_revision: "red"        };

const relTimeAi = (iso) => {
  if (!iso) return "";
  const ms = Date.now() - new Date(iso).getTime();
  const s = Math.floor(ms / 1000);
  if (s < 60)   return `${s}s ago`;
  if (s < 3600) return `${Math.floor(s/60)}m ago`;
  if (s < 86400) return `${Math.floor(s/3600)}h ago`;
  return `${Math.floor(s/86400)}d ago`;
};

const AiReviewScreen = () => {
  const [tab, setTab] = React.useState("pending");
  const [rows, setRows] = React.useState([]);
  const [counts, setCounts] = React.useState({ pending: 0, reviewed: 0, needs_revision: 0 });
  const [search, setSearch] = React.useState("");
  const [subjectFilter, setSubjectFilter] = React.useState("");
  const [selectedId, setSelectedId] = React.useState(null);
  const [loading, setLoading] = React.useState(true);
  const [err, setErr] = React.useState(null);

  const subjects = window.APP?.SUBJECTS || [];

  const refresh = React.useCallback(async () => {
    setLoading(true); setErr(null);
    try {
      const [list, c] = await Promise.all([
        window.AppApi.get(`/teacher/ai-tests?status=${tab}`),
        window.AppApi.get("/teacher/ai-tests/counts"),
      ]);
      setRows(list || []);
      setCounts(c || { pending: 0, reviewed: 0, needs_revision: 0 });
    } catch (e) {
      setErr(String(e.message || e));
    } finally { setLoading(false); }
  }, [tab]);

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

  const filtered = rows.filter((r) => {
    if (subjectFilter && r.subjectCode !== subjectFilter && r.subjectName !== subjectFilter) return false;
    if (!search) return true;
    const q = search.toLowerCase();
    return (
      (r.title || "").toLowerCase().includes(q) ||
      (r.displayId || "").toLowerCase().includes(q) ||
      (r.studentName || "").toLowerCase().includes(q) ||
      (r.studentRoll || "").toLowerCase().includes(q) ||
      (r.subjectName || "").toLowerCase().includes(q)
    );
  });

  const selected = rows.find((r) => r.id === selectedId) || null;

  return (
    <div style={{ display: "grid", gridTemplateColumns: "minmax(380px, 500px) 1fr", height: "100%", overflow: "hidden" }}>
      {/* ─── Left: list ─── */}
      <div style={{ overflow: "auto", padding: "28px 24px", borderRight: "1px solid var(--line)", background: "var(--bg-1)" }}>
        <div className="cx-eyebrow" style={{ marginBottom: 6, display: "flex", alignItems: "center", gap: 6 }}>
          <AiIcon name="sparkle" size={13}/>AI test review
        </div>
        <h1 className="cx-h1">Practice queue</h1>
        <p className="muted" style={{ margin: "6px 0 0", fontSize: 13, lineHeight: 1.5, maxWidth: 480 }}>
          AI-generated practice tests for individual students. Edit any question, sign off when satisfied. Admin / HoD can also reopen or delete a test.
        </p>

        {/* Tabs */}
        <div style={{ marginTop: 18 }}>
          <window.AppUI.Tabs value={tab} full ariaLabel="Review status"
            onChange={(t) => { setTab(t); setSelectedId(null); }}
            items={["pending", "reviewed", "needs_revision"].map((t) => ({ value: t, label: AI_STATUS_LABEL[t], count: counts[t] || 0 }))}/>
        </div>

        {/* Filter bar */}
        <div style={{ display: "flex", gap: 8, marginTop: 12 }}>
          <div className="ui-search" style={{ flex: 1 }}>
            <AiIcon name="search" size={14}/>
            <input className="input" type="text" value={search} onChange={(e) => setSearch(e.target.value)}
              placeholder="Search test, student, ID…" style={{ width: "100%" }}/>
          </div>
          <select className="select" value={subjectFilter} onChange={(e) => setSubjectFilter(e.target.value)}
            style={{ minWidth: 140, width: "auto" }}>
            <option value="">All subjects</option>
            {subjects.map((s) => (
              <option key={s.id} value={s.short_code || s.name}>
                {s.name}
              </option>
            ))}
          </select>
        </div>

        {err && <div className="ui-alert red" style={{ marginTop: 14 }}>{err}</div>}
        {loading && <div className="muted" style={{ marginTop: 16, fontSize: 13 }}>Loading…</div>}

        <div style={{ marginTop: 14, display: "flex", flexDirection: "column", gap: 8 }}>
          {!loading && filtered.length === 0 && (
            <window.AppUI.EmptyState icon={tab === "pending" ? "checkCircle" : "inbox"} compact card
              title={tab === "pending" ? "Inbox zero" : `Nothing ${AI_STATUS_LABEL[tab].toLowerCase()} matches`}
              hint={tab === "pending" ? "No practice tests waiting." : null}/>
          )}
          {filtered.map((r) => {
            const active = r.id === selectedId;
            return (
              <button key={r.id} onClick={() => setSelectedId(r.id)}
                style={{
                  textAlign: "left", padding: "12px 14px", font: "inherit",
                  background: active ? "var(--surface-active)" : "var(--surface)",
                  border: `1px solid ${active ? "var(--line-strong)" : "var(--line)"}`,
                  borderRadius: "var(--radius-tile)", cursor: "pointer", display: "flex", flexDirection: "column", gap: 6,
                }}>
                <div style={{ display: "flex", alignItems: "center", gap: 8 }}>
                  <window.AppUI.StatusBadge tone={AI_STATUS_CLS[r.reviewStatus]}>
                    {AI_STATUS_LABEL[r.reviewStatus]}
                  </window.AppUI.StatusBadge>
                  <span className="ui-id">{r.displayId}</span>
                  <span style={{ color: "var(--ink-3)", fontSize: 11.5, marginLeft: "auto" }}>{relTimeAi(r.createdAt)}</span>
                </div>
                <div style={{ color: "var(--ink-0)", fontSize: 13.5, fontWeight: 600, lineHeight: 1.35 }}>
                  {r.title}
                </div>
                <div className="muted" style={{ fontSize: 12.5 }}>
                  {r.studentName ? <>
                    {r.studentName} <span className="ui-id">{r.studentRoll}</span> · </> : null}
                  {r.subjectCode || r.subjectName} · {r.questionsCount}Q · {r.totalMarks ?? "—"} marks
                  {r.attemptsCount > 0 ? <> · {r.attemptsCount} attempt</> : null}
                </div>
              </button>
            );
          })}
        </div>
      </div>

      {/* ─── Right: detail ─── */}
      {selected ? (
        <AiTestDetail key={selected.id} testId={selected.id} onChanged={refresh} />
      ) : (
        <div style={{ display: "grid", placeItems: "center" }}>
          <window.AppUI.EmptyState icon="sparkle" title="No test selected" hint="Pick a test from the queue to review."/>
        </div>
      )}
    </div>
  );
};

// ─────────────────────────────────────────────────────────────────────────
// AiTestDetail — full editing pane for one test. Each question gets an
// inline editor (text + options + correctness + marks). Saving a single
// question fires a PATCH; the wider Approve / Needs work / Delete / Reopen
// actions live in the sticky header.
// ─────────────────────────────────────────────────────────────────────────

const AiTestDetail = ({ testId, onChanged }) => {
  const [detail, setDetail] = React.useState(null);
  const [loading, setLoading] = React.useState(true);
  const [err, setErr] = React.useState(null);
  const [busy, setBusy] = React.useState(false);

  const reload = React.useCallback(async () => {
    setLoading(true); setErr(null);
    try {
      const d = await window.AppApi.get(`/teacher/ai-tests/${testId}`);
      setDetail(d);
    } catch (e) {
      setErr(String(e.message || e));
    } finally { setLoading(false); }
  }, [testId]);

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

  const decide = async (decision) => {
    setBusy(true);
    try {
      await window.AppApi.post(`/teacher/ai-tests/${testId}/review`, { decision });
      await reload();
      onChanged && onChanged();
    } catch (e) {
      setErr(String(e.message || e));
    } finally { setBusy(false); }
  };

  const reopen = async () => {
    setBusy(true);
    try {
      await window.AppApi.post(`/teacher/ai-tests/${testId}/reopen`, {});
      await reload();
      onChanged && onChanged();
    } catch (e) {
      setErr(String(e.message || e));
    } finally { setBusy(false); }
  };

  const remove = async () => {
    if (!window.confirm("Permanently delete this practice test? Cannot be undone.")) return;
    setBusy(true);
    try {
      await window.AppApi.del(`/teacher/ai-tests/${testId}`);
      onChanged && onChanged();
    } catch (e) {
      setErr(String(e.message || e));
    } finally { setBusy(false); }
  };

  if (loading) {
    return (
      <div style={{ display: "grid", placeItems: "center", color: "var(--ink-3)", fontSize: 13 }}>
        Loading…
      </div>
    );
  }
  if (err) {
    return (
      <div style={{ padding: 28 }}>
        <div className="ui-alert red">{err}</div>
      </div>
    );
  }
  if (!detail) return null;

  const t = detail.test;

  return (
    <div style={{ display: "flex", flexDirection: "column", height: "100%", overflow: "hidden" }}>
      {/* Sticky header */}
      <div style={{ padding: "22px 28px 18px", borderBottom: "1px solid var(--line)", background: "var(--bg-0)" }}>
        <window.AppUI.PageHeader
          eyebrow={<>{t.subjectCode || t.subjectName}{t.classLevel ? <> · Class {t.classLevel}{t.section ? `-${t.section}` : ""}</> : null}</>}
          title={t.title}
          status={<window.AppUI.StatusBadge tone={AI_STATUS_CLS[t.reviewStatus]} variant="outline">{AI_STATUS_LABEL[t.reviewStatus]}</window.AppUI.StatusBadge>}
          meta={[
            <span className="mono">{t.displayId}</span>,
            t.studentName ? <span>For {t.studentName} <span className="ui-id">{t.studentRoll}</span></span> : null,
            `${detail.questions.length} questions · ${t.totalMarks ?? "—"} marks`,
            t.reviewedAt ? `reviewed ${relTimeAi(t.reviewedAt)}` : null,
          ]}
          actions={<>
            <button className="btn danger" onClick={() => decide("needs_revision")} disabled={busy}>
              <AiIcon name="alertCircle" size={15}/>Needs work
            </button>
            <button className="btn primary" onClick={() => decide("reviewed")} disabled={busy}>
              <AiIcon name="check" size={15}/>Approve
            </button>
          </>}
          toolbar={<>
            {t.reviewStatus !== "pending" && (
              <button className="btn" onClick={reopen} disabled={busy}>
                <AiIcon name="refresh" size={15}/>Reopen for re-review
              </button>
            )}
            <button className="btn ghost" onClick={remove} disabled={busy} style={{ color: "var(--red)" }}>
              <AiIcon name="trash" size={15}/>Delete test
            </button>
          </>}
        />
      </div>

      {/* Question list */}
      <div style={{ flex: 1, overflow: "auto", padding: "22px 28px", display: "flex", flexDirection: "column", gap: 16 }}>
        {detail.questions.map((q, i) => (
          <AiQuestionEditor key={q.id} index={i} testId={testId} question={q} onSaved={reload}/>
        ))}
      </div>
    </div>
  );
};

const AiQuestionEditor = ({ index, testId, question, onSaved }) => {
  const isMcq = question.type === "mcq";
  const [text, setText] = React.useState(question.text);
  const [marks, setMarks] = React.useState(question.marks);
  const [expected, setExpected] = React.useState(question.expectedAnswer ?? "");
  const [options, setOptions] = React.useState(() =>
    (question.options || []).map((o) => ({
      letter: o.letter, text: o.text, is_correct: !!o.is_correct,
    }))
  );
  const [busy, setBusy] = React.useState(false);
  const [err, setErr] = React.useState(null);

  // Reset local draft when the parent reloads (after a save / decision).
  React.useEffect(() => {
    setText(question.text);
    setMarks(question.marks);
    setExpected(question.expectedAnswer ?? "");
    setOptions((question.options || []).map((o) => ({
      letter: o.letter, text: o.text, is_correct: !!o.is_correct,
    })));
    setErr(null);
  }, [question]);

  const dirty =
    text !== question.text ||
    marks !== question.marks ||
    expected !== (question.expectedAnswer ?? "") ||
    JSON.stringify(options) !== JSON.stringify(
      (question.options || []).map((o) => ({ letter: o.letter, text: o.text, is_correct: !!o.is_correct }))
    );

  const setOpt = (i, patch) => setOptions((xs) => xs.map((o, j) => (j === i ? { ...o, ...patch } : o)));
  const setCorrect = (i) => setOptions((xs) => xs.map((o, j) => ({ ...o, is_correct: j === i })));

  const save = async () => {
    setBusy(true); setErr(null);
    try {
      const optionsChanged = isMcq && JSON.stringify(options) !== JSON.stringify(
        (question.options || []).map((o) => ({ letter: o.letter, text: o.text, is_correct: !!o.is_correct }))
      );
      if (optionsChanged && options.filter((o) => o.is_correct).length !== 1) {
        throw new Error("exactly one option must be marked correct");
      }
      const patch = {};
      if (text !== question.text) patch.text = text;
      if (marks !== question.marks) patch.marks = marks;
      if (expected !== (question.expectedAnswer ?? "")) patch.expected_answer = expected;
      if (optionsChanged) patch.options = options;
      await window.AppApi.patch(`/teacher/ai-tests/${testId}/questions/${question.id}`, patch);
      onSaved && onSaved();
    } catch (e) {
      setErr(String(e.message || e));
    } finally { setBusy(false); }
  };

  return (
    <div className="cx-card">
      <div className="cx-card-head">
        <div style={{ display: "flex", alignItems: "center", gap: 10 }}>
          <span className="cx-card-title">Question {index + 1}</span>
          <window.AppUI.StatusBadge tone="grey" icon={false}>{String(question.type || "").toUpperCase()}</window.AppUI.StatusBadge>
          {dirty && <window.AppUI.StatusBadge tone="amber" icon="penLine">Unsaved</window.AppUI.StatusBadge>}
        </div>
      </div>

      <AiField label="Question text">
        <textarea className="textarea" value={text} onChange={(e) => setText(e.target.value)} rows={3}
          style={{ width: "100%" }}/>
      </AiField>

      {isMcq && (
        <AiField label="Options · pick the correct one">
          <div style={{ display: "flex", flexDirection: "column", gap: 6 }}>
            {options.map((opt, i) => (
              <div key={i} style={{
                display: "flex", alignItems: "flex-start", gap: 10,
                padding: "8px 10px", borderRadius: "var(--radius-ctl)",
                border: `1px solid ${opt.is_correct ? "color-mix(in srgb, var(--green-solid) 45%, transparent)" : "var(--line)"}`,
                background: opt.is_correct ? "var(--green-bg)" : "var(--surface)",
              }}>
                <button type="button" onClick={() => setCorrect(i)} aria-label={`Mark ${opt.letter} correct`}
                  style={{
                    width: 18, height: 18, borderRadius: 99,
                    border: `2px solid ${opt.is_correct ? "var(--green-solid)" : "var(--ink-4)"}`,
                    background: "transparent", cursor: "pointer", marginTop: 8,
                    display: "grid", placeItems: "center", padding: 0, flexShrink: 0,
                  }}>
                  {opt.is_correct && <span style={{ width: 8, height: 8, borderRadius: 99, background: "var(--green-solid)" }}/>}
                </button>
                <span className="mono" style={{ color: "var(--ink-3)", fontSize: 12.5, marginTop: 8 }}>
                  {opt.letter}
                </span>
                <textarea className="textarea" value={opt.text} onChange={(e) => setOpt(i, { text: e.target.value })} rows={1}
                  style={{ flex: 1, minHeight: 34 }}/>
              </div>
            ))}
          </div>
        </AiField>
      )}

      {!isMcq && (
        <AiField label="Expected answer (with units)">
          <input className="input" value={expected} onChange={(e) => setExpected(e.target.value)}
            style={{ width: "100%" }}
            placeholder="e.g. 17 g/mol"/>
        </AiField>
      )}

      <AiField label="Marks">
        <input className="input" type="number" min={1} max={10} value={marks}
          onChange={(e) => setMarks(Math.max(1, Math.min(10, Math.round(Number(e.target.value) || 1))))}
          style={{ width: 90 }}/>
      </AiField>

      {err && <div className="ui-alert red" style={{ marginTop: 6 }}>{err}</div>}

      <div className="cx-card-foot">
        <button className="btn primary" onClick={save} disabled={!dirty || busy}>
          <AiIcon name="check" size={15}/>Save question
        </button>
      </div>
    </div>
  );
};

const AiField = ({ label, children }) => (
  <label className="field" style={{ display: "block", marginBottom: 14 }}>
    <div className="label" style={{ marginBottom: 6 }}>{label}</div>
    {children}
  </label>
);

window.AiReviewScreen = AiReviewScreen;
