/* ==================================================================
   Admin → Teachers
   ------------------------------------------------------------------
   The cockpit is the admin panel. Teachers themselves use the mobile
   app. This screen lets the admin add a teacher, assign them to a
   set of (class × subject) pairs (controls which tests they can
   author + grade on mobile), reset passwords, and deactivate (which
   immediately revokes any live mobile session).
   ================================================================== */

const { Icon: AdIcon } = window.KXUI;

const ROLE_LABEL = { admin: "Admin", hod: "HoD", teacher: "Teacher", coordinator: "Coordinator", boarder: "Boarder", support_staff: "Support Staff" };

const TeachersScreen = () => {
  const [teachers, setTeachers] = React.useState([]);
  const [loading, setLoading] = React.useState(true);
  const [err, setErr] = React.useState(null);
  const [selectedId, setSelectedId] = React.useState(null);
  const [addOpen, setAddOpen] = React.useState(false);
  const [credentialFlash, setCredentialFlash] = React.useState(null); // { username, temp_password }
  const [search, setSearch] = React.useState("");
  const [resets, setResets] = React.useState([]);          // pending password-reset requests
  const [actBusy, setActBusy] = React.useState(null);      // id currently being approved/rejected

  const refresh = React.useCallback(async () => {
    setLoading(true); setErr(null);
    try {
      const [t, pr] = await Promise.all([
        window.KXApi.get("/admin/teachers"),
        window.KXApi.get("/password-resets?status=pending").catch(() => []),
      ]);
      setTeachers(t); setResets(pr || []);
    }
    catch (e) { setErr(String(e.message || e)); }
    finally { setLoading(false); }
  }, []);

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

  // Self-registered teachers awaiting approval are surfaced in a dedicated card
  // above the roster (and kept OUT of the main list until activated).
  const pendingUsers = teachers.filter(t => t.status === "pending");
  const activeUsers  = teachers.filter(t => t.status !== "pending");

  const approveTeacher = async (id) => {
    setActBusy(id);
    try { await window.KXApi.post(`/admin/teachers/${id}/approve`, {}); await refresh(); }
    catch (e) { setErr(String(e.message || e)); }
    finally { setActBusy(null); }
  };
  const rejectTeacher = async (id, name) => {
    if (!window.confirm(`Reject and delete the registration for ${name || "this teacher"}?`)) return;
    setActBusy(id);
    try { await window.KXApi.post(`/admin/teachers/${id}/reject`, {}); if (selectedId === id) setSelectedId(null); await refresh(); }
    catch (e) { setErr(String(e.message || e)); }
    finally { setActBusy(null); }
  };
  const decideReset = async (id, kind) => {
    setActBusy(id);
    try { await window.KXApi.post(`/password-resets/${id}/${kind}`, {}); await refresh(); }
    catch (e) { setErr(String(e.message || e)); }
    finally { setActBusy(null); }
  };

  const filtered = activeUsers.filter(t => {
    if (!search) return true;
    const q = search.toLowerCase();
    return (t.name || "").toLowerCase().includes(q)
        || (t.email || "").toLowerCase().includes(q)
        || (t.username || "").toLowerCase().includes(q);
  });

  const selected = selectedId ? teachers.find(t => t.id === selectedId) : null;

  return (
    <div className={`cx-roster-split${selected ? " has-detail" : ""}`}>
      <div style={{ padding: "24px 28px", minWidth: 0 }}>
        <div style={{ display: "flex", alignItems: "center", gap: 12, marginBottom: 4 }}>
          <span style={{ color: "var(--accent)" }}><AdIcon name="cohort" size={18}/></span>
          <div className="muted" style={{ fontSize: 11, letterSpacing: ".08em", textTransform: "uppercase" }}>Admin · Access Control</div>
        </div>
        <h1 style={{ margin: "4px 0 6px", color: "var(--ink-0)", fontFamily: "'Instrument Serif', serif", fontWeight: 400, fontSize: 32, letterSpacing: "-0.01em" }}>
          Teachers
        </h1>
        <p className="muted" style={{ margin: 0, fontSize: 13.5, maxWidth: 640 }}>
          Each teacher logs in to the mobile app and only sees tests for the (class × subject) pairs you assign here. Deactivating a teacher revokes their open sessions immediately.
        </p>

        {credentialFlash && (
          <div style={{
            marginTop: 16, padding: "12px 16px", background: "rgba(75, 201, 123, 0.08)",
            border: "1px solid var(--green)", borderRadius: 8, color: "var(--ink-0)", fontSize: 13,
          }}>
            <div style={{ display: "flex", justifyContent: "space-between", alignItems: "flex-start", gap: 12 }}>
              <div>
                <div style={{ fontWeight: 600, marginBottom: 4 }}>Credentials issued — copy now, won't be shown again</div>
                <div className="mono" style={{ fontSize: 13 }}>
                  Username: <b>{credentialFlash.username}</b>
                  &nbsp;&nbsp;·&nbsp;&nbsp;
                  Password: <b>{credentialFlash.temp_password}</b>
                </div>
              </div>
              <button className="btn ghost sm" onClick={() => setCredentialFlash(null)}><AdIcon name="x" size={12}/></button>
            </div>
          </div>
        )}

        {pendingUsers.length > 0 && (
          <div className="card" style={{ marginTop: 18, borderColor: "var(--amber)" }}>
            <div className="card-head" style={{ gap: 10 }}>
              <span className="card-title" style={{ color: "var(--amber)" }}>
                {pendingUsers.length} pending approval{pendingUsers.length === 1 ? "" : "s"}
              </span>
              <span className="muted" style={{ fontSize: 11, marginLeft: "auto" }}>Self-registered from the mobile app</span>
            </div>
            <div className="card-body" style={{ padding: 0 }}>
              {pendingUsers.map(t => (
                <div key={t.id} className="cx-tchqueue" style={{
                  padding: "12px 16px", borderBottom: "1px solid var(--line-soft)",
                  gap: 12, alignItems: "center",
                }}>
                  <div style={{ cursor: "pointer" }} onClick={() => setSelectedId(t.id)}>
                    <div style={{ color: "var(--ink-0)", fontSize: 13, fontWeight: 500 }}>
                      {t.name}
                      {t.boarding && <span style={{ marginLeft: 8, fontSize: 10, color: "var(--accent)", padding: "1px 6px", border: "1px solid var(--accent)", borderRadius: 4 }}>BOARDING</span>}
                    </div>
                    <div className="muted" style={{ fontSize: 11, marginTop: 2 }}>{t.email} · {t.phone || "no phone"}</div>
                  </div>
                  <div style={{ fontSize: 11, color: "var(--ink-2)" }}>{ROLE_LABEL[t.role] || t.role}</div>
                  <div className="muted" style={{ fontSize: 11 }}>{t.assignment_count} {t.assignment_count === 1 ? "scope" : "scopes"}</div>
                  <div style={{ display: "flex", gap: 6, justifyContent: "flex-end" }}>
                    <button className="btn sm primary" disabled={actBusy === t.id} onClick={() => approveTeacher(t.id)}>Approve</button>
                    <button className="btn sm ghost" style={{ color: "var(--red)", borderColor: "var(--red)" }} disabled={actBusy === t.id} onClick={() => rejectTeacher(t.id, t.name)}>Reject</button>
                  </div>
                </div>
              ))}
            </div>
          </div>
        )}

        {resets.length > 0 && (
          <div className="card" style={{ marginTop: 18 }}>
            <div className="card-head" style={{ gap: 10 }}>
              <span className="card-title">{resets.length} password reset request{resets.length === 1 ? "" : "s"}</span>
              <span className="muted" style={{ fontSize: 11, marginLeft: "auto" }}>Approving renews the password &amp; signs them out</span>
            </div>
            <div className="card-body" style={{ padding: 0 }}>
              {resets.map(r => (
                <div key={r.id} className="cx-tchqueue reset" style={{
                  padding: "12px 16px", borderBottom: "1px solid var(--line-soft)",
                  gap: 12, alignItems: "center",
                }}>
                  <div>
                    <div style={{ color: "var(--ink-0)", fontSize: 13, fontWeight: 500 }}>{r.teacher.name}</div>
                    <div className="muted" style={{ fontSize: 11, marginTop: 2 }}>{r.teacher.phone || r.teacher.email}</div>
                  </div>
                  <div style={{ fontSize: 11, color: "var(--ink-2)" }}>{ROLE_LABEL[r.teacher.role] || r.teacher.role}</div>
                  <div style={{ display: "flex", gap: 6, justifyContent: "flex-end" }}>
                    <button className="btn sm primary" disabled={actBusy === r.id} onClick={() => decideReset(r.id, "approve")}>Approve</button>
                    <button className="btn sm ghost" style={{ color: "var(--red)", borderColor: "var(--red)" }} disabled={actBusy === r.id} onClick={() => decideReset(r.id, "reject")}>Reject</button>
                  </div>
                </div>
              ))}
            </div>
          </div>
        )}

        <div className="card" style={{ marginTop: 18 }}>
          <div className="card-head" style={{ gap: 10 }}>
            <span className="card-title">{activeUsers.length} {activeUsers.length === 1 ? "user" : "users"}</span>
            <div style={{ position: "relative", flex: 1, marginLeft: 12 }}>
              <span style={{ position: "absolute", left: 10, top: "50%", transform: "translateY(-50%)", color: "var(--ink-3)" }}>
                <AdIcon name="search" size={12}/>
              </span>
              <input className="input" placeholder="Search name, email, username…" value={search} onChange={e => setSearch(e.target.value)}
                style={{ paddingLeft: 28, padding: "5px 10px 5px 28px", fontSize: 12.5, width: "100%", background: "var(--bg-2)" }}/>
            </div>
            <button className="btn sm primary" onClick={() => setAddOpen(true)}>
              <AdIcon name="plus" size={11}/> Add teacher
            </button>
          </div>

          <div className="card-body" style={{ padding: 0 }}>
            {loading && <div style={{ padding: 28, color: "var(--ink-3)", fontSize: 12 }}>Loading…</div>}
            {err && <div style={{ padding: 18, color: "var(--red)", fontSize: 12 }}>{err}</div>}
            {!loading && filtered.length === 0 && (
              <div style={{ padding: 36, textAlign: "center", color: "var(--ink-3)", fontSize: 13 }}>
                {teachers.length === 0 ? "No teachers yet. Click Add teacher to create one." : "No matches."}
              </div>
            )}

            {filtered.map(t => (
              <div key={t.id}
                onClick={() => setSelectedId(t.id)}
                onMouseEnter={e => e.currentTarget.style.background = "var(--bg-2)"}
                onMouseLeave={e => e.currentTarget.style.background = selectedId === t.id ? "var(--bg-2)" : "transparent"}
                className="cx-tchrow"
                style={{
                  padding: "12px 16px",
                  borderBottom: "1px solid var(--line-soft)",
                  gap: 12, alignItems: "center", cursor: "pointer",
                  background: selectedId === t.id ? "var(--bg-2)" : "transparent",
                }}>
                <div>
                  <div style={{ color: "var(--ink-0)", fontSize: 13, fontWeight: 500 }}>
                    {t.name}
                    {!t.active && <span style={{ marginLeft: 8, fontSize: 10, color: "var(--ink-3)", padding: "1px 6px", border: "1px solid var(--line)", borderRadius: 4 }}>DISABLED</span>}
                    {t.must_reset && t.active && <span style={{ marginLeft: 8, fontSize: 10, color: "var(--amber)", padding: "1px 6px", border: "1px solid var(--amber)", borderRadius: 4 }}>RESET PENDING</span>}
                  </div>
                  <div className="muted" style={{ fontSize: 11, marginTop: 2 }}>{t.email}</div>
                </div>
                <div className="mono muted" style={{ fontSize: 11 }}>{t.username || "—"}</div>
                <div style={{ fontSize: 11, color: t.role === "admin" ? "var(--accent)" : "var(--ink-2)" }}>{ROLE_LABEL[t.role] || t.role}</div>
                <div className="muted" style={{ fontSize: 11 }}>
                  {t.assignment_count} {t.assignment_count === 1 ? "scope" : "scopes"}
                </div>
                <div className="muted" style={{ fontSize: 11, textAlign: "right" }}>
                  {t.active_sessions > 0 ? <span style={{ color: "var(--green)" }}>● live</span> : "—"}
                </div>
              </div>
            ))}
          </div>
        </div>
      </div>

      {selected && (
        <TeacherDetail
          key={selected.id}
          teacherSummary={selected}
          onClose={() => setSelectedId(null)}
          onChanged={async (flashCreds) => { if (flashCreds) setCredentialFlash(flashCreds); await refresh(); }}
        />
      )}

      <AddTeacherModal
        open={addOpen}
        onClose={() => setAddOpen(false)}
        onCreated={async (creds) => { setAddOpen(false); setCredentialFlash(creds); await refresh(); setSelectedId(creds.id); }}
      />
    </div>
  );
};

/* ---------- Right-hand detail panel ---------- */
const TeacherDetail = ({ teacherSummary, onClose, onChanged }) => {
  const [full, setFull] = React.useState(null);
  const [classSections, setClassSections] = React.useState([]);
  const [subjects, setSubjects] = React.useState([]);
  const [loading, setLoading] = React.useState(true);
  const [busy, setBusy] = React.useState(false);
  const [err, setErr] = React.useState(null);

  React.useEffect(() => {
    let cancelled = false;
    (async () => {
      setLoading(true);
      try {
        const [t, cs, sb] = await Promise.all([
          window.KXApi.get(`/admin/teachers/${teacherSummary.id}`),
          window.KXApi.get("/admin/class-sections"),
          window.KXApi.get("/admin/subjects"),
        ]);
        if (cancelled) return;
        setFull(t); setClassSections(cs); setSubjects(sb);
      } catch (e) { if (!cancelled) setErr(String(e.message || e)); }
      finally { if (!cancelled) setLoading(false); }
    })();
    return () => { cancelled = true; };
  }, [teacherSummary.id]);

  // selected set, keyed "class_section_id::subject_id"
  const [selected, setSelected] = React.useState(new Set());
  React.useEffect(() => {
    if (full) setSelected(new Set(full.assignments.map(a => `${a.class_section_id}::${a.subject_id}`)));
  }, [full]);

  const toggle = (csId, sbId) => {
    const key = `${csId}::${sbId}`;
    setSelected(prev => {
      const next = new Set(prev);
      if (next.has(key)) next.delete(key); else next.add(key);
      return next;
    });
  };

  const saveAssignments = async () => {
    setBusy(true); setErr(null);
    try {
      const assignments = Array.from(selected).map(k => {
        const [class_section_id, subject_id] = k.split("::");
        return { class_section_id, subject_id };
      });
      await window.KXApi.put(`/admin/teachers/${teacherSummary.id}/assignments`, { assignments });
      await onChanged();
    } catch (e) { setErr(String(e.message || e)); }
    finally { setBusy(false); }
  };

  const patch = async (body) => {
    setBusy(true); setErr(null);
    try {
      await window.KXApi.patch(`/admin/teachers/${teacherSummary.id}`, body);
      await onChanged();
    } catch (e) { setErr(String(e.message || e)); }
    finally { setBusy(false); }
  };

  const resetPassword = async () => {
    if (!window.confirm("Generate a new temporary password? Existing mobile sessions will be revoked.")) return;
    setBusy(true); setErr(null);
    try {
      const out = await window.KXApi.post(`/admin/teachers/${teacherSummary.id}/reset-password`, {});
      await onChanged({ id: teacherSummary.id, username: out.username, temp_password: out.temp_password });
    } catch (e) { setErr(String(e.message || e)); }
    finally { setBusy(false); }
  };

  const removeTeacher = async () => {
    if (!window.confirm(
      `Remove ${teacherSummary.name}?\n\n` +
      `If they've never authored a test, review, or rubric, the account is deleted outright. ` +
      `Otherwise it's deactivated and the login is dropped — past work they own is preserved.`
    )) return;
    setBusy(true); setErr(null);
    try {
      const out = await window.KXApi.del(`/admin/teachers/${teacherSummary.id}`);

      // Soft-delete branch: backend tells us what's blocking. If the only
      // blocker is the teacher's own tests/submissions, offer a second
      // confirm that escalates to ?cascade=tests and nukes the lot.
      if (out && out.removed === "soft") {
        const b = out.blocked_by || {};
        const testsCreated = Number(b.tests_created || 0);
        const subs         = Number(b.submissions   || 0);
        const otherReviews = Number(b.reviews       || 0);
        const offersCascade = testsCreated > 0;

        if (offersCascade && window.confirm(
          `${teacherSummary.name} authored ${testsCreated} test${testsCreated === 1 ? "" : "s"} ` +
          `with ${subs} student submission${subs === 1 ? "" : "s"}.\n\n` +
          `Delete the teacher's tests AND every submission underneath them, then remove ` +
          `the account?\n\nThis can't be undone.`
        )) {
          const cascade = await window.KXApi.del(`/admin/teachers/${teacherSummary.id}?cascade=tests`);
          await onChanged();
          onClose();
          if (cascade?.removed === "hard") {
            window.alert(
              `Removed ${teacherSummary.name}. ` +
              `Cleared ${cascade.cascaded?.tests ?? 0} test(s) and ` +
              `${cascade.cascaded?.submissions ?? 0} submission(s).`,
            );
          } else {
            // Still soft — they had reviews on OTHER teachers' work that
            // we won't touch (NOT NULL teacher_id, audit-trail material).
            window.alert(
              `${teacherSummary.name} also has ${cascade?.blocked_by?.reviews ?? otherReviews} ` +
              `review${(cascade?.blocked_by?.reviews ?? otherReviews) === 1 ? "" : "s"} on ` +
              `other teachers' work. The account was deactivated (login removed) but the ` +
              `user row stays as a tombstone so those reviews keep their author.`,
            );
          }
          return;
        }

        await onChanged();
        onClose();
        window.alert(
          `${teacherSummary.name} has work that's still referenced ` +
          `(${testsCreated} test(s), ${otherReviews} review(s) on others, etc.), so the ` +
          `account was deactivated instead of fully removed. Their login is gone and ` +
          `they can no longer sign in.`,
        );
        return;
      }

      // Hard delete on the first call — row just vanishes after refresh.
      await onChanged();
      onClose();
    } catch (e) { setErr(String(e.message || e)); setBusy(false); }
  };

  // Same reasoning as the student roster: while the pane is a bottom sheet the
  // 28-row teacher list behind it must not scroll, or a drag inside the sheet
  // moves the page underneath and the sheet appears to drift.
  useEffect(() => {
    const sheet = window.matchMedia("(max-width: 1000px)");
    if (!sheet.matches) return;
    const prev = document.body.style.overflow;
    document.body.style.overflow = "hidden";
    const onKey = (e) => { if (e.key === "Escape") onClose(); };
    window.addEventListener("keydown", onKey);
    return () => {
      document.body.style.overflow = prev;
      window.removeEventListener("keydown", onKey);
    };
  }, [onClose]);

  return (
    <>
    <div className="cx-roster-scrim" onClick={onClose} aria-hidden="true"/>
    <aside className="cx-roster-detail">
      <div className="cx-sheet-grip" aria-hidden="true"/>
      <div className="cx-roster-detail-head" style={{ padding: "16px 20px", borderBottom: "1px solid var(--line)", display: "flex", alignItems: "center", gap: 10 }}>
        <div style={{ flex: 1 }}>
          <div style={{ color: "var(--ink-0)", fontSize: 14, fontWeight: 500 }}>{teacherSummary.name}</div>
          <div className="muted" style={{ fontSize: 11, marginTop: 2 }}>{teacherSummary.email}</div>
        </div>
        <button className="btn ghost sm" onClick={onClose}><AdIcon name="x" size={13}/></button>
      </div>

      {err && <div style={{ margin: "10px 20px", padding: 10, background: "rgba(255,107,107,0.08)", border: "1px solid var(--red)", borderRadius: 6, color: "var(--red)", fontSize: 12 }}>{err}</div>}

      {loading && <div style={{ padding: 28, color: "var(--ink-3)", fontSize: 12 }}>Loading…</div>}

      {!loading && full && (
        <>
          {/* Account block */}
          <section style={{ padding: "14px 20px", borderBottom: "1px solid var(--line)" }}>
            <div className="muted" style={{ fontSize: 10, letterSpacing: ".08em", textTransform: "uppercase", marginBottom: 8 }}>Account</div>
            <EditableRow label="Name" value={full.name} onSave={v => patch({ name: v })} disabled={busy}/>
            <EditableRow label="Email" value={full.email} onSave={v => patch({ email: v })} disabled={busy}/>
            <RoleRow value={full.role} onSave={v => patch({ role: v })} disabled={busy}/>
            <Row label="Username">
              <span className="mono" style={{ fontSize: 12, color: "var(--ink-1)" }}>{full.username || "—"}</span>
            </Row>
            {/* This number receives the sign-in code, so it's the one field
                that decides whether this person can get into the app at all. */}
            <EditableRow
              label="Phone" mono allowEmpty
              value={full.phone}
              placeholder="10-digit mobile"
              hint="Receives the sign-in code. Saved as +91…; leaving it blank disables code sign-in for this person."
              onSave={v => patch({ phone: v })}
              disabled={busy}/>
            <Row label="Boarding">
              <span style={{ fontSize: 12, color: full.boarding ? "var(--accent)" : "var(--ink-2)" }}>{full.boarding ? "Yes" : "No"}</span>
            </Row>
            <Row label="Login">
              <label style={{ display: "inline-flex", alignItems: "center", gap: 6, cursor: "pointer", fontSize: 12 }}>
                <input type="checkbox" checked={full.active} disabled={busy}
                  onChange={e => patch({ active: e.target.checked })}/>
                <span>{full.active ? "Active" : "Disabled"}</span>
              </label>
            </Row>
            <div style={{ display: "flex", gap: 6, marginTop: 10 }}>
              <button className="btn sm" disabled={busy || !full.username} onClick={resetPassword}>Reset password</button>
              <button className="btn sm ghost" style={{ color: "var(--red)", borderColor: "var(--red)" }} disabled={busy} onClick={removeTeacher}>Remove</button>
            </div>
          </section>

          {/* Assignments matrix */}
          <section style={{ padding: "14px 20px" }}>
            <div className="muted" style={{ fontSize: 10, letterSpacing: ".08em", textTransform: "uppercase", marginBottom: 4 }}>Question-authoring scope</div>
            <p className="muted" style={{ fontSize: 11.5, margin: "0 0 12px" }}>
              Tick every (class × subject) this teacher can create tests for and grade. Mobile login filters tests by this matrix.
              {full.role === "admin" && <span style={{ color: "var(--accent)", display: "block", marginTop: 4 }}>Admins bypass scope and see every test.</span>}
            </p>
            {classSections.length === 0 && (
              <div className="cx-emptycard" style={{ padding: "24px 20px" }}>
                No class sections in this school yet. Add one (via the database / a future Classes screen) before assigning.
              </div>
            )}
            {classSections.length > 0 && subjects.length > 0 && (
              <div className="cx-tablecard cx-tablescroll">
                <table className="cx-table compact">
                  <thead>
                    <tr style={{ background: "var(--bg-2)" }}>
                      <th style={{ padding: "6px 10px", textAlign: "left", color: "var(--ink-2)", fontWeight: 500, position: "sticky", left: 0, background: "var(--bg-2)" }}>Class</th>
                      {subjects.map(s => (
                        <th key={s.id} style={{ padding: "6px 8px", color: "var(--ink-2)", fontWeight: 500, whiteSpace: "nowrap" }}>{s.name}</th>
                      ))}
                    </tr>
                  </thead>
                  <tbody>
                    {classSections.map(cs => (
                      <tr key={cs.id} style={{ borderTop: "1px solid var(--line-soft)" }}>
                        <td style={{ padding: "6px 10px", color: "var(--ink-1)", whiteSpace: "nowrap", position: "sticky", left: 0, background: "var(--bg-1)" }}>
                          {cs.label} <span className="muted" style={{ fontSize: 10 }}>{cs.academic_year}</span>
                        </td>
                        {subjects.map(s => {
                          const key = `${cs.id}::${s.id}`;
                          return (
                            <td key={s.id} style={{ padding: "6px 8px", textAlign: "center" }}>
                              <input type="checkbox"
                                checked={selected.has(key)}
                                onChange={() => toggle(cs.id, s.id)}/>
                            </td>
                          );
                        })}
                      </tr>
                    ))}
                  </tbody>
                </table>
              </div>
            )}
            <div style={{ display: "flex", justifyContent: "flex-end", marginTop: 12 }}>
              <button className="btn sm primary" disabled={busy} onClick={saveAssignments}>
                {busy ? "Saving…" : "Save scope"}
              </button>
            </div>
          </section>
        </>
      )}
    </aside>
    </>
  );
};

/* ---------- Add-teacher modal ---------- */
const AddTeacherModal = ({ open, onClose, onCreated }) => {
  const [name, setName] = React.useState("");
  const [email, setEmail] = React.useState("");
  const [role, setRole] = React.useState("teacher");
  const [password, setPassword] = React.useState("");
  const [busy, setBusy] = React.useState(false);
  const [err, setErr] = React.useState(null);

  React.useEffect(() => {
    if (!open) { setName(""); setEmail(""); setRole("teacher"); setPassword(""); setErr(null); }
  }, [open]);

  if (!open) return null;

  const submit = async (e) => {
    e?.preventDefault();
    if (!name.trim() || !email.trim()) return;
    setBusy(true); setErr(null);
    try {
      const body = { name: name.trim(), email: email.trim(), role };
      if (password.trim()) body.password = password.trim();
      const out = await window.KXApi.post("/admin/teachers", body);
      onCreated(out);
    } catch (e) { setErr(String(e.message || e)); }
    finally { setBusy(false); }
  };

  return (
    <div onClick={onClose} style={{ position: "fixed", inset: 0, background: "rgba(0,0,0,0.7)", zIndex: 200, display: "grid", placeItems: "center", padding: 40 }}>
      <form onClick={e => e.stopPropagation()} onSubmit={submit}
        style={{ background: "var(--bg-1)", border: "1px solid var(--line-strong)", borderRadius: 10, width: 480, maxWidth: "100%" }}>
        <div className="card-head">
          <AdIcon name="plus" size={13}/>
          <span className="card-title">Add teacher</span>
          <button type="button" className="btn ghost sm" style={{ marginLeft: "auto" }} onClick={onClose}><AdIcon name="x" size={13}/></button>
        </div>
        <div style={{ padding: 18 }}>
          {/* Both name and email are required (email is the unique key on
              the users table and seeds the username). Mark them with * so
              the disabled Create button isn't a mystery. */}
          <label style={{ display: "block", color: "var(--ink-2)", fontSize: 11, marginBottom: 4 }}>
            Full name <span style={{ color: "var(--red)" }}>*</span>
          </label>
          <input className="input" autoFocus value={name} onChange={e => setName(e.target.value)} style={{ width: "100%" }}/>

          <label style={{ display: "block", color: "var(--ink-2)", fontSize: 11, margin: "10px 0 4px" }}>
            Email <span style={{ color: "var(--red)" }}>*</span>
          </label>
          <input className="input" type="email" value={email} onChange={e => setEmail(e.target.value)}
            placeholder="teacher@school.edu" style={{ width: "100%" }}/>
          <div className="muted" style={{ fontSize: 11, marginTop: 4 }}>
            Required — becomes the unique account id and the source of the username.
          </div>

          <label style={{ display: "block", color: "var(--ink-2)", fontSize: 11, margin: "10px 0 4px" }}>Role</label>
          <div style={{ display: "flex", gap: 6 }}>
            {["teacher","hod","coordinator","support_staff","boarder","admin"].map(r => (
              <button type="button" key={r} className={`btn ${role === r ? "primary" : ""}`}
                onClick={() => setRole(r)} style={{ flex: 1, justifyContent: "center" }}>
                {ROLE_LABEL[r]}
              </button>
            ))}
          </div>

          <label style={{ display: "block", color: "var(--ink-2)", fontSize: 11, margin: "10px 0 4px" }}>Password (leave blank to auto-generate)</label>
          <input className="input" value={password} onChange={e => setPassword(e.target.value)}
            placeholder="random 8-char password" style={{ width: "100%" }}/>

          <p className="muted" style={{ fontSize: 11, marginTop: 10 }}>
            Username is derived from the email local-part. You'll see the credentials once after creation — copy them then.
          </p>

          {err && <div style={{ color: "var(--red)", fontSize: 12, marginTop: 10 }}>{err}</div>}

          {/* Surface why the button is greyed out so the admin doesn't tap
              into a wall. Reads "Add an email…" or "Add a name…" depending
              on what's missing. */}
          {(!name.trim() || !email.trim()) && !err && (
            <div className="muted" style={{ fontSize: 11, marginTop: 10, color: "var(--amber)" }}>
              {!name.trim() && !email.trim()
                ? "Add a name and email to enable Create."
                : !name.trim() ? "Add a name to enable Create."
                : "Add an email to enable Create."}
            </div>
          )}

          <div style={{ display: "flex", justifyContent: "flex-end", gap: 8, marginTop: 16 }}>
            <button type="button" className="btn ghost" onClick={onClose} disabled={busy}>Cancel</button>
            <button type="submit" className="btn primary" disabled={busy || !name.trim() || !email.trim()}>
              {busy ? "Creating…" : "Create teacher"}
            </button>
          </div>
        </div>
      </form>
    </div>
  );
};

/* ---------- tiny editable row helpers ---------- */
const Row = ({ label, children }) => (
  <div style={{ display: "grid", gridTemplateColumns: "90px 1fr", gap: 10, alignItems: "center", padding: "4px 0", fontSize: 12 }}>
    <span className="muted" style={{ fontSize: 11 }}>{label}</span>
    <div>{children}</div>
  </div>
);

// `allowEmpty` lets a field be cleared (phone uses it — an admin has to be able
// to remove a wrong number). `hint` renders under the input; the phone row uses
// it to warn that clearing the number removes code sign-in. `mono` matches the
// read-only phone styling this replaced.
const EditableRow = ({ label, value, onSave, disabled, allowEmpty, hint, mono, placeholder }) => {
  const [editing, setEditing] = React.useState(false);
  const [draft, setDraft] = React.useState(value || "");
  React.useEffect(() => setDraft(value || ""), [value]);
  if (!editing) {
    return (
      <Row label={label}>
        <div style={{ display: "flex", alignItems: "center", gap: 6 }}>
          <span className={mono ? "mono" : undefined}
            style={{ color: "var(--ink-1)", fontSize: mono ? 12 : undefined }}>{value || "—"}</span>
          <button className="btn ghost sm" disabled={disabled} onClick={() => setEditing(true)}>
            <AdIcon name="edit" size={11}/>
          </button>
        </div>
      </Row>
    );
  }
  const trimmed = draft.trim();
  const unchanged = trimmed === (value || "");
  const canSave = !disabled && !unchanged && (allowEmpty || !!trimmed);
  return (
    <Row label={label}>
      <div style={{ flex: 1 }}>
        <div style={{ display: "flex", gap: 6 }}>
          <input className="input" value={draft} placeholder={placeholder || ""}
            onChange={e => setDraft(e.target.value)} style={{ flex: 1 }}/>
          <button className="btn sm primary" disabled={!canSave}
            onClick={() => { onSave(trimmed); setEditing(false); }}>Save</button>
          <button className="btn sm ghost" onClick={() => { setDraft(value || ""); setEditing(false); }}>Cancel</button>
        </div>
        {hint && <div className="muted" style={{ fontSize: 11, marginTop: 4 }}>{hint}</div>}
      </div>
    </Row>
  );
};

const RoleRow = ({ value, onSave, disabled }) => (
  <Row label="Role">
    <select className="input" value={value} disabled={disabled}
      onChange={e => onSave(e.target.value)}
      style={{ padding: "4px 8px", fontSize: 12 }}>
      <option value="teacher">Teacher</option>
      <option value="hod">HoD</option>
      <option value="coordinator">Coordinator</option>
      <option value="support_staff">Support Staff</option>
      <option value="boarder">Boarder</option>
      <option value="admin">Admin</option>
    </select>
  </Row>
);

window.TeachersScreen = TeachersScreen;
