// Admin panels that used to live in features-more.jsx: courses/content,
// centres, certificates, institutions, audit, inquiries, settings, quizzes,
// users, roles, parents and enrollments.

// ── Admin: Courses & Content ──────────────────────────────────────────────────
const COURSE_COLORS = ["var(--coral)","var(--sky)","var(--moss)","var(--plum)","var(--gold)"];

// ── Course Edit Panel ─────────────────────────────────────────────────────────
const FILE_ICONS = { pdf:"📄", txt:"📝", ppt:"📊", pptx:"📊" };
const PERM_LIST = [
  { key:"manage_students",     label:"Manage Students" },
  { key:"manage_teachers",     label:"Manage Teachers" },
  { key:"manage_batches",      label:"Manage Batches" },
  { key:"manage_courses",      label:"Manage Courses" },
  { key:"manage_schedule",     label:"Manage Schedule" },
  { key:"manage_billing",      label:"Manage Billing" },
  { key:"manage_quizzes",      label:"Manage Quizzes" },
  { key:"manage_homework",     label:"Manage Homework" },
  { key:"view_analytics",      label:"View Analytics" },
  { key:"manage_users",        label:"Manage Users" },
  { key:"broadcast",           label:"Broadcast" },
  { key:"manage_kits",         label:"Manage Kits" },
  { key:"manage_certificates", label:"Manage Certificates" },
  { key:"manage_roles",        label:"Manage Roles (super only)" },
  { key:"upload_content",      label:"Upload Course Content" },
  { key:"view_courses",        label:"View Courses (student)" },
  { key:"take_quiz",           label:"Take Quizzes (student)" },
  { key:"submit_homework",     label:"Submit Homework (student)" },
  { key:"view_dashboard",      label:"View Dashboard (parent)" },
];

const getCourseRole = () => (typeof currentRole === "function" ? currentRole() || "" : "");

const CourseEditPanel = ({ course, courseContent, onClose, onRefreshContent, onDeleteCourse }) => {
  // Course create/delete is gated by the permission, not a hardcoded role, so
  // content-managers get it and teachers (no manage_courses) never do.
  const isAdmin = hasPerm("manage_courses");
  const [tab, setTab] = React.useState("units");
  const [unitTitle, setUnitTitle] = React.useState("");
  const [addingUnit, setAddingUnit] = React.useState(false);
  const [unitError, setUnitError] = React.useState("");
  const [deleting, setDeleting] = React.useState(false);
  const [deleteError, setDeleteError] = React.useState("");

  // Assignment tab state
  const [assignedData, setAssignedData] = React.useState(null);
  const [availBatches, setAvailBatches] = React.useState(null);
  const [availStudents, setAvailStudents] = React.useState(null);
  const [selBatch, setSelBatch] = React.useState("");
  const [selStudent, setSelStudent] = React.useState("");
  const [assignSaving, setAssignSaving] = React.useState(false);
  const [assignError, setAssignError] = React.useState("");

  const loadAssigned = React.useCallback(() => {
    if (!course) return;
    apiFetch(`/courses/${course.id}/assigned`).then(r=>r.json()).then(setAssignedData);
    apiFetch(`/courses/${course.id}/available-batches`).then(r=>r.json()).then(setAvailBatches);
    apiFetch(`/courses/${course.id}/available-students`).then(r=>r.json()).then(setAvailStudents);
  }, [course?.id]);

  React.useEffect(() => { if (tab === "assign") loadAssigned(); }, [tab, course?.id]);

  const assignBatch = async () => {
    if (!selBatch) return;
    setAssignSaving(true); setAssignError("");
    const res = await apiFetch(`/courses/${course.id}/assign-batch`, { method:"POST", body: JSON.stringify({ batch_id: parseInt(selBatch) }) });
    if (!res.ok) { const d=await res.json(); setAssignError(d.error||"Failed"); setAssignSaving(false); return; }
    setSelBatch(""); setAssignSaving(false); loadAssigned();
  };

  const assignStudent = async () => {
    if (!selStudent) return;
    setAssignSaving(true); setAssignError("");
    const res = await apiFetch(`/courses/${course.id}/assign-student`, { method:"POST", body: JSON.stringify({ student_id: parseInt(selStudent) }) });
    if (!res.ok) { const d=await res.json(); setAssignError(d.error||"Failed"); setAssignSaving(false); return; }
    setSelStudent(""); setAssignSaving(false); loadAssigned();
  };

  const removeStudent = async (sid) => {
    await apiFetch(`/courses/${course.id}/students/${sid}`, { method:"DELETE" });
    loadAssigned();
  };
  const { data: initFiles,    loading: filesLoading }    = useApi(course ? `/course-files/${course.id}` : null);
  const { data: initHomework, loading: hwLoading }       = useApi(course ? `/courses/${course.id}/homework` : null);
  const { data: initQuizzes, loading: quizzesLoading }   = useApi(course ? `/courses/${course.id}/quizzes` : null);
  const { data: BATCHES } = useApi("/batches");
  const [files,    setFiles]    = React.useState(null);
  const [homework, setHomework] = React.useState(null);
  const [quizzes,  setQuizzes]  = React.useState(null);
  const [uploading, setUploading] = React.useState(false);
  const [uploadError, setUploadError] = React.useState("");
  const [hwForm,   setHwForm]   = React.useState({ title:"", due_date:"", xp:"40", type:"paragraph", description:"" });
  const [qForm,    setQForm]    = React.useState({ title:"", batch_id:"", time_limit:"20 minutes" });
  const [saving,   setSaving]   = React.useState(false);

  const fileList = files    ?? initFiles    ?? [];
  const hwList   = homework ?? initHomework ?? [];
  const qList    = quizzes  ?? initQuizzes  ?? [];

  const refreshFiles    = () => apiFetch(`/course-files/${course.id}`).then(r=>r.json()).then(setFiles);
  const refreshHomework = () => apiFetch(`/courses/${course.id}/homework`).then(r=>r.json()).then(setHomework);
  const refreshQuizzes  = () => apiFetch(`/courses/${course.id}/quizzes`).then(r=>r.json()).then(setQuizzes);

  const uploadFile = async e => {
    const file = e.target.files[0];
    e.target.value = "";
    if (!file) return;
    setUploadError("");
    if (file.size > 35 * 1024 * 1024) {
      setUploadError(`"${file.name}" is ${(file.size/1048576).toFixed(1)} MB — max is 35 MB.`);
      return;
    }
    setUploading(true);
    const ext = file.name.split(".").pop().toLowerCase();
    const reader = new FileReader();
    reader.onload = async ev => {
      const base64 = ev.target.result.split(",")[1];
      const res = await apiFetch("/course-files", { method:"POST", body: JSON.stringify({ course_id: course.id, title: file.name, file_type: ext, file_data: base64 }) });
      if (!res.ok) {
        const d = await res.json().catch(() => ({}));
        setUploadError(d.error || (res.status === 413 ? "File too large for the server." : `Upload failed (${res.status}).`));
        setUploading(false);
        return;
      }
      await refreshFiles();
      setUploading(false);
    };
    reader.onerror = () => { setUploadError("Could not read that file."); setUploading(false); };
    reader.readAsDataURL(file);
  };

  const deleteFile = async id => {
    await apiFetch(`/course-files/${id}`, { method:"DELETE" });
    setFiles(prev => (prev ?? initFiles ?? []).filter(f=>f.id!==id));
  };

  const b64ToBlob = (b64, mime) => {
    const bin = atob(b64), bytes = new Uint8Array(bin.length);
    for (let i = 0; i < bin.length; i++) bytes[i] = bin.charCodeAt(i);
    return new Blob([bytes], { type: mime });
  };
  const fetchFileBlobUrl = async (fileId) => {
    const r = await apiFetch(`/course-files/${course.id}/${fileId}/data`);
    if (!r.ok) return null;
    const { file_data, file_type } = await r.json();
    const blob = b64ToBlob(file_data, fileMimeType(file_type));
    return { url: URL.createObjectURL(blob), file_type };
  };

  // Preview: PDFs and text render inline in a new tab; Office files (ppt/doc)
  // can't render in-browser, so the new tab will offer them as a download.
  const viewFile = async (fileId) => {
    const f = await fetchFileBlobUrl(fileId);
    if (!f) { setUploadError("Could not open file."); return; }
    window.open(f.url, "_blank");
    setTimeout(() => URL.revokeObjectURL(f.url), 60000);
  };

  const downloadFile = async (fileId, title) => {
    const f = await fetchFileBlobUrl(fileId);
    if (!f) { setUploadError("Could not download file."); return; }
    const a = document.createElement("a"); a.href = f.url; a.download = title; a.click();
    setTimeout(() => URL.revokeObjectURL(f.url), 60000);
  };

  const addHomework = async e => {
    e.preventDefault(); setSaving(true);
    await apiFetch("/homework", { method:"POST", body: JSON.stringify({ ...hwForm, course_id: course.id, xp: parseInt(hwForm.xp)||40 }) });
    await refreshHomework();
    setHwForm({ title:"", due_date:"", xp:"40", type:"paragraph", description:"" });
    setSaving(false);
  };

  const addQuiz = async e => {
    e.preventDefault(); setSaving(true);
    await apiFetch("/quizzes", { method:"POST", body: JSON.stringify({ title: qForm.title, course_id: course.id, batch_id: parseInt(qForm.batch_id)||null, time_limit: qForm.time_limit, questions:0 }) });
    await refreshQuizzes();
    setQForm({ title:"", batch_id:"", time_limit:"20 minutes" });
    setSaving(false);
  };

  const saveUnit = async () => {
    if (!unitTitle.trim()) { setUnitError("Title required"); return; }
    setUnitError(""); setAddingUnit(true);
    const res = await apiFetch(`/courses/${course.id}/units`, { method:"POST", body: JSON.stringify({ title: unitTitle.trim() }) });
    if (!res.ok) { const d=await res.json(); setUnitError(d.error||"Failed"); setAddingUnit(false); return; }
    setUnitTitle(""); setAddingUnit(false);
    if (onRefreshContent) onRefreshContent();
  };

  const pStyle = { padding:"6px 10px", borderRadius:6, border:"none", fontSize:11, cursor:"pointer", fontWeight:600 };
  const tabs = [["units","Units"],["assign","Assign"],["files","Files"],["homework","Homework"],["quizzes","Quizzes"]];

  const handleDelete = async () => {
    if (!window.confirm(`Delete "${course.title}"? This cannot be undone.`)) return;
    setDeleting(true); setDeleteError("");
    const res = await apiFetch(`/courses/${course.id}`, { method:"DELETE" });
    if (res.ok) { onDeleteCourse && onDeleteCourse(course.id); onClose(); }
    else { const d=await res.json(); setDeleteError(d.error||"Failed"); setDeleting(false); }
  };

  return (
    <div style={{ width:340, borderLeft:"var(--border-thin)", display:"flex", flexDirection:"column", flexShrink:0, background:"var(--paper-card)" }}>
      <div style={{ padding:"14px 16px", borderBottom:"var(--border-thin)" }}>
        <div style={{ display:"flex", alignItems:"center", gap:8, marginBottom:8 }}>
          <div className="display" style={{ fontSize:16, flex:1 }}>{course.title}</div>
          {isAdmin && (
            <button onClick={handleDelete} disabled={deleting} style={{ ...pStyle, background:"var(--coral)", color:"white" }} title="Delete course">
              {deleting ? "…" : "Delete"}
            </button>
          )}
          <button onClick={onClose} style={{ ...pStyle, background:"var(--paper-deep)", color:"var(--ink-soft)" }}>✕</button>
        </div>
        {deleteError && <div style={{ color:"var(--coral)", fontSize:11, marginBottom:6, padding:"4px 8px", background:"rgba(255,80,80,.1)", borderRadius:4 }}>{deleteError}</div>}
        <div style={{ display:"flex", gap:4, flexWrap:"wrap" }}>
          {tabs.map(([k,l])=>(
            <button key={k} onClick={()=>setTab(k)} style={{ ...pStyle, background: tab===k?"var(--coral)":"var(--paper-deep)", color: tab===k?"white":"var(--ink-soft)" }}>{l}</button>
          ))}
        </div>
      </div>

      <div style={{ flex:1, overflow:"auto", padding:14 }}>
        {tab === "units" && (
          <div style={{ display:"flex", flexDirection:"column", gap:8 }}>
            {/* Add unit form */}
            <div style={{ background:"var(--paper-deep)", borderRadius:8, padding:10, border:"var(--border-thin)" }}>
              <div style={{ fontSize:11, fontWeight:700, color:"var(--ink-mute)", marginBottom:6, letterSpacing:".06em" }}>ADD UNIT</div>
              <div style={{ display:"flex", gap:6 }}>
                <input
                  value={unitTitle}
                  onChange={e=>setUnitTitle(e.target.value)}
                  placeholder="e.g. Unit 1 · Getting Started"
                  style={{ flex:1, padding:"6px 10px", border:"var(--border-thin)", borderRadius:6, background:"var(--paper-card)", fontSize:12, color:"var(--ink)", outline:"none" }}
                  onKeyDown={async e => { if (e.key==="Enter") { e.preventDefault(); await saveUnit(); } }}
                />
                <button
                  disabled={addingUnit}
                  onClick={async () => { await saveUnit(); }}
                  className="btn btn-primary"
                  style={{ padding:"6px 12px", fontSize:12 }}>
                  {addingUnit ? "…" : "+ Add"}
                </button>
              </div>
              {unitError && <div style={{ color:"var(--coral)", fontSize:11, marginTop:4 }}>{unitError}</div>}
            </div>

            {courseContent.length === 0
              ? <div style={{ fontSize:12, color:"var(--ink-mute)", padding:"4px 0" }}>No units yet — add one above.</div>
              : courseContent.map(u=>(
                <div key={u.id} style={{ padding:"8px 10px", background:"var(--paper-deep)", borderRadius:8, border:"var(--border-thin)" }}>
                  <div style={{ fontWeight:700, fontSize:12 }}>{u.unit}</div>
                  <div style={{ fontSize:11, color:"var(--ink-mute)", marginTop:2 }}>{u.lessons?.length ?? 0} lessons</div>
                </div>
              ))
            }
          </div>
        )}

        {tab === "assign" && (
          <div style={{ display:"flex", flexDirection:"column", gap:12 }}>
            {/* Batches */}
            <div style={{ background:"var(--paper-deep)", borderRadius:8, padding:10, border:"var(--border-thin)" }}>
              <div style={{ fontSize:11, fontWeight:700, color:"var(--ink-mute)", marginBottom:8, letterSpacing:".06em" }}>ASSIGN BATCH</div>
              <div style={{ display:"flex", gap:6, marginBottom:8 }}>
                <select value={selBatch} onChange={e=>setSelBatch(e.target.value)}
                  style={{ flex:1, padding:"6px 8px", border:"var(--border-thin)", borderRadius:6, background:"var(--paper-card)", fontSize:12, color:"var(--ink)", outline:"none" }}>
                  <option value="">— pick a batch —</option>
                  {(availBatches||[]).map(b=>(
                    <option key={b.id} value={b.id}>{b.name}{b.current_course ? ` (currently: ${b.current_course})` : ""}</option>
                  ))}
                </select>
                <button onClick={assignBatch} disabled={!selBatch||assignSaving} className="btn btn-primary" style={{ padding:"6px 12px", fontSize:12 }}>
                  {assignSaving ? "…" : "Assign"}
                </button>
              </div>
              {(assignedData?.batches||[]).length === 0
                ? <div style={{ fontSize:12, color:"var(--ink-mute)" }}>No batches assigned yet.</div>
                : (assignedData.batches||[]).map(b=>(
                  <div key={b.id} style={{ display:"flex", alignItems:"center", gap:8, padding:"6px 10px", background:"var(--paper-card)", borderRadius:6, border:"var(--border-thin)", marginBottom:4 }}>
                    <div style={{ flex:1 }}>
                      <div style={{ fontSize:12, fontWeight:600 }}>{b.name}</div>
                      <div style={{ fontSize:10, color:"var(--ink-mute)" }}>{b.students} student{b.students!==1?"s":""}</div>
                    </div>
                  </div>
                ))
              }
            </div>
            {/* Individual students */}
            <div style={{ background:"var(--paper-deep)", borderRadius:8, padding:10, border:"var(--border-thin)" }}>
              <div style={{ fontSize:11, fontWeight:700, color:"var(--ink-mute)", marginBottom:8, letterSpacing:".06em" }}>ASSIGN INDIVIDUAL STUDENT</div>
              <div style={{ display:"flex", gap:6, marginBottom:8 }}>
                <select value={selStudent} onChange={e=>setSelStudent(e.target.value)}
                  style={{ flex:1, padding:"6px 8px", border:"var(--border-thin)", borderRadius:6, background:"var(--paper-card)", fontSize:12, color:"var(--ink)", outline:"none" }}>
                  <option value="">— pick a student —</option>
                  {(availStudents||[]).map(s=>(
                    <option key={s.id} value={s.id}>{s.name}{s.age ? ` (age ${s.age})` : ""}</option>
                  ))}
                </select>
                <button onClick={assignStudent} disabled={!selStudent||assignSaving} className="btn btn-primary" style={{ padding:"6px 12px", fontSize:12 }}>
                  {assignSaving ? "…" : "Assign"}
                </button>
              </div>
              {assignError && <div style={{ color:"var(--coral)", fontSize:11, marginBottom:6 }}>{assignError}</div>}
              {(assignedData?.students||[]).length === 0
                ? <div style={{ fontSize:12, color:"var(--ink-mute)" }}>No individual students assigned yet.</div>
                : (assignedData.students||[]).map(s=>(
                  <div key={s.id} style={{ display:"flex", alignItems:"center", gap:8, padding:"6px 10px", background:"var(--paper-card)", borderRadius:6, border:"var(--border-thin)", marginBottom:4 }}>
                    <div style={{ flex:1 }}>
                      <div style={{ fontSize:12, fontWeight:600 }}>{s.name}</div>
                      <div style={{ fontSize:10, color:"var(--ink-mute)" }}>Age {s.age||"—"} · {s.xp||0} XP</div>
                    </div>
                    <button onClick={()=>removeStudent(s.id)} style={{ ...pStyle, background:"var(--paper-deep)", color:"var(--coral)", fontSize:11, padding:"4px 8px" }}>✕</button>
                  </div>
                ))
              }
            </div>
            {!assignedData && <Spinner/>}
          </div>
        )}

        {tab === "files" && (
          <div style={{ display:"flex", flexDirection:"column", gap:10 }}>
            <label style={{ display:"flex", alignItems:"center", gap:8, padding:"10px 14px", background:"var(--paper-deep)", borderRadius:8, border:"2px dashed var(--rule)", cursor:"pointer", fontSize:13, color:"var(--ink-soft)" }}>
              {uploading ? "Uploading…" : `${I.upload({size:14})} Upload file (PDF, TXT, PPT)`}
              <input type="file" accept=".pdf,.txt,.ppt,.pptx" style={{ display:"none" }} onChange={uploadFile} disabled={uploading}/>
            </label>
            {uploadError && <div style={{ color:"var(--coral)", fontSize:12 }}>{uploadError}</div>}
            {filesLoading ? <Spinner/> : fileList.length === 0 ? (
              <div style={{ fontSize:12, color:"var(--ink-mute)" }}>No files uploaded yet.</div>
            ) : fileList.map(f=>(
              <div key={f.id} style={{ display:"flex", alignItems:"center", gap:8, padding:"8px 10px", background:"var(--paper-deep)", borderRadius:8, border:"var(--border-thin)" }}>
                <span style={{ fontSize:18 }}>{FILE_ICONS[f.file_type]||"📁"}</span>
                <div style={{ flex:1, minWidth:0 }}>
                  <div style={{ fontSize:12, fontWeight:600, overflow:"hidden", textOverflow:"ellipsis", whiteSpace:"nowrap" }}>{f.title}</div>
                  <div style={{ fontSize:10, color:"var(--ink-mute)", textTransform:"uppercase" }}>{f.file_type} · {Math.round((f.size_bytes||0)/1024)}KB</div>
                </div>
                <button onClick={()=>viewFile(f.id)} style={{ ...pStyle, background:"var(--sky)", color:"white" }}>Preview</button>
                <button onClick={()=>downloadFile(f.id, f.title)} style={{ ...pStyle, background:"var(--moss)", color:"white" }}>Download</button>
                <button onClick={()=>deleteFile(f.id)} style={{ ...pStyle, background:"var(--paper-card)", color:"var(--coral)" }}>✕</button>
              </div>
            ))}
          </div>
        )}

        {tab === "homework" && (
          <div style={{ display:"flex", flexDirection:"column", gap:10 }}>
            <form onSubmit={addHomework} style={{ background:"var(--paper-deep)", borderRadius:8, padding:12, border:"var(--border-thin)" }}>
              <div style={{ fontSize:11, fontWeight:700, color:"var(--ink-mute)", marginBottom:8, letterSpacing:".06em" }}>ADD HOMEWORK</div>
              <input required placeholder="Title" value={hwForm.title} onChange={e=>setHwForm(f=>({...f,title:e.target.value}))} style={{ width:"100%", padding:"7px 10px", border:"var(--border-thin)", borderRadius:6, background:"var(--paper-card)", fontSize:12, color:"var(--ink)", outline:"none", marginBottom:6, boxSizing:"border-box" }}/>
              <textarea placeholder="Description (optional)" value={hwForm.description} onChange={e=>setHwForm(f=>({...f,description:e.target.value}))} style={{ width:"100%", padding:"7px 10px", border:"var(--border-thin)", borderRadius:6, background:"var(--paper-card)", fontSize:12, color:"var(--ink)", outline:"none", resize:"vertical", minHeight:54, marginBottom:6, boxSizing:"border-box" }}/>
              <div style={{ display:"grid", gridTemplateColumns:"1fr 1fr 1fr", gap:6 }}>
                <input type="date" value={hwForm.due_date} onChange={e=>setHwForm(f=>({...f,due_date:e.target.value}))} style={{ padding:"6px 8px", border:"var(--border-thin)", borderRadius:6, background:"var(--paper-card)", fontSize:11, color:"var(--ink)", outline:"none" }}/>
                <input type="number" placeholder="XP" value={hwForm.xp} onChange={e=>setHwForm(f=>({...f,xp:e.target.value}))} style={{ padding:"6px 8px", border:"var(--border-thin)", borderRadius:6, background:"var(--paper-card)", fontSize:11, color:"var(--ink)", outline:"none" }}/>
                <select value={hwForm.type} onChange={e=>setHwForm(f=>({...f,type:e.target.value}))} style={{ padding:"6px 8px", border:"var(--border-thin)", borderRadius:6, background:"var(--paper-card)", fontSize:11, color:"var(--ink)", outline:"none" }}>
                  {["paragraph","mcq","video"].map(t=><option key={t} value={t}>{t}</option>)}
                </select>
              </div>
              <button type="submit" disabled={saving} className="btn btn-primary" style={{ marginTop:8, width:"100%", padding:"7px 0", fontSize:12 }}>{saving?"Saving…":"Add homework"}</button>
            </form>
            {hwLoading ? <Spinner/> : hwList.length === 0 ? (
              <div style={{ fontSize:12, color:"var(--ink-mute)" }}>No homework for this course yet.</div>
            ) : hwList.map(h=>(
              <div key={h.id} style={{ padding:"8px 10px", background:"var(--paper-deep)", borderRadius:8, border:"var(--border-thin)" }}>
                <div style={{ fontWeight:600, fontSize:12 }}>{h.title}</div>
                <div style={{ fontSize:10, color:"var(--ink-mute)", marginTop:2 }}>{h.type?.toUpperCase()} · Due {h.due} · +{h.xp} XP</div>
              </div>
            ))}
          </div>
        )}

        {tab === "quizzes" && (
          <div style={{ display:"flex", flexDirection:"column", gap:10 }}>
            <form onSubmit={addQuiz} style={{ background:"var(--paper-deep)", borderRadius:8, padding:12, border:"var(--border-thin)" }}>
              <div style={{ fontSize:11, fontWeight:700, color:"var(--ink-mute)", marginBottom:8, letterSpacing:".06em" }}>ADD QUIZ</div>
              <input required placeholder="Quiz title" value={qForm.title} onChange={e=>setQForm(f=>({...f,title:e.target.value}))} style={{ width:"100%", padding:"7px 10px", border:"var(--border-thin)", borderRadius:6, background:"var(--paper-card)", fontSize:12, color:"var(--ink)", outline:"none", marginBottom:6, boxSizing:"border-box" }}/>
              <div style={{ display:"grid", gridTemplateColumns:"1fr 1fr", gap:6, marginBottom:6 }}>
                <select value={qForm.batch_id} onChange={e=>setQForm(f=>({...f,batch_id:e.target.value}))} style={{ padding:"6px 8px", border:"var(--border-thin)", borderRadius:6, background:"var(--paper-card)", fontSize:11, color:"var(--ink)", outline:"none" }}>
                  <option value="">— any batch —</option>
                  {BATCHES.map(b=><option key={b.id} value={b.id}>{b.name}</option>)}
                </select>
                <select value={qForm.time_limit} onChange={e=>setQForm(f=>({...f,time_limit:e.target.value}))} style={{ padding:"6px 8px", border:"var(--border-thin)", borderRadius:6, background:"var(--paper-card)", fontSize:11, color:"var(--ink)", outline:"none" }}>
                  {["10 minutes","15 minutes","20 minutes","30 minutes","45 minutes","60 minutes"].map(t=><option key={t} value={t}>{t}</option>)}
                </select>
              </div>
              <button type="submit" disabled={saving} className="btn btn-primary" style={{ width:"100%", padding:"7px 0", fontSize:12 }}>{saving?"Saving…":"Create quiz"}</button>
            </form>
            {quizzesLoading ? <Spinner/> : qList.length === 0 ? (
              <div style={{ fontSize:12, color:"var(--ink-mute)" }}>No quizzes for this course yet.</div>
            ) : qList.map(q=>(
              <div key={q.id} style={{ padding:"8px 10px", background:"var(--paper-deep)", borderRadius:8, border:"var(--border-thin)" }}>
                <div style={{ fontWeight:600, fontSize:12 }}>{q.title}</div>
                <div style={{ fontSize:10, color:"var(--ink-mute)", marginTop:2 }}>{q.batch} · {q.assigned} · {q.questions} Qs</div>
              </div>
            ))}
          </div>
        )}
      </div>
    </div>
  );
};

const AdminCourses = ({ dark = true, go }) => {
  const { data: initCourses } = useApi("/courses");
  const [courses, setCourses]   = React.useState(null);
  const [selected, setSelected] = React.useState(null);
  const [showAdd, setShowAdd]   = React.useState(false);
  const [form, setForm]         = React.useState({ name:"", level:"Beginner" });
  const [saving, setSaving]     = React.useState(false);
  const [error, setError]       = React.useState("");
  const list = courses ?? initCourses;
  const course = selected ? list.find(c=>c.id===selected) : null;

  const { data: initCourseContent } = useApi(selected ? `/content/${selected}` : "/content/0");
  const [courseContent, setCourseContent] = React.useState(null);
  React.useEffect(() => { setCourseContent(null); }, [selected]);
  const cc = courseContent ?? initCourseContent;
  const refreshCourseContent = () => selected && apiFetch(`/content/${selected}`).then(r=>r.json()).then(setCourseContent);

  const refresh = () => apiFetch("/courses").then(r=>r.json()).then(setCourses);

  const save = async e => {
    e.preventDefault(); setError(""); setSaving(true);
    const res = await apiFetch("/courses/list", { method:"POST", body: JSON.stringify(form) });
    const data = await res.json();
    if (!res.ok) { setError(data.error||"Failed"); setSaving(false); return; }
    await refresh(); setForm({ name:"", level:"Beginner" }); setShowAdd(false); setSaving(false);
  };

  return (
    <Themed className={dark?"theme-dark":""} style={{ width:"100%", height:"100%", display:"flex" }}>
      {showAdd && (
        <Modal title="New course" onClose={()=>setShowAdd(false)}>
          <form onSubmit={save}>
            <FormField label="COURSE NAME">
              <input required style={inputStyle} value={form.name} onChange={e=>setForm(f=>({...f,name:e.target.value}))} placeholder="e.g. Python · Beginner"/>
            </FormField>
            <FormField label="LEVEL">
              <select style={selectStyle} value={form.level} onChange={e=>setForm(f=>({...f,level:e.target.value}))}>
                {["Beginner","Intermediate","Advanced"].map(l=><option key={l} value={l}>{l}</option>)}
              </select>
            </FormField>
            {error && <div style={{ color:"var(--coral)", fontSize:13, marginBottom:12 }}>{error}</div>}
            <div style={{ display:"flex", gap:10, justifyContent:"flex-end", marginTop:4 }}>
              <button type="button" onClick={()=>setShowAdd(false)} className="btn btn-ghost">Cancel</button>
              <button type="submit" disabled={saving} className="btn btn-primary">{saving?"Saving…":"Create course"}</button>
            </div>
          </form>
        </Modal>
      )}
      <AdminSidebar active="/app/admin/courses" go={go}/>
      <div style={{ flex:1, display:"flex", flexDirection:"column", minWidth:0, background:"var(--paper)" }}>
        <div style={{ display:"flex", alignItems:"center", gap:12, padding:"12px 22px", borderBottom:"var(--border-thin)", background:"var(--paper-card)" }}>
          <div>
            <div className="display" style={{ fontSize:20 }}>Courses</div>
            <div className="mono" style={{ fontSize:10, color:"var(--ink-mute)" }}>{list.length} courses · {list.filter(c=>c.status==="active").length} active</div>
          </div>
          <div style={{ flex:1 }}/>
          <button onClick={()=>setShowAdd(true)} className="btn btn-primary" style={{ padding:"6px 14px", fontSize:12 }}>{I.plus({ size:14 })} New course</button>
        </div>
        <div style={{ flex:1, display:"flex", overflow:"hidden" }}>
          <div style={{ flex:1, overflow:"auto", padding:22 }}>
            {list.length === 0 ? (
              <div style={{ textAlign:"center", padding:60, color:"var(--ink-mute)" }}>
                <div style={{ fontSize:32, marginBottom:12 }}>📚</div>
                <div style={{ fontSize:16, fontWeight:700 }}>No courses yet</div>
                <div style={{ fontSize:13, marginTop:4, marginBottom:20 }}>Create your first course to get started</div>
                <button onClick={()=>setShowAdd(true)} className="btn btn-primary">{I.plus({ size:14 })} New course</button>
              </div>
            ) : (
              <div style={{ display:"grid", gridTemplateColumns:"repeat(auto-fill, minmax(260px,1fr))", gap:16 }}>
                {list.map((c, idx) => {
                  const color = COURSE_COLORS[idx % COURSE_COLORS.length];
                  return (
                    <div key={c.id} onClick={() => setSelected(selected===c.id?null:c.id)} className="card" style={{ padding:0, cursor:"pointer", overflow:"hidden", border: selected===c.id ? `2px solid ${color}` : "var(--border)" }}>
                      <div style={{ background:color, padding:"20px 18px", color:"white", position:"relative", overflow:"hidden" }}>
                        <div style={{ position:"absolute", top:-20, right:-20, width:80, height:80, borderRadius:"50%", background:"rgba(255,255,255,.12)" }}/>
                        <div style={{ width:36, height:36, borderRadius:10, background:"rgba(255,255,255,.2)", display:"grid", placeItems:"center", marginBottom:10 }}>{I.book({ size:18 })}</div>
                        <div className="display" style={{ fontSize:20 }}>{c.title}</div>
                        <span className="chip" style={{ marginTop:8, background:"rgba(255,255,255,.25)", color:"white", fontSize:10, display:"inline-flex" }}>{c.status}</span>
                      </div>
                      <div style={{ padding:"14px 18px", display:"grid", gridTemplateColumns:"1fr 1fr 1fr", gap:10 }}>
                        {[["Batches",c.batches],["Students",c.students],["Lessons",c.lessons]].map(([l,v])=>(
                          <div key={l}>
                            <div style={{ fontSize:10, color:"var(--ink-mute)" }}>{l}</div>
                            <div className="display" style={{ fontSize:22 }}>{v}</div>
                          </div>
                        ))}
                      </div>
                    </div>
                  );
                })}
              </div>
            )}
          </div>
          {course && (
            <CourseEditPanel
              course={course}
              courseContent={cc}
              onClose={()=>setSelected(null)}
              onRefreshContent={refreshCourseContent}
              onDeleteCourse={id=>{ setCourses(prev=>(prev||initCourses||[]).filter(c=>c.id!==id)); setSelected(null); }}
            />
          )}
        </div>
      </div>
    </Themed>
  );
};

// ── Admin: Sub-centres ────────────────────────────────────────────────────────
const AdminCentres = ({ dark = true, go }) => {
  const { data: CENTRES } = useApi("/centres");
  return (
  <Themed className={dark?"theme-dark":""} style={{ width:"100%", height:"100%", display:"flex" }}>
    <AdminSidebar active="/app/admin/centres" go={go}/>
    <div style={{ flex:1, display:"flex", flexDirection:"column", minWidth:0, background:"var(--paper)" }}>
      <div style={{ display:"flex", alignItems:"center", gap:12, padding:"12px 22px", borderBottom:"var(--border-thin)", background:"var(--paper-card)" }}>
        <div>
          <div className="display" style={{ fontSize:20 }}>Sub-centres</div>
          <div className="mono" style={{ fontSize:10, color:"var(--ink-mute)" }}>{CENTRES.length} centres · {CENTRES.reduce((a,c)=>a+c.students,0)} total students</div>
        </div>
        <div style={{ flex:1 }}/>
        <button className="btn btn-primary" style={{ padding:"6px 14px", fontSize:12 }}>{I.plus({ size:14 })} Add centre</button>
      </div>
      <div style={{ flex:1, overflow:"auto", padding:22 }}>
        <div style={{ display:"grid", gridTemplateColumns:"repeat(auto-fill,minmax(280px,1fr))", gap:16, marginBottom:22 }}>
          {CENTRES.map(c=>(
            <div key={c.id} className="card" style={{ padding:0, overflow:"hidden" }}>
              <div style={{ background:c.color, padding:"18px 20px", color:"white", display:"flex", justifyContent:"space-between", alignItems:"center" }}>
                <div>
                  <div className="display" style={{ fontSize:18 }}>{c.name}</div>
                  <div style={{ fontSize:12, opacity:.85 }}>{c.city}</div>
                </div>
                <span style={{ padding:"3px 10px", borderRadius:999, background:"rgba(255,255,255,.25)", fontSize:10, fontWeight:700 }}>{c.status}</span>
              </div>
              <div style={{ padding:"14px 20px", display:"grid", gridTemplateColumns:"1fr 1fr 1fr", gap:10 }}>
                {[["Students",c.students],["Teachers",c.teachers],["Revenue",c.revenue]].map(([l,v])=>(
                  <div key={l}>
                    <div style={{ fontSize:10, color:"var(--ink-mute)" }}>{l}</div>
                    <div style={{ fontWeight:700, fontSize:l==="Revenue"?14:20 }}>{v}</div>
                  </div>
                ))}
              </div>
              <div style={{ padding:"0 20px 14px", display:"flex", gap:8 }}>
                <button className="btn btn-ghost" style={{ flex:1, padding:"6px 0", fontSize:12 }}>{I.users({ size:14 })} Students</button>
                <button className="btn btn-ghost" style={{ flex:1, padding:"6px 0", fontSize:12 }}>{I.chart({ size:14 })} Analytics</button>
              </div>
            </div>
          ))}
        </div>
        <div className="card-flat" style={{ padding:18 }}>
          <SectionHead eyebrow="TOTAL NETWORK" title="Revenue by centre"/>
          <div style={{ display:"flex", alignItems:"end", gap:8, height:120 }}>
            {CENTRES.map((c,i)=>{
              const h = [50,45,33,14,100][i];
              return (
                <div key={i} style={{ flex:1, display:"flex", flexDirection:"column", alignItems:"center", gap:6 }}>
                  <div style={{ width:"100%", height:`${h}%`, background:c.color, border:"1.5px solid var(--rule-bold)", borderRadius:"4px 4px 0 0" }}/>
                  <div style={{ fontSize:10, color:"var(--ink-mute)", textAlign:"center", fontFamily:"var(--font-mono)" }}>{c.city.split(" ")[0]}</div>
                </div>
              );
            })}
          </div>
        </div>
      </div>
    </div>
  </Themed>
  );
};

// ── Admin: Certificates ───────────────────────────────────────────────────────
const AdminCertificates = ({ dark = true, go }) => {
  const { data: initCerts } = useApi("/certificates/all");
  const { data: STUDENTS }  = useApi("/students");
  const { data: COURSES }   = useApi("/courses/list");
  const [certs, setCerts]   = React.useState(null);
  const [showAdd, setShowAdd] = React.useState(false);
  const [form, setForm]       = React.useState({ student_id:"", course:"" });
  const [saving, setSaving]   = React.useState(false);
  const [error, setError]     = React.useState("");
  const list = certs ?? initCerts;

  const refresh = () => apiFetch("/certificates/all").then(r=>r.json()).then(setCerts);

  const issue = async e => {
    e.preventDefault(); setError(""); setSaving(true);
    const res = await apiFetch("/certificates", { method:"POST", body: JSON.stringify(form) });
    const data = await res.json();
    if (!res.ok) { setError(data.error||"Failed"); setSaving(false); return; }
    await refresh(); setForm({ student_id:"", course:"" }); setShowAdd(false); setSaving(false);
  };

  return (
  <Themed className={dark?"theme-dark":""} style={{ width:"100%", height:"100%", display:"flex" }}>
    {showAdd && (
      <Modal title="Issue certificate" onClose={()=>setShowAdd(false)}>
        <form onSubmit={issue}>
          <FormField label="STUDENT">
            <select required style={selectStyle} value={form.student_id} onChange={e=>setForm(f=>({...f,student_id:e.target.value}))}>
              <option value="">— select student —</option>
              {STUDENTS.map(s=><option key={s.id} value={s.id}>{s.name}</option>)}
            </select>
          </FormField>
          <FormField label="COURSE">
            <select required style={selectStyle} value={form.course} onChange={e=>setForm(f=>({...f,course:e.target.value}))}>
              <option value="">— select course —</option>
              {COURSES.map(c=><option key={c.id} value={`${c.name} · ${c.level}`}>{c.name} · {c.level}</option>)}
            </select>
          </FormField>
          {error && <div style={{ color:"var(--coral)", fontSize:13, marginBottom:12 }}>{error}</div>}
          <div style={{ display:"flex", gap:10, justifyContent:"flex-end", marginTop:4 }}>
            <button type="button" onClick={()=>setShowAdd(false)} className="btn btn-ghost">Cancel</button>
            <button type="submit" disabled={saving} className="btn btn-primary">{saving?"Issuing…":"Issue certificate"}</button>
          </div>
        </form>
      </Modal>
    )}
    <AdminSidebar active="/app/admin/certificates" go={go}/>
    <div style={{ flex:1, display:"flex", flexDirection:"column", minWidth:0, background:"var(--paper)" }}>
      <div style={{ display:"flex", alignItems:"center", gap:12, padding:"12px 22px", borderBottom:"var(--border-thin)", background:"var(--paper-card)" }}>
        <div>
          <div className="display" style={{ fontSize:20 }}>Certificates</div>
          <div className="mono" style={{ fontSize:10, color:"var(--ink-mute)" }}>{list.length} issued total</div>
        </div>
        <div style={{ flex:1 }}/>
        <button onClick={()=>setShowAdd(true)} className="btn btn-primary" style={{ padding:"6px 14px", fontSize:12 }}>{I.plus({ size:14 })} Issue certificate</button>
      </div>
      <div style={{ flex:1, overflow:"auto", padding:22 }}>
        <div style={{ display:"grid", gridTemplateColumns:"repeat(2,1fr)", gap:14, marginBottom:22 }}>
          {[
            { l:"TOTAL ISSUED", v:list.length, c:"var(--moss)" },
            { l:"STUDENTS WITH CERTS", v: new Set(list.map(c=>c.student)).size, c:"var(--sky)" },
          ].map(k=>(
            <div key={k.l} className="card-flat" style={{ padding:14 }}>
              <div className="mono" style={{ fontSize:10, color:"var(--ink-mute)", letterSpacing:".06em" }}>{k.l}</div>
              <div className="display" style={{ fontSize:28, color:k.c, marginTop:4 }}>{k.v}</div>
            </div>
          ))}
        </div>
        {list.length === 0 ? (
          <div style={{ textAlign:"center", padding:60, color:"var(--ink-mute)" }}>
            <div style={{ fontSize:32, marginBottom:12 }}>🏆</div>
            <div style={{ fontSize:16, fontWeight:700 }}>No certificates issued yet</div>
            <div style={{ fontSize:13, marginTop:4, marginBottom:20 }}>Issue certificates to students who complete courses</div>
            <button onClick={()=>setShowAdd(true)} className="btn btn-primary">{I.plus({ size:14 })} Issue first certificate</button>
          </div>
        ) : (
          <table style={{ width:"100%", borderCollapse:"collapse", fontSize:13 }}>
            <thead>
              <tr style={{ textAlign:"left", color:"var(--ink-mute)" }}>
                {["Student","Course","Cert ID","Issued",""].map((h,hi)=>(
                  <th key={hi} style={{ padding:"8px 12px", fontWeight:600, fontSize:11, borderBottom:"var(--border-thin)" }}>{h}</th>
                ))}
              </tr>
            </thead>
            <tbody>
              {list.map((c,i)=>(
                <tr key={i} style={{ borderTop: i?"var(--border-thin)":"none" }}>
                  <td style={{ padding:"12px" }}>
                    <div style={{ display:"flex", alignItems:"center", gap:8 }}>
                      <Avatar name={c.student[0]} color={c.color||"var(--coral)"} size={26}/>
                      <span style={{ fontWeight:700 }}>{c.student}</span>
                    </div>
                  </td>
                  <td style={{ padding:"12px", color:"var(--ink-soft)" }}>{c.course}</td>
                  <td style={{ padding:"12px" }}><a href={`#/verify/${c.id}`} title="Public verification page" className="mono" style={{ fontSize:11, textDecoration:"underline", color:"var(--ink)" }}>{c.id}</a></td>
                  <td style={{ padding:"12px" }}><span className="mono" style={{ fontSize:11, color:"var(--ink-mute)" }}>{c.date}</span></td>
                  <td style={{ padding:"12px" }}><button onClick={()=>downloadCertificate({ id:c.id, name:c.student, course:c.course, issued:c.date, color:c.color })} className="btn btn-ghost" style={{ padding:"4px 10px", fontSize:11 }}>{I.upload({ size:11 })} PDF</button></td>
                </tr>
              ))}
            </tbody>
          </table>
        )}
      </div>
    </div>
  </Themed>
  );
};

// ── Admin: Settings ───────────────────────────────────────────────────────────
// ── Admin: Institutions & Divisions ───────────────────────────────────────────
const AdminInstitutions = ({ dark = true, go }) => {
  const { data: initInst, loading } = useApi("/institutions");
  const { data: TEACHERS } = useApi("/teachers");
  const { data: COURSES } = useApi("/courses/list");
  const [inst, setInst] = React.useState(null);
  const [selected, setSelected] = React.useState(null);   // selected institution id
  const [divisions, setDivisions] = React.useState([]);
  const [divLoading, setDivLoading] = React.useState(false);
  const [showInst, setShowInst] = React.useState(false);
  const [showDiv, setShowDiv] = React.useState(false);
  const [instForm, setInstForm] = React.useState({ name:"", city:"", contact:"" });
  const [divForm, setDivForm] = React.useState({ name:"", grade_label:"", teacher_id:"", course_id:"" });
  const [saving, setSaving] = React.useState(false);
  const [error, setError] = React.useState("");
  const list = inst ?? initInst;
  const current = selected ? list.find(i => i.id === selected) : null;
  const canManageInst = hasPerm("manage_institutions");
  const canManageDiv = hasPerm("manage_divisions");

  const refresh = () => apiFetch("/institutions").then(r => r.json()).then(setInst);
  const loadDivisions = (id) => {
    setDivLoading(true);
    apiFetch(`/institutions/${id}/divisions`).then(r => r.json())
      .then(d => setDivisions(Array.isArray(d) ? d : []))
      .finally(() => setDivLoading(false));
  };
  const openInst = (i) => { setSelected(i.id); loadDivisions(i.id); };

  const addInst = async (e) => {
    e.preventDefault(); setError(""); setSaving(true);
    const res = await apiFetch("/institutions", { method:"POST", body: JSON.stringify(instForm) });
    const data = await res.json();
    if (!res.ok) { setError(data.error || "Failed"); setSaving(false); return; }
    await refresh(); setInstForm({ name:"", city:"", contact:"" }); setShowInst(false); setSaving(false);
  };
  const deleteInst = async (id) => {
    if (!confirm("Delete this institution and all its divisions?")) return;
    await apiFetch(`/institutions/${id}`, { method:"DELETE" });
    if (selected === id) { setSelected(null); setDivisions([]); }
    await refresh();
  };
  const toggleInstStatus = async (i) => {
    await apiFetch(`/institutions/${i.id}`, { method:"PATCH", body: JSON.stringify({ status: i.status === "active" ? "inactive" : "active" }) });
    await refresh();
  };

  const addDiv = async (e) => {
    e.preventDefault(); setError(""); setSaving(true);
    const res = await apiFetch(`/institutions/${selected}/divisions`, { method:"POST", body: JSON.stringify({
      name: divForm.name, grade_label: divForm.grade_label || null,
      teacher_id: divForm.teacher_id || null, course_id: divForm.course_id || null,
    })});
    const data = await res.json();
    if (!res.ok) { setError(data.error || "Failed"); setSaving(false); return; }
    loadDivisions(selected); await refresh();
    setDivForm({ name:"", grade_label:"", teacher_id:"", course_id:"" }); setShowDiv(false); setSaving(false);
  };
  const deleteDiv = async (id) => {
    if (!confirm("Delete this division?")) return;
    await apiFetch(`/divisions/${id}`, { method:"DELETE" });
    loadDivisions(selected); await refresh();
  };

  if (loading) return <Spinner/>;
  return (
    <Themed className={dark?"theme-dark":""} style={{ width:"100%", height:"100%", display:"flex" }}>
      {showInst && (
        <Modal title="New institution" onClose={()=>setShowInst(false)}>
          <form onSubmit={addInst}>
            <FormField label="NAME"><input required style={inputStyle} value={instForm.name} onChange={e=>setInstForm(f=>({...f,name:e.target.value}))} placeholder="e.g. Greenwood International School"/></FormField>
            <FormField label="CITY"><input style={inputStyle} value={instForm.city} onChange={e=>setInstForm(f=>({...f,city:e.target.value}))} placeholder="e.g. Mumbai"/></FormField>
            <FormField label="CONTACT"><input style={inputStyle} value={instForm.contact} onChange={e=>setInstForm(f=>({...f,contact:e.target.value}))} placeholder="Name / phone / email"/></FormField>
            {error && <div style={{ color:"var(--coral)", fontSize:13, marginBottom:10 }}>{error}</div>}
            <div style={{ display:"flex", gap:10, justifyContent:"flex-end" }}>
              <button type="button" onClick={()=>setShowInst(false)} className="btn btn-ghost">Cancel</button>
              <button type="submit" disabled={saving} className="btn btn-primary">{saving?"Creating…":"Create"}</button>
            </div>
          </form>
        </Modal>
      )}
      {showDiv && (
        <Modal title="New division" onClose={()=>setShowDiv(false)}>
          <form onSubmit={addDiv}>
            <FormField label="NAME"><input required style={inputStyle} value={divForm.name} onChange={e=>setDivForm(f=>({...f,name:e.target.value}))} placeholder="e.g. Class 6 - A"/></FormField>
            <FormField label="GRADE LABEL"><input style={inputStyle} value={divForm.grade_label} onChange={e=>setDivForm(f=>({...f,grade_label:e.target.value}))} placeholder="e.g. Grade 6"/></FormField>
            <FormField label="TEACHER">
              <select style={selectStyle} value={divForm.teacher_id} onChange={e=>setDivForm(f=>({...f,teacher_id:e.target.value}))}>
                <option value="">— optional —</option>
                {TEACHERS.map(t=><option key={t.id} value={t.id}>{t.name}</option>)}
              </select>
            </FormField>
            <FormField label="COURSE">
              <select style={selectStyle} value={divForm.course_id} onChange={e=>setDivForm(f=>({...f,course_id:e.target.value}))}>
                <option value="">— optional —</option>
                {COURSES.map(c=><option key={c.id} value={c.id}>{c.name} · {c.level}</option>)}
              </select>
            </FormField>
            {error && <div style={{ color:"var(--coral)", fontSize:13, marginBottom:10 }}>{error}</div>}
            <div style={{ display:"flex", gap:10, justifyContent:"flex-end" }}>
              <button type="button" onClick={()=>setShowDiv(false)} className="btn btn-ghost">Cancel</button>
              <button type="submit" disabled={saving} className="btn btn-primary">{saving?"Creating…":"Create"}</button>
            </div>
          </form>
        </Modal>
      )}
      <AdminSidebar active="/app/admin/institutions" go={go}/>
      <div style={{ flex:1, display:"flex", minWidth:0, background:"var(--paper)" }}>
        {/* Institution list */}
        <div style={{ width:280, borderRight:"var(--border-thin)", display:"flex", flexDirection:"column", background:"var(--paper-card)" }}>
          <div style={{ padding:"12px 16px", borderBottom:"var(--border-thin)", display:"flex", alignItems:"center", gap:8 }}>
            <div className="display" style={{ fontSize:16, flex:1 }}>Institutions</div>
            {canManageInst && <button onClick={()=>setShowInst(true)} className="btn btn-primary" style={{ padding:"4px 10px", fontSize:11 }}>{I.plus({size:12})} New</button>}
          </div>
          <div style={{ flex:1, overflow:"auto", padding:10 }}>
            {list.length === 0 && <div style={{ padding:16, fontSize:13, color:"var(--ink-mute)" }}>No institutions yet.</div>}
            {list.map(i=>(
              <button key={i.id} onClick={()=>openInst(i)} style={{ display:"flex", alignItems:"center", gap:10, width:"100%", padding:"10px 12px", borderRadius:8, border:"none", marginBottom:4,
                background: selected===i.id?"var(--paper-deep)":"transparent", cursor:"pointer", textAlign:"left" }}>
                <div style={{ width:8, height:8, borderRadius:"50%", background: i.status==="active"?"var(--moss)":"var(--ink-mute)", flexShrink:0 }}/>
                <div style={{ flex:1, minWidth:0 }}>
                  <div style={{ fontWeight:700, fontSize:13, color:"var(--ink)", overflow:"hidden", textOverflow:"ellipsis", whiteSpace:"nowrap" }}>{i.name}</div>
                  <div style={{ fontSize:10, color:"var(--ink-mute)", marginTop:1 }}>{i.city || "—"} · {i.divisions} div · {i.students} students</div>
                </div>
              </button>
            ))}
          </div>
        </div>

        {/* Detail */}
        {current ? (
          <div style={{ flex:1, display:"flex", flexDirection:"column", overflow:"hidden" }}>
            <div style={{ padding:"12px 22px", borderBottom:"var(--border-thin)", background:"var(--paper-card)", display:"flex", alignItems:"center", gap:12 }}>
              <div style={{ flex:1 }}>
                <div className="display" style={{ fontSize:18 }}>{current.name}</div>
                <div style={{ fontSize:11, color:"var(--ink-mute)" }}>{current.city || "—"}{current.contact ? " · " + current.contact : ""} · {current.status}</div>
              </div>
              {canManageInst && <button onClick={()=>toggleInstStatus(current)} className="btn btn-ghost" style={{ padding:"6px 12px", fontSize:11 }}>{current.status==="active"?"Deactivate":"Activate"}</button>}
              {canManageInst && <button onClick={()=>deleteInst(current.id)} style={{ fontSize:11, padding:"6px 12px", borderRadius:6, border:"var(--border-thin)", background:"transparent", color:"var(--coral)", cursor:"pointer", fontWeight:600 }}>Delete</button>}
              {canManageDiv && <button onClick={()=>setShowDiv(true)} className="btn btn-primary" style={{ padding:"6px 14px", fontSize:12 }}>{I.plus({size:12})} New division</button>}
            </div>
            <div style={{ flex:1, overflow:"auto", padding:22 }}>
              {divLoading ? <Spinner/> : divisions.length === 0 ? (
                <div style={{ textAlign:"center", padding:48, color:"var(--ink-mute)" }}>
                  <div style={{ fontSize:32, marginBottom:8 }}>🏫</div>
                  <div style={{ fontWeight:700, fontSize:15 }}>No divisions yet</div>
                  <div style={{ fontSize:13, marginTop:4 }}>Create class divisions to enroll students into this institution.</div>
                </div>
              ) : (
                <div className="card-flat" style={{ overflow:"hidden" }}>
                  <table style={{ width:"100%", borderCollapse:"collapse", fontSize:13 }}>
                    <thead>
                      <tr style={{ background:"var(--paper-deep)" }}>
                        {["Division","Grade","Teacher","Students",""].map(h=>(
                          <th key={h} style={{ padding:"10px 14px", textAlign:"left", fontSize:11, fontWeight:700, color:"var(--ink-mute)", letterSpacing:".06em" }}>{h.toUpperCase()}</th>
                        ))}
                      </tr>
                    </thead>
                    <tbody>
                      {divisions.map((d,i)=>(
                        <tr key={d.id} style={{ borderTop: i?"var(--border-thin)":"none" }}>
                          <td style={{ padding:"11px 14px", fontWeight:700 }}>{d.name}</td>
                          <td style={{ padding:"11px 14px", color:"var(--ink-soft)" }}>{d.grade_label || "—"}</td>
                          <td style={{ padding:"11px 14px", color:"var(--ink-soft)" }}>{d.teacher || "—"}</td>
                          <td style={{ padding:"11px 14px" }}>{d.students}</td>
                          <td style={{ padding:"11px 14px", textAlign:"right" }}>
                            {canManageDiv && <button onClick={()=>deleteDiv(d.id)} style={{ fontSize:11, padding:"4px 10px", borderRadius:6, border:"var(--border-thin)", background:"transparent", color:"var(--coral)", cursor:"pointer", fontWeight:600 }}>Delete</button>}
                          </td>
                        </tr>
                      ))}
                    </tbody>
                  </table>
                </div>
              )}
            </div>
          </div>
        ) : (
          <div style={{ flex:1, display:"flex", alignItems:"center", justifyContent:"center", color:"var(--ink-mute)", flexDirection:"column", gap:10 }}>
            <div style={{ fontSize:32 }}>🏫</div>
            <div style={{ fontSize:14, fontWeight:600 }}>Select an institution to manage its divisions</div>
          </div>
        )}
      </div>
    </Themed>
  );
};

// ── Admin: Audit Log viewer ───────────────────────────────────────────────────
const AdminAudit = ({ dark = true, go }) => {
  const PAGE = 50;
  const [offset, setOffset] = React.useState(0);
  const [rows, setRows] = React.useState([]);
  const [total, setTotal] = React.useState(0);
  const [loading, setLoading] = React.useState(true);
  React.useEffect(() => {
    setLoading(true);
    apiFetch(`/audit?limit=${PAGE}&offset=${offset}`).then(r => r.json())
      .then(d => { setRows(d.data || []); setTotal(d.total || 0); })
      .finally(() => setLoading(false));
  }, [offset]);

  const actionColor = (a) => a.includes("delete") ? "var(--coral)"
    : a.includes("create") ? "var(--moss)"
    : a.includes("role") || a.includes("password") || a.includes("status") ? "var(--gold)"
    : "var(--sky)";

  return (
    <Themed className={dark?"theme-dark":""} style={{ width:"100%", height:"100%", display:"flex" }}>
      <AdminSidebar active="/app/admin/audit" go={go}/>
      <div style={{ flex:1, display:"flex", flexDirection:"column", minWidth:0, background:"var(--paper)" }}>
        <div style={{ display:"flex", alignItems:"center", gap:12, padding:"12px 22px", borderBottom:"var(--border-thin)", background:"var(--paper-card)" }}>
          <div>
            <div className="display" style={{ fontSize:20 }}>Audit Log</div>
            <div className="mono" style={{ fontSize:10, color:"var(--ink-mute)" }}>{total} events · security & admin actions</div>
          </div>
          <div style={{ flex:1 }}/>
          <button disabled={offset===0} onClick={()=>setOffset(o=>Math.max(0,o-PAGE))} className="btn btn-ghost" style={{ padding:"6px 12px", fontSize:12, opacity: offset===0?0.5:1 }}>← Newer</button>
          <button disabled={offset+PAGE>=total} onClick={()=>setOffset(o=>o+PAGE)} className="btn btn-ghost" style={{ padding:"6px 12px", fontSize:12, opacity: offset+PAGE>=total?0.5:1 }}>Older →</button>
        </div>
        <div style={{ flex:1, overflow:"auto", padding:22 }}>
          {loading ? <Spinner/> : rows.length === 0 ? (
            <div style={{ textAlign:"center", padding:60, color:"var(--ink-mute)" }}>
              <div style={{ fontSize:32, marginBottom:8 }}>📋</div>
              <div style={{ fontWeight:700, fontSize:15 }}>No audit events yet</div>
            </div>
          ) : (
            <table style={{ width:"100%", borderCollapse:"collapse", fontSize:13 }}>
              <thead>
                <tr>
                  {["When","Actor","Action","Entity","IP"].map(h=>(
                    <th key={h} style={{ padding:"8px 12px", fontWeight:600, fontSize:11, borderBottom:"var(--border-thin)", textAlign:"left", color:"var(--ink-mute)" }}>{h}</th>
                  ))}
                </tr>
              </thead>
              <tbody>
                {rows.map((r,i)=>(
                  <tr key={r.id} style={{ borderTop:i?"var(--border-thin)":"none" }}>
                    <td style={{ padding:"10px 12px", fontSize:11, color:"var(--ink-mute)", whiteSpace:"nowrap" }}>{new Date(r.created_at).toLocaleString("en-IN",{day:"numeric",month:"short",hour:"2-digit",minute:"2-digit"})}</td>
                    <td style={{ padding:"10px 12px" }}>
                      <div style={{ fontWeight:600, fontSize:12 }}>{r.actor_email || "—"}</div>
                      <div style={{ fontSize:10, color:"var(--ink-mute)" }}>{r.actor_role || ""}</div>
                    </td>
                    <td style={{ padding:"10px 12px" }}>
                      <span className="mono" style={{ fontSize:11, fontWeight:700, padding:"2px 8px", borderRadius:6, background:"var(--paper-deep)", color: actionColor(r.action) }}>{r.action}</span>
                    </td>
                    <td style={{ padding:"10px 12px", fontSize:12, color:"var(--ink-soft)" }}>{r.entity_type ? `${r.entity_type} #${r.entity_id ?? "—"}` : "—"}</td>
                    <td style={{ padding:"10px 12px", fontSize:11, color:"var(--ink-mute)", fontFamily:"var(--font-mono)" }}>{r.ip || "—"}</td>
                  </tr>
                ))}
              </tbody>
            </table>
          )}
        </div>
      </div>
    </Themed>
  );
};

// Setting field catalog: [storage key, label, placeholder]. Values persist to
// the `settings` table via PUT /settings/:key.
const SETTINGS_SECTIONS = [
  { section:"ORGANISATION", fields:[
    ["centre_name","Centre name","EpiqMinds · Mumbai"],
    ["admin_email","Admin email","admin@epiqminds.com"],
    ["support_phone","Support phone","+91 98765 00000"],
    ["timezone","Timezone","Asia/Kolkata (IST +5:30)"],
  ]},
  { section:"NOTIFICATIONS", fields:[
    ["whatsapp_api_key","WhatsApp API key","twilio_…"],
    ["sendgrid_api_key","SendGrid API key","SG.…"],
    ["sender_name","Default sender name","EpiqMinds Team"],
  ]},
  { section:"PAYMENTS", fields:[
    ["razorpay_key_id","Razorpay key ID","rzp_live_…"],
    ["currency","Currency","INR"],
    ["late_fee_days","Late fee after (days)","7"],
    ["reminder_schedule","Auto-reminder schedule","Day 0, Day 3, Day 7"],
  ]},
];

// ── Admin: Inquiries / Leads ──────────────────────────────────────────────────
const INQ_TABS = ["all", "inquired", "negotiating", "joined", "enrolled", "completed", "lost"];
const INQ_COLOR = { inquired:"var(--sky)", negotiating:"var(--gold)", joined:"var(--moss)", enrolled:"var(--moss)", completed:"var(--moss)", lost:"var(--ink-mute)" };
const INQ_SOURCES = ["landing", "pricing", "manual", "referral", "instagram", "ads", "other"];
// Source options offered when manually adding a lead (value → label).
const LEAD_SOURCES = [["website","Website"],["call","Call"],["walkin","Walk-in"],["whatsapp","WhatsApp"],["referral","Referral"],["instagram","Instagram"],["ads","Ads"],["other","Other"]];

const AdminInquiries = ({ dark = true, go, session = {} }) => {
  const [tab, setTab] = React.useState("all");
  const [list, setList] = React.useState([]);
  const [loading, setLoading] = React.useState(true);
  const [selectedId, setSelectedId] = React.useState(null);
  const [edit, setEdit] = React.useState({ negotiated_amount:"", intended_amount:"", source:"", notes:"", status:"" });
  const [saving, setSaving] = React.useState(false);
  const [convertResult, setConvertResult] = React.useState(null);
  const [linkResult, setLinkResult] = React.useState(null);
  const [genLink, setGenLink] = React.useState(false);
  const [copied, setCopied] = React.useState("");
  // Manual "Add lead" (walk-in / phone / referral leads captured off-platform).
  const BLANK_LEAD = { parent_name:"", email:"", phone:"", child_name:"", child_age:"", plan_label:"", intended_amount:"", source:"call", status:"inquired", notes:"" };
  const [showAdd, setShowAdd] = React.useState(false);
  const [addForm, setAddForm] = React.useState(BLANK_LEAD);
  const [addSaving, setAddSaving] = React.useState(false);
  const [addError, setAddError] = React.useState("");
  const [payCurrency, setPayCurrency] = React.useState("USD");
  const [payType, setPayType] = React.useState("one_time");
  const [months, setMonths] = React.useState(3);
  const [monthAmts, setMonthAmts] = React.useState([]);
  // Even split with the last month absorbing any rounding remainder.
  const splitAmount = (total, n) => {
    total = Number(total) || 0; n = Math.max(2, Math.min(12, Number(n) || 2));
    const per = Math.floor((total / n) * 100) / 100;
    const arr = Array(n).fill(per);
    arr[n - 1] = Math.round((total - per * (n - 1)) * 100) / 100;
    return arr;
  };
  const sumAmts = (arr) => arr.reduce((a, b) => a + (Number(b) || 0), 0);

  const load = React.useCallback(() => {
    setLoading(true);
    apiFetch(`/admin/inquiries?status=${tab}&limit=100`).then(r=>r.json())
      .then(d => setList(d.data || [])).finally(()=>setLoading(false));
  }, [tab]);
  React.useEffect(load, [load]);

  const selected = selectedId ? list.find(i=>i.id===selectedId) : null;
  const openRow = (i) => {
    setSelectedId(i.id);
    setLinkResult(null); setCopied("");
    setPayType(i.payment_type === "monthly" ? "monthly" : "one_time");
    setMonths(3); setMonthAmts([]);
    setEdit({ negotiated_amount: i.negotiated_amount ?? "", intended_amount: i.intended_amount ?? "", source: i.source || "manual", notes: i.notes ?? "", status: i.status });
  };

  const patch = async (id, body) => {
    setSaving(true);
    await apiFetch(`/admin/inquiries/${id}`, { method:"PATCH", body: JSON.stringify(body) });
    load(); setSaving(false);
  };
  const saveEdit = () => patch(selectedId, {
    status: edit.status,
    negotiated_amount: edit.negotiated_amount === "" ? undefined : Number(edit.negotiated_amount),
    intended_amount: edit.intended_amount === "" ? undefined : Number(edit.intended_amount),
    source: edit.source || undefined,
    notes: edit.notes,
    payment_mode: edit.negotiated_amount !== "" ? "negotiated" : undefined,
  });
  const markJoined = (id) => patch(id, { status:"joined", payment_status:"paid" });

  const createLead = async (e) => {
    e.preventDefault(); setAddError("");
    const f = addForm;
    if (!f.parent_name && !f.email && !f.phone && !f.child_name) { setAddError("Add at least a name, email, phone, or child name."); return; }
    setAddSaving(true);
    const payload = {
      parent_name: f.parent_name || undefined,
      email: f.email || undefined,
      phone: f.phone || undefined,
      child_name: f.child_name || undefined,
      child_age: f.child_age ? Number(f.child_age) : undefined,
      plan_label: f.plan_label || undefined,
      intended_amount: f.intended_amount === "" ? undefined : Number(f.intended_amount),
      notes: f.notes || undefined,
      source: f.source || "manual",
      status: f.status || "inquired",
    };
    const res = await apiFetch("/admin/inquiries", { method:"POST", body: JSON.stringify(payload) });
    const data = await res.json().catch(()=>({}));
    setAddSaving(false);
    if (!res.ok) { setAddError(data.error || "Could not add lead"); return; }
    setShowAdd(false); setAddForm(BLANK_LEAD); load();
  };

  const generateLink = async (i) => {
    const body = { currency: payCurrency };
    if (payType === "monthly") {
      const amts = monthAmts.map(Number);
      const total = Number(amountOf(i)) || 0;
      if (Math.abs(sumAmts(amts) - total) > 0.5) { alert(`The monthly amounts add up to ${sumAmts(amts)}, but the total is ${total}.`); return; }
      body.payment_type = "monthly";
      body.installments = amts;
    }
    setGenLink(true); setLinkResult(null); setCopied("");
    const res = await apiFetch(`/admin/inquiries/${i.id}/payment-link`, { method:"POST", body: JSON.stringify(body) });
    const data = await res.json().catch(()=>({}));
    setGenLink(false);
    if (!res.ok) { alert(data.error || "Could not generate payment link"); return; }
    setLinkResult(data);
    load();
  };
  const copy = (text, which) => {
    navigator.clipboard?.writeText(text).then(()=>{ setCopied(which); setTimeout(()=>setCopied(""), 1500); }).catch(()=>{});
  };

  const convert = async (i) => {
    if (!confirm(`Convert "${i.child_name || i.parent_name}" into a student${i.email ? " + parent login" : ""}?`)) return;
    setSaving(true);
    const res = await apiFetch(`/admin/inquiries/${i.id}/convert`, { method:"POST", body: JSON.stringify({}) });
    const data = await res.json().catch(()=>({}));
    setSaving(false);
    if (!res.ok) { alert(data.error || "Convert failed"); return; }
    setConvertResult(data);
    load();
  };

  const fmt$ = (n) => n == null || n === "" ? "—" : "$" + Number(n).toLocaleString();
  const amountOf = (i) => i.negotiated_amount ?? i.intended_amount;

  return (
    <Themed className={dark?"theme-dark":""} style={{ width:"100%", height:"100%", display:"flex" }}>
      {convertResult && (
        <Modal title="Converted to student ✓" onClose={()=>setConvertResult(null)}>
          <div style={{ fontSize:13, color:"var(--ink-soft)", lineHeight:1.6 }}>
            <div>Student <b>{convertResult.student?.name}</b> created.</div>
            {convertResult.parent_login_created ? (
              <div style={{ marginTop:12, padding:14, background:"var(--paper-deep)", borderRadius:10, border:"var(--border-thin)" }}>
                <div style={{ fontSize:11, color:"var(--ink-mute)", marginBottom:6 }}>PARENT LOGIN — share this once</div>
                <div><b>Email:</b> {convertResult.parent_email}</div>
                <div><b>Temp password:</b> <span className="mono" style={{ color:"var(--coral)" }}>{convertResult.temp_password}</span></div>
                <div style={{ fontSize:11, color:"var(--ink-mute)", marginTop:6 }}>They'll be asked to change it on first login.</div>
              </div>
            ) : convertResult.parent_email ? (
              <div style={{ marginTop:10, fontSize:12, color:"var(--ink-mute)" }}>A user with {convertResult.parent_email} already existed — no new login created.</div>
            ) : (
              <div style={{ marginTop:10, fontSize:12, color:"var(--ink-mute)" }}>No email on the lead, so no parent login was created. Add one via Users if needed.</div>
            )}
          </div>
          <div style={{ display:"flex", justifyContent:"flex-end", marginTop:16 }}>
            <button onClick={()=>setConvertResult(null)} className="btn btn-primary">Done</button>
          </div>
        </Modal>
      )}
      {showAdd && (
        <Modal title="Add lead" onClose={()=>setShowAdd(false)}>
          <form onSubmit={createLead}>
            <div style={{ display:"grid", gridTemplateColumns:"1fr 1fr", gap:12 }}>
              <FormField label="PARENT NAME">
                <input style={inputStyle} value={addForm.parent_name} onChange={e=>setAddForm(f=>({...f,parent_name:e.target.value}))} placeholder="e.g. Priya Sharma"/>
              </FormField>
              <FormField label="CHILD NAME">
                <input style={inputStyle} value={addForm.child_name} onChange={e=>setAddForm(f=>({...f,child_name:e.target.value}))} placeholder="e.g. Aarav"/>
              </FormField>
              <FormField label="EMAIL">
                <input type="email" style={inputStyle} value={addForm.email} onChange={e=>setAddForm(f=>({...f,email:e.target.value}))} placeholder="parent@email.com"/>
              </FormField>
              <FormField label="PHONE">
                <input style={inputStyle} value={addForm.phone} onChange={e=>setAddForm(f=>({...f,phone:e.target.value}))} placeholder="+91…"/>
              </FormField>
              <FormField label="CHILD AGE">
                <input type="number" min="2" max="100" style={inputStyle} value={addForm.child_age} onChange={e=>setAddForm(f=>({...f,child_age:e.target.value}))} placeholder="8"/>
              </FormField>
              <FormField label="PLAN INTEREST">
                <input style={inputStyle} value={addForm.plan_label} onChange={e=>setAddForm(f=>({...f,plan_label:e.target.value}))} placeholder="e.g. Pay-in-Full"/>
              </FormField>
              <FormField label="OFFERED AMOUNT">
                <input type="number" min="0" style={inputStyle} value={addForm.intended_amount} onChange={e=>setAddForm(f=>({...f,intended_amount:e.target.value}))} placeholder="0"/>
              </FormField>
              <FormField label="SOURCE">
                <select style={selectStyle} value={addForm.source} onChange={e=>setAddForm(f=>({...f,source:e.target.value}))}>
                  {LEAD_SOURCES.map(([v,l])=><option key={v} value={v}>{l}</option>)}
                </select>
              </FormField>
              <FormField label="STATUS">
                <select style={selectStyle} value={addForm.status} onChange={e=>setAddForm(f=>({...f,status:e.target.value}))}>
                  {INQ_TABS.filter(t=>t!=="all").map(s=><option key={s} value={s}>{s[0].toUpperCase()+s.slice(1)}</option>)}
                </select>
              </FormField>
            </div>
            <FormField label="NOTES">
              <textarea style={{ ...inputStyle, minHeight:64, resize:"vertical" }} value={addForm.notes} onChange={e=>setAddForm(f=>({...f,notes:e.target.value}))} placeholder="How they reached out, what they want…"/>
            </FormField>
            {addError && <div style={{ color:"var(--coral)", fontSize:13, marginBottom:10 }}>{addError}</div>}
            <div style={{ display:"flex", gap:10, justifyContent:"flex-end", marginTop:4 }}>
              <button type="button" onClick={()=>setShowAdd(false)} className="btn btn-ghost">Cancel</button>
              <button type="submit" disabled={addSaving} className="btn btn-primary">{addSaving ? "Adding…" : "Add lead"}</button>
            </div>
          </form>
        </Modal>
      )}
      <AdminSidebar active="/app/admin/leads" go={go}/>
      <div style={{ flex:1, display:"flex", minWidth:0, background:"var(--paper)" }}>
        {/* List */}
        <div style={{ flex: selected ? "0 0 55%" : 1, display:"flex", flexDirection:"column", minWidth:0 }}>
          <div style={{ padding:"12px 22px", borderBottom:"var(--border-thin)", background:"var(--paper-card)", display:"flex", alignItems:"center", gap:12, flexWrap:"wrap" }}>
            <div>
              <div className="display" style={{ fontSize:20 }}>Leads</div>
              <div className="mono" style={{ fontSize:10, color:"var(--ink-mute)" }}>{list.length} {tab==="all"?"total":tab}</div>
            </div>
            <div style={{ flex:1 }}/>
            <Tabs items={INQ_TABS.map(t=>t[0].toUpperCase()+t.slice(1))} active={tab[0].toUpperCase()+tab.slice(1)} onChange={(t)=>{setTab(t.toLowerCase()); setSelectedId(null);}}/>
            <button onClick={()=>{ setAddForm(BLANK_LEAD); setAddError(""); setShowAdd(true); }} className="btn btn-primary" style={{ padding:"6px 14px", fontSize:12, display:"inline-flex", alignItems:"center", gap:5 }}>{I.plus({ size:14 })} Add lead</button>
          </div>
          <div style={{ flex:1, overflow:"auto", padding:18 }}>
            {loading ? <Spinner/> : list.length === 0 ? (
              <div style={{ textAlign:"center", padding:60, color:"var(--ink-mute)" }}>
                <div style={{ fontSize:32, marginBottom:8 }}>📥</div>
                <div style={{ fontWeight:700, fontSize:15 }}>No leads {tab!=="all"?`in "${tab}"`:"yet"}</div>
                <div style={{ fontSize:13, marginTop:4 }}>New reservations from the website appear here.</div>
              </div>
            ) : (
              <table style={{ width:"100%", borderCollapse:"collapse", fontSize:13 }}>
                <thead>
                  <tr>{["Parent","Child","Plan","Amount","Status",""].map(h=>(
                    <th key={h} style={{ padding:"8px 10px", fontWeight:600, fontSize:11, borderBottom:"var(--border-thin)", textAlign:"left", color:"var(--ink-mute)" }}>{h}</th>
                  ))}</tr>
                </thead>
                <tbody>
                  {list.map((i,idx)=>(
                    <tr key={i.id} onClick={()=>openRow(i)} style={{ borderTop: idx?"var(--border-thin)":"none", cursor:"pointer", background: selectedId===i.id?"var(--paper-deep)":"transparent" }}>
                      <td style={{ padding:"10px", fontWeight:700 }}>{i.parent_name || "—"}<div style={{ fontSize:11, color:"var(--ink-mute)", fontWeight:400 }}>{i.email || i.phone || ""}</div></td>
                      <td style={{ padding:"10px", color:"var(--ink-soft)" }}>{i.child_name || "—"}{i.child_age?` · ${i.child_age}`:""}</td>
                      <td style={{ padding:"10px", color:"var(--ink-soft)", fontSize:12 }}>{i.plan_label || "—"}</td>
                      <td style={{ padding:"10px", fontWeight:700 }}>{fmt$(amountOf(i))}</td>
                      <td style={{ padding:"10px" }}><span style={{ fontSize:10, fontWeight:700, padding:"2px 8px", borderRadius:999, background:INQ_COLOR[i.status]||"var(--sky)", color:"white" }}>{i.status}</span></td>
                      <td style={{ padding:"10px", fontSize:11, color:"var(--ink-mute)", whiteSpace:"nowrap" }}>{new Date(i.created_at).toLocaleDateString("en-IN",{day:"numeric",month:"short"})}</td>
                    </tr>
                  ))}
                </tbody>
              </table>
            )}
          </div>
        </div>

        {/* Detail */}
        {selected && (
          <div style={{ flex:1, borderLeft:"var(--border-thin)", background:"var(--paper-card)", overflow:"auto", padding:22, minWidth:0 }}>
            <div style={{ display:"flex", alignItems:"flex-start", gap:10 }}>
              <div style={{ flex:1 }}>
                <div className="display" style={{ fontSize:18 }}>{selected.parent_name || "Lead"}</div>
                <div style={{ fontSize:12, color:"var(--ink-mute)" }}>{selected.email || "—"}{selected.phone?` · ${selected.phone}`:""}</div>
              </div>
              <button onClick={()=>setSelectedId(null)} style={{ background:"none", border:"none", fontSize:20, cursor:"pointer", color:"var(--ink-mute)", lineHeight:1 }}>×</button>
            </div>

            <div style={{ display:"grid", gridTemplateColumns:"1fr 1fr", gap:10, margin:"16px 0", fontSize:13 }}>
              {[["Child", `${selected.child_name||"—"}${selected.child_age?` · ${selected.child_age}`:""}`],
                ["Plan interest", selected.plan_label||"—"],
                ["Offered amount", fmt$(selected.intended_amount)],
                ["Source", selected.source]].map(([l,v])=>(
                <div key={l} className="card-flat" style={{ padding:"8px 12px" }}>
                  <div className="mono" style={{ fontSize:10, color:"var(--ink-mute)" }}>{l.toUpperCase()}</div>
                  <div style={{ fontWeight:600, marginTop:2 }}>{v}</div>
                </div>
              ))}
            </div>
            {selected.message && (
              <div style={{ padding:12, background:"var(--paper-deep)", borderRadius:10, border:"var(--border-thin)", fontSize:13, marginBottom:16 }}>
                <div className="mono" style={{ fontSize:10, color:"var(--ink-mute)", marginBottom:4 }}>MESSAGE</div>{selected.message}
              </div>
            )}

            <div style={{ display:"grid", gridTemplateColumns:"1fr 1fr", gap:10 }}>
              <FormField label="STATUS">
                <select style={selectStyle} value={edit.status} onChange={e=>setEdit(s=>({...s,status:e.target.value}))}>
                  {["inquired","negotiating","joined","enrolled","completed","lost"].map(s=><option key={s} value={s}>{s}</option>)}
                </select>
              </FormField>
              <FormField label="SOURCE">
                <select style={selectStyle} value={edit.source} onChange={e=>setEdit(s=>({...s,source:e.target.value}))}>
                  {INQ_SOURCES.map(s=><option key={s} value={s}>{s}</option>)}
                </select>
              </FormField>
            </div>
            <div style={{ display:"grid", gridTemplateColumns:"1fr 1fr", gap:10 }}>
              <FormField label="OFFERED AMOUNT">
                <input type="number" min="0" style={inputStyle} value={edit.intended_amount} onChange={e=>setEdit(s=>({...s,intended_amount:e.target.value}))} placeholder="e.g. 12000"/>
              </FormField>
              <FormField label="NEGOTIATED AMOUNT">
                <input type="number" min="0" style={inputStyle} value={edit.negotiated_amount} onChange={e=>setEdit(s=>({...s,negotiated_amount:e.target.value}))} placeholder="overrides offered"/>
              </FormField>
            </div>
            <FormField label="NOTES">
              <textarea rows={3} style={{ ...inputStyle, resize:"vertical" }} value={edit.notes} onChange={e=>setEdit(s=>({...s,notes:e.target.value}))} placeholder="Call notes, agreed terms…"/>
            </FormField>

            <div style={{ display:"flex", gap:8, flexWrap:"wrap", marginTop:6 }}>
              <button onClick={saveEdit} disabled={saving} className="btn btn-primary" style={{ padding:"8px 16px", fontSize:12 }}>{saving?"Saving…":"Save"}</button>
              {selected.payment_status!=="paid" && selected.status!=="enrolled" && (
                <button onClick={()=>markJoined(selected.id)} disabled={saving} className="btn btn-ghost" style={{ padding:"8px 14px", fontSize:12, color:"var(--moss)" }}>✓ Mark joined</button>
              )}
              {!selected.student_id && (
                <button onClick={()=>convert(selected)} disabled={saving} className="btn btn-go" style={{ padding:"8px 14px", fontSize:12 }}>Convert to student →</button>
              )}
              {selected.student_id && <span className="chip flat" style={{ fontSize:11, background:"var(--moss)", color:"white" }}>Enrolled · student #{selected.student_id}</span>}
            </div>

            {/* Payment slot — generate a Razorpay payment link + registration page */}
            <div style={{ marginTop:18, padding:14, background:"var(--paper-deep)", borderRadius:10, border:"var(--border-thin)" }}>
              <div className="mono" style={{ fontSize:10, color:"var(--ink-mute)", marginBottom:6 }}>PAYMENT</div>
              <div style={{ fontSize:13 }}>Amount due: <b>{fmt$(amountOf(selected))}</b> · {selected.payment_status==="paid" ? <span style={{color:"var(--moss)"}}>paid ✓</span> : "unpaid"}</div>
              {selected.payment_status!=="paid" && !selected.student_id && (
                <div style={{ display:"flex", flexDirection:"column", gap:8, marginTop:8 }}>
                  <div style={{ display:"flex", alignItems:"center", gap:8, flexWrap:"wrap" }}>
                    <select value={payCurrency} onChange={e=>setPayCurrency(e.target.value)} title="Payment currency" style={{ padding:"6px 8px", fontSize:11, border:"var(--border-thin)", borderRadius:8, background:"var(--paper-card)", color:"var(--ink)", fontFamily:"var(--font-ui)" }}>
                      <option value="USD">USD $</option>
                      <option value="INR">INR ₹</option>
                    </select>
                    <select value={payType} onChange={e=>{ const v=e.target.value; setPayType(v); if(v==="monthly") setMonthAmts(splitAmount(amountOf(selected), months)); }} title="Payment type" style={{ padding:"6px 8px", fontSize:11, border:"var(--border-thin)", borderRadius:8, background:"var(--paper-card)", color:"var(--ink)", fontFamily:"var(--font-ui)" }}>
                      <option value="one_time">One-time</option>
                      <option value="monthly">Monthly</option>
                    </select>
                  </div>
                  {payType==="monthly" && (
                    <div style={{ padding:"8px 10px", background:"var(--paper-card)", borderRadius:8, border:"var(--border-thin)" }}>
                      <div style={{ display:"flex", alignItems:"center", gap:8, marginBottom:6 }}>
                        <span style={{ fontSize:11, color:"var(--ink-mute)" }}>Months</span>
                        <input type="number" min="2" max="12" value={months} onChange={e=>{ const n=Math.max(2,Math.min(12,Number(e.target.value)||2)); setMonths(n); setMonthAmts(splitAmount(amountOf(selected), n)); }} style={{ width:50, padding:"4px 6px", fontSize:11, border:"var(--border-thin)", borderRadius:6, background:"var(--paper-deep)" }}/>
                        <span style={{ fontSize:10, color:"var(--ink-mute)" }}>auto-split, editable</span>
                      </div>
                      <div style={{ display:"flex", gap:6, flexWrap:"wrap" }}>
                        {monthAmts.map((a,idx)=>(
                          <div key={idx} style={{ display:"flex", flexDirection:"column", alignItems:"center" }}>
                            <span style={{ fontSize:9, color:"var(--ink-mute)" }}>M{idx+1}</span>
                            <input type="number" min="0" value={a} onChange={e=>{ const next=[...monthAmts]; next[idx]=e.target.value; setMonthAmts(next); }} style={{ width:64, padding:"4px 6px", fontSize:11, border:"var(--border-thin)", borderRadius:6, background:"var(--paper-deep)" }}/>
                          </div>
                        ))}
                      </div>
                      {(() => { const s=sumAmts(monthAmts), tot=Number(amountOf(selected))||0, ok=Math.abs(s-tot)<=0.5;
                        return <div style={{ fontSize:11, marginTop:6, color: ok?"var(--moss)":"var(--coral)" }}>Sum: {s} / {tot} {ok?"✓":"— must match total"}</div>; })()}
                    </div>
                  )}
                  <button onClick={()=>generateLink(selected)} disabled={genLink || !amountOf(selected)} title={!amountOf(selected) ? "Set an amount first" : "Create a Razorpay payment link + registration page"} className="btn btn-ghost" style={{ padding:"6px 12px", fontSize:11, opacity:(genLink||!amountOf(selected))?.5:1, alignSelf:"flex-start" }}>
                    {I.wallet({size:13})} {genLink ? "Generating…" : (selected.payment_link_url ? "Regenerate link" : "Generate link")} {payType==="monthly"?"(Month 1)":""}
                  </button>
                </div>
              )}
              {(linkResult || selected.payment_link_url) && (
                <div style={{ marginTop:10, display:"flex", flexDirection:"column", gap:8 }}>
                  {[["Payment link", (linkResult&&linkResult.payment_link_url) || selected.payment_link_url, "pay"],
                    ...(linkResult&&linkResult.register_url ? [["Registration page", linkResult.register_url, "reg"]] : [])
                  ].map(([label,url,key])=> url ? (
                    <div key={key}>
                      <div className="mono" style={{ fontSize:9, color:"var(--ink-mute)", marginBottom:3 }}>{label.toUpperCase()}</div>
                      <div style={{ display:"flex", gap:6, alignItems:"center" }}>
                        <input readOnly value={url} onFocus={e=>e.target.select()} style={{ ...inputStyle, fontSize:11, padding:"6px 8px" }}/>
                        <button onClick={()=>copy(url,key)} className="btn btn-ghost" style={{ padding:"6px 10px", fontSize:11, whiteSpace:"nowrap" }}>{copied===key?"Copied ✓":"Copy"}</button>
                      </div>
                    </div>
                  ) : null)}
                  {linkResult && selected.email && <div style={{ fontSize:11, color:"var(--ink-mute)" }}>Registration link emailed to {selected.email}.</div>}
                </div>
              )}
            </div>
          </div>
        )}
      </div>
    </Themed>
  );
};

const AdminSettings = ({ dark = true, go }) => {
  const [values, setValues] = React.useState({});
  const [loading, setLoading] = React.useState(true);
  const [savingKey, setSavingKey] = React.useState(null);
  const [savedKey, setSavedKey] = React.useState(null);

  React.useEffect(() => {
    apiFetch("/settings").then(r => r.ok ? r.json() : {}).then(d => setValues(d || {})).finally(() => setLoading(false));
  }, []);

  const setField = (k, v) => setValues(s => ({ ...s, [k]: v }));
  const saveField = async (k) => {
    setSavingKey(k); setSavedKey(null);
    const res = await apiFetch(`/settings/${k}`, { method:"PUT", body: JSON.stringify({ value: values[k] ?? "" }) });
    setSavingKey(null);
    if (res.ok) { setSavedKey(k); setTimeout(() => setSavedKey(c => c === k ? null : c), 1800); }
  };

  if (loading) return <Spinner/>;
  return (
  <Themed className={dark?"theme-dark":""} style={{ width:"100%", height:"100%", display:"flex" }}>
    <AdminSidebar active="/app/admin/settings" go={go}/>
    <div style={{ flex:1, display:"flex", flexDirection:"column", minWidth:0, background:"var(--paper)" }}>
      <div style={{ padding:"12px 22px", borderBottom:"var(--border-thin)", background:"var(--paper-card)" }}>
        <div className="display" style={{ fontSize:20 }}>Settings</div>
        <div className="mono" style={{ fontSize:10, color:"var(--ink-mute)" }}>Organisation, integrations & billing</div>
      </div>
      <div style={{ flex:1, overflow:"auto", padding:22, display:"flex", flexDirection:"column", gap:18 }}>
        {SETTINGS_SECTIONS.map(({section, fields})=>(
          <div key={section} className="card-flat" style={{ padding:20 }}>
            <div className="mono" style={{ fontSize:10, color:"var(--ink-mute)", letterSpacing:".08em", marginBottom:14 }}>{section}</div>
            <div style={{ display:"flex", flexDirection:"column", gap:12 }}>
              {fields.map(([k,l,ph])=>(
                <div key={k} style={{ display:"grid", gridTemplateColumns:"200px 1fr auto", alignItems:"center", gap:14 }}>
                  <div style={{ fontSize:13, fontWeight:600, color:"var(--ink-soft)" }}>{l}</div>
                  <input value={values[k] ?? ""} placeholder={ph} onChange={e=>setField(k, e.target.value)}
                    style={{ padding:"7px 12px", border:"var(--border-thin)", borderRadius:8, background:"var(--paper-deep)", fontSize:13, fontFamily:"var(--font-ui)", color:"var(--ink)", outline:"none" }}/>
                  <button onClick={()=>saveField(k)} disabled={savingKey===k} className="btn btn-ghost" style={{ padding:"6px 12px", fontSize:11, color: savedKey===k ? "var(--moss)" : "var(--ink)" }}>
                    {savingKey===k ? "Saving…" : savedKey===k ? "✓ Saved" : "Save"}
                  </button>
                </div>
              ))}
            </div>
          </div>
        ))}
      </div>
    </div>
  </Themed>
  );
};

// ── Admin: Quizzes (admin view across all batches) ────────────────────────────
const AdminQuizzes = ({ dark = true, go }) => {
  const { data: initQuizzes, loading } = useApi("/quizzes");
  const [quizzesLocal, setQuizzesLocal] = React.useState(null);
  const QUIZZES = quizzesLocal ?? initQuizzes;
  const refresh = () => apiFetch("/quizzes").then(r=>r.json()).then(setQuizzesLocal).catch(()=>{});
  // Admins own the content library, so they can remove any quiz outright —
  // questions, results and assignments go with it.
  const deleteQuiz = async (qz) => {
    if (!confirm(`Delete quiz "${qz.title}"?\n\nIts questions and all ${qz.submitted ?? 0} student result(s) are removed too. This cannot be undone.`)) return;
    const r = await apiFetch(`/quizzes/${qz.id}`, { method:"DELETE" });
    if (!r.ok) { const d = await r.json().catch(()=>({})); alert(d.error || "Could not delete this quiz."); return; }
    refresh();
  };
  const completed  = QUIZZES.filter(q => q.submitted > 0).length;
  const scored     = QUIZZES.filter(q => q.avgScore);
  const avgScore   = scored.length ? Math.round(scored.reduce((a,q)=>a+q.avgScore,0)/scored.length) : null;
  const passRate   = scored.length ? Math.round(scored.filter(q=>q.avgScore>=60).length/scored.length*100) : null;
  if (loading) return <Spinner />;
  return (
  <Themed className={dark?"theme-dark":""} style={{ width:"100%", height:"100%", display:"flex" }}>
    <AdminSidebar active="/app/admin/quizzes" go={go}/>
    <div style={{ flex:1, display:"flex", flexDirection:"column", minWidth:0, background:"var(--paper)" }}>
      <div style={{ display:"flex", alignItems:"center", gap:12, padding:"12px 22px", borderBottom:"var(--border-thin)", background:"var(--paper-card)" }}>
        <div>
          <div className="display" style={{ fontSize:20 }}>Quizzes</div>
          <div className="mono" style={{ fontSize:10, color:"var(--ink-mute)" }}>All batches · performance overview</div>
        </div>
        <div style={{ flex:1 }}/>
        <button className="btn btn-ghost" onClick={()=>go&&go("/app/teacher/quizzes")} style={{ padding:"6px 12px", fontSize:12 }}>Teacher view</button>
      </div>
      <div style={{ flex:1, overflow:"auto", padding:22, display:"flex", flexDirection:"column", gap:16 }}>
        <div style={{ display:"grid", gridTemplateColumns:"repeat(4,1fr)", gap:14 }}>
          {[
            { l:"TOTAL QUIZZES", v: QUIZZES.length,                        c:"var(--sky)"  },
            { l:"WITH RESPONSES",v: completed,                              c:"var(--moss)" },
            { l:"AVG SCORE",     v: avgScore  != null ? `${avgScore}%`:"—", c:"var(--coral)"},
            { l:"PASS RATE",     v: passRate  != null ? `${passRate}%`:"—", c:"var(--moss)" },
          ].map(k=>(
            <div key={k.l} className="card-flat" style={{ padding:14 }}>
              <div className="mono" style={{ fontSize:10, color:"var(--ink-mute)", letterSpacing:".06em" }}>{k.l}</div>
              <div className="display" style={{ fontSize:28, color:k.c, marginTop:4 }}>{k.v}</div>
            </div>
          ))}
        </div>
        {QUIZZES.length === 0 ? (
          <div style={{ textAlign:"center", padding:60, color:"var(--ink-mute)" }}>
            <div style={{ fontSize:32, marginBottom:12 }}>🧩</div>
            <div style={{ fontSize:16, fontWeight:700 }}>No quizzes yet</div>
            <div style={{ fontSize:13, marginTop:4 }}>Teachers can create quizzes from the Teacher view</div>
            <button onClick={()=>go&&go("/app/teacher/quizzes")} className="btn btn-ghost" style={{ marginTop:16 }}>Go to Teacher view →</button>
          </div>
        ) : (
          <table style={{ width:"100%", borderCollapse:"collapse", fontSize:13 }}>
            <thead>
              <tr style={{ textAlign:"left", color:"var(--ink-mute)" }}>
                {["Quiz","Batch","Questions","Assigned","Avg Score","Completed",""].map(h=>(
                  <th key={h} style={{ padding:"8px 12px", fontWeight:600, fontSize:11, borderBottom:"var(--border-thin)" }}>{h}</th>
                ))}
              </tr>
            </thead>
            <tbody>
              {QUIZZES.map((q,i)=>(
                <tr key={q.id} style={{ borderTop: i?"var(--border-thin)":"none" }}>
                  <td style={{ padding:"12px", fontWeight:700 }}>{q.title}</td>
                  <td style={{ padding:"12px", color:"var(--ink-soft)" }}>{q.batch}</td>
                  <td style={{ padding:"12px" }}>{q.questions}</td>
                  <td style={{ padding:"12px" }}><span className="mono" style={{ fontSize:11, color:"var(--ink-mute)" }}>{q.assigned}</span></td>
                  <td style={{ padding:"12px", fontWeight:700, color: q.avgScore ? q.avgScore>=80?"var(--moss)":"var(--gold)" : "var(--ink-mute)" }}>{q.avgScore ? `${q.avgScore}%` : "—"}</td>
                  <td style={{ padding:"12px" }}>{q.submitted ?? 0}/{q.total ?? 0}</td>
                  <td style={{ padding:"12px", textAlign:"right" }}>
                    <button onClick={()=>deleteQuiz(q)} style={{ fontSize:11, padding:"4px 10px", borderRadius:6, border:"var(--border-thin)", background:"transparent", color:"var(--coral)", cursor:"pointer", fontWeight:600 }}>Delete</button>
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
        )}
      </div>
    </div>
  </Themed>
  );
};

// ── Admin: User Accounts (superadmin) ─────────────────────────────────────────
const AdminUsers = ({ dark = true, go }) => {
  const { data: initUsers, loading } = useApi("/admin/users");
  const { data: STUDENTS } = useApi("/students");
  const { data: TEACHERS } = useApi("/teachers");
  const [users, setUsers] = React.useState(null);
  const [showAdd, setShowAdd] = React.useState(false);
  const [form, setForm] = React.useState({ email:"", password:"", role:"admin", name:"", student_id:"", teacher_id:"" });
  const [saving, setSaving] = React.useState(false);
  const [error, setError] = React.useState("");
  const list = asArray(users ?? initUsers);
  const roleColors = { student:"var(--sky)", parent:"var(--plum)", teacher:"var(--moss)", admin:"var(--coral)", superadmin:"var(--gold)" };

  const refresh = async () => setUsers(await apiList("/admin/users"));

  const addUser = async e => {
    e.preventDefault(); setError(""); setSaving(true);
    const res = await apiFetch("/admin/users", { method:"POST", body: JSON.stringify({
      email: form.email, password: form.password, role: form.role, name: form.name,
      student_id: form.student_id||null, teacher_id: form.teacher_id||null,
    })});
    const data = await res.json();
    if (!res.ok) { setError(data.error||"Failed"); setSaving(false); return; }
    await refresh();
    setForm({ email:"", password:"", role:"admin", name:"", student_id:"", teacher_id:"" });
    setShowAdd(false); setSaving(false);
  };

  const deleteUser = async id => {
    if (!confirm("Delete this user?")) return;
    try {
      const res = await apiFetch(`/admin/users/${id}`, { method:"DELETE" });
      if (!res.ok) {
        const d = await res.json().catch(()=>({}));
        alert(d.error || (res.status===401 ? "Your session expired — please sign in again." : "Could not delete this user."));
        return;
      }
      await refresh();
    } catch (e) {
      // Never leave the screen hung if the request/refresh throws.
      alert("Something went wrong deleting the user. Please refresh and try again.");
    }
  };

  const toggleStatus = async u => {
    const next = u.status === "suspended" ? "active" : "suspended";
    if (next === "suspended" && !confirm(`Suspend ${u.name || u.email}? Their active sessions will be revoked.`)) return;
    const res = await apiFetch(`/admin/users/${u.id}/status`, { method:"PATCH", body: JSON.stringify({ status: next }) });
    if (!res.ok) { const d = await res.json().catch(()=>({})); alert(d.error || "Failed"); return; }
    await refresh();
  };

  const resetPassword = async u => {
    const pw = prompt(`Set a new password for ${u.name || u.email} (min 8 chars). They'll be asked to change it on next login.`);
    if (pw == null) return;
    if (pw.length < 8) { alert("Password must be at least 8 characters."); return; }
    const res = await apiFetch(`/admin/users/${u.id}/password`, { method:"PATCH", body: JSON.stringify({ password: pw }) });
    if (!res.ok) { const d = await res.json().catch(()=>({})); alert(d.error || "Failed"); return; }
    alert("Password reset. The user's sessions were revoked.");
  };

  // Clears a failed-login lockout without changing the password — the usual fix
  // when a learner forgot theirs and tripped the attempt limit.
  const unlockUser = async u => {
    const res = await apiFetch(`/admin/users/${u.id}/unlock`, { method:"POST" });
    if (!res.ok) { const d = await res.json().catch(()=>({})); alert(d.error || "Could not unlock this account."); return; }
    await refresh();
  };

  if (loading) return <Spinner/>;
  return (
    <Themed className={dark?"theme-dark":""} style={{ width:"100%", height:"100%", display:"flex" }}>
      {showAdd && (
        <Modal title="Create user account" onClose={()=>setShowAdd(false)}>
          <form onSubmit={addUser}>
            <div style={{ display:"grid", gridTemplateColumns:"1fr 1fr", gap:10 }}>
              <div style={{ gridColumn:"1/-1" }}>
                <div style={{ fontSize:11, fontWeight:700, color:"var(--ink-mute)", marginBottom:4, letterSpacing:".06em" }}>FULL NAME</div>
                <input required style={{ width:"100%", padding:"9px 12px", borderRadius:10, border:"var(--border-thin)", background:"var(--paper-deep)", fontSize:14, fontFamily:"var(--font-ui)", color:"var(--ink)", boxSizing:"border-box", outline:"none" }} value={form.name} onChange={e=>setForm(f=>({...f,name:e.target.value}))} placeholder="e.g. Priya Raman"/>
              </div>
              {[["EMAIL","email","email","you@epiqminds.com"],["PASSWORD","password","password","min 6 chars"]].map(([l,k,t,ph])=>(
                <div key={k}>
                  <div style={{ fontSize:11, fontWeight:700, color:"var(--ink-mute)", marginBottom:4, letterSpacing:".06em" }}>{l}</div>
                  <input required type={t} style={{ width:"100%", padding:"9px 12px", borderRadius:10, border:"var(--border-thin)", background:"var(--paper-deep)", fontSize:14, fontFamily:"var(--font-ui)", color:"var(--ink)", boxSizing:"border-box", outline:"none" }} value={form[k]} onChange={e=>setForm(f=>({...f,[k]:e.target.value}))} placeholder={ph}/>
                </div>
              ))}
            </div>
            <div style={{ marginTop:10 }}>
              <div style={{ fontSize:11, fontWeight:700, color:"var(--ink-mute)", marginBottom:4, letterSpacing:".06em" }}>ROLE</div>
              <select style={{ width:"100%", padding:"9px 12px", borderRadius:10, border:"var(--border-thin)", background:"var(--paper-deep)", fontSize:14, fontFamily:"var(--font-ui)", color:"var(--ink)", outline:"none" }} value={form.role} onChange={e=>setForm(f=>({...f,role:e.target.value}))}>
                {["student","parent","teacher","admin","superadmin"].map(r=><option key={r} value={r}>{r}</option>)}
              </select>
            </div>
            {form.role === "student" && (
              <div style={{ marginTop:10 }}>
                <div style={{ fontSize:11, fontWeight:700, color:"var(--ink-mute)", marginBottom:4, letterSpacing:".06em" }}>LINK STUDENT PROFILE</div>
                <select style={{ width:"100%", padding:"9px 12px", borderRadius:10, border:"var(--border-thin)", background:"var(--paper-deep)", fontSize:14, fontFamily:"var(--font-ui)", color:"var(--ink)", outline:"none" }} value={form.student_id} onChange={e=>setForm(f=>({...f,student_id:e.target.value}))}>
                  <option value="">— optional —</option>
                  {STUDENTS.map(s=><option key={s.id} value={s.id}>{s.name}</option>)}
                </select>
              </div>
            )}
            {form.role === "teacher" && (
              <div style={{ marginTop:10 }}>
                <div style={{ fontSize:11, fontWeight:700, color:"var(--ink-mute)", marginBottom:4, letterSpacing:".06em" }}>LINK TEACHER PROFILE</div>
                <select style={{ width:"100%", padding:"9px 12px", borderRadius:10, border:"var(--border-thin)", background:"var(--paper-deep)", fontSize:14, fontFamily:"var(--font-ui)", color:"var(--ink)", outline:"none" }} value={form.teacher_id} onChange={e=>setForm(f=>({...f,teacher_id:e.target.value}))}>
                  <option value="">— optional —</option>
                  {TEACHERS.map(t=><option key={t.id} value={t.id}>{t.name}</option>)}
                </select>
              </div>
            )}
            {error && <div style={{ color:"var(--coral)", fontSize:13, marginTop:10 }}>{error}</div>}
            <div style={{ display:"flex", gap:10, justifyContent:"flex-end", marginTop:16 }}>
              <button type="button" onClick={()=>setShowAdd(false)} className="btn btn-ghost">Cancel</button>
              <button type="submit" disabled={saving} className="btn btn-primary">{saving?"Creating…":"Create account"}</button>
            </div>
          </form>
        </Modal>
      )}
      <AdminSidebar active="/app/admin/users" go={go}/>
      <div style={{ flex:1, display:"flex", flexDirection:"column", minWidth:0, background:"var(--paper)" }}>
        <div style={{ display:"flex", alignItems:"center", gap:12, padding:"12px 22px", borderBottom:"var(--border-thin)", background:"var(--paper-card)" }}>
          <div>
            <div className="display" style={{ fontSize:20 }}>User Accounts</div>
            <div className="mono" style={{ fontSize:10, color:"var(--ink-mute)" }}>{list.length} accounts</div>
          </div>
          <div style={{ flex:1 }}/>
          <button onClick={()=>setShowAdd(true)} className="btn btn-primary" style={{ padding:"6px 14px", fontSize:12 }}>{I.plus({size:14})} Create account</button>
        </div>
        <div style={{ flex:1, overflow:"auto", padding:22 }}>
          <table style={{ width:"100%", borderCollapse:"collapse", fontSize:13 }}>
            <thead>
              <tr>
                {["Name","Email","Role","Linked to","Status","Created",""].map(h=>(
                  <th key={h} style={{ padding:"8px 10px", fontWeight:600, fontSize:11, borderBottom:"var(--border-thin)", textAlign:"left", color:"var(--ink-mute)" }}>{h}</th>
                ))}
              </tr>
            </thead>
            <tbody>
              {list.map((u,i)=>{
                const suspended = u.status === "suspended";
                return (
                <tr key={u.id} style={{ borderTop:i?"var(--border-thin)":"none", opacity: suspended ? 0.6 : 1 }}>
                  <td style={{ padding:"10px 10px", fontWeight:700 }}>{u.name}</td>
                  <td style={{ padding:"10px 10px", color:"var(--ink-soft)", fontSize:12 }}>{u.email}</td>
                  <td style={{ padding:"10px 10px" }}>
                    <span style={{ fontSize:10, fontWeight:700, padding:"2px 8px", borderRadius:999, background:roleColors[u.role]||"var(--sky)", color:"white" }}>{u.role}</span>
                  </td>
                  <td style={{ padding:"10px 10px", fontSize:12, color:"var(--ink-soft)" }}>{u.student_name || u.teacher_name || "—"}</td>
                  <td style={{ padding:"10px 10px" }}>
                    <span style={{ fontSize:10, fontWeight:700, padding:"2px 8px", borderRadius:999, background: suspended ? "var(--coral)" : "var(--moss)", color:"white" }}>{suspended ? "suspended" : "active"}</span>
                    {u.locked && <span title={`Locked after ${u.failed_logins} failed sign-ins`} style={{ fontSize:10, fontWeight:700, padding:"2px 8px", borderRadius:999, background:"var(--gold)", color:"white", marginLeft:6 }}>locked</span>}
                  </td>
                  <td style={{ padding:"10px 10px", fontSize:11, color:"var(--ink-mute)" }}>{new Date(u.created_at).toLocaleDateString("en-IN",{day:"numeric",month:"short",year:"numeric"})}</td>
                  <td style={{ padding:"10px 10px", whiteSpace:"nowrap" }}>
                    {u.locked && <button onClick={()=>unlockUser(u)} style={{ fontSize:11, padding:"4px 10px", borderRadius:6, border:"1.5px solid var(--moss)", background:"transparent", color:"var(--moss)", cursor:"pointer", fontWeight:600, marginRight:6 }}>Unlock</button>}
                    <button onClick={()=>resetPassword(u)} style={{ fontSize:11, padding:"4px 10px", borderRadius:6, border:"var(--border-thin)", background:"transparent", color:"var(--ink-soft)", cursor:"pointer", fontWeight:600, marginRight:6 }}>Reset PW</button>
                    <button onClick={()=>toggleStatus(u)} style={{ fontSize:11, padding:"4px 10px", borderRadius:6, border:"var(--border-thin)", background:"transparent", color: suspended ? "var(--moss)" : "var(--gold)", cursor:"pointer", fontWeight:600, marginRight:6 }}>{suspended ? "Activate" : "Suspend"}</button>
                    <button onClick={()=>deleteUser(u.id)} style={{ fontSize:11, padding:"4px 10px", borderRadius:6, border:"var(--border-thin)", background:"transparent", color:"var(--coral)", cursor:"pointer", fontWeight:600 }}>Delete</button>
                  </td>
                </tr>
              );})}
            </tbody>
          </table>
        </div>
      </div>
    </Themed>
  );
};

// ── Admin: Roles & Permissions (superadmin RBAC) ──────────────────────────────
const AdminRoles = ({ dark = true, go, session = {} }) => {
  const { data: initRoles, loading } = useApi("/roles");
  const { data: initUsers, loading: usersLoading } = useApi("/admin/users");
  const { data: permCatalog } = useApi("/permissions", {});
  // Build the permission list from the backend catalog so it can never drift
  // out of sync with what the server actually enforces. Falls back to the
  // static PERM_LIST until the catalog loads.
  const permList = React.useMemo(() => {
    const cat = permCatalog && permCatalog.permissions;
    if (!cat || !Object.keys(cat).length) return PERM_LIST;
    return Object.entries(cat).map(([key, desc]) => ({
      key,
      label: key.replace(/_/g, " ").replace(/\b\w/g, c => c.toUpperCase()),
      desc,
    }));
  }, [permCatalog]);
  const [roles, setRoles] = React.useState(null);
  const [users, setUsers] = React.useState(null);
  const [selected, setSelected] = React.useState(null);
  const [editing, setEditing] = React.useState(null); // permissions array being edited
  const [showCreate, setShowCreate] = React.useState(false);
  const [newName, setNewName] = React.useState("");
  const [saving, setSaving] = React.useState(false);
  const [error, setError] = React.useState("");
  const [tab, setTab] = React.useState("roles"); // "roles" | "users"
  const [changingRole, setChangingRole] = React.useState(null); // userId being changed
  const list = asArray(roles ?? initRoles);
  const userList = asArray(users ?? initUsers);
  const role = selected ? list.find(r=>r.id===selected) : null;

  const refresh = async () => setRoles(asArray(await apiList("/roles")));
  const refreshUsers = async () => setUsers(await apiList("/admin/users"));

  const changeUserRole = async (uid, newRole) => {
    setChangingRole(uid);
    await apiFetch(`/admin/users/${uid}/role`, { method:"PATCH", body: JSON.stringify({ role: newRole }) });
    await refreshUsers();
    setChangingRole(null);
  };

  const openRole = r => {
    setSelected(r.id);
    setEditing([...(r.permissions||[])]);
  };

  const togglePerm = key => {
    setEditing(prev => prev.includes(key) ? prev.filter(p=>p!==key) : [...prev, key]);
  };

  const savePerms = async () => {
    setError(""); setSaving(true);
    const res = await apiFetch(`/roles/${selected}`, { method:"PATCH", body: JSON.stringify({ permissions: editing }) });
    if (!res.ok) {
      const d = await res.json().catch(() => ({}));
      setError(d.error || "Failed to save permissions"); setSaving(false); return;
    }
    await refresh();
    // If we just edited our own role, refresh live permissions so gates update.
    if (Session.user && list.find(r => r.id === selected)?.name === Session.user.role) {
      await authApi.me().catch(() => {});
    }
    setSaving(false);
  };

  const createRole = async e => {
    e.preventDefault(); setError(""); setSaving(true);
    const res = await apiFetch("/roles", { method:"POST", body: JSON.stringify({ name: newName, permissions: [] }) });
    const data = await res.json();
    if (!res.ok) { setError(data.error||"Failed"); setSaving(false); return; }
    await refresh(); setNewName(""); setShowCreate(false); setSaving(false);
  };

  const deleteRole = async id => {
    if (!confirm("Delete this role?")) return;
    const res = await apiFetch(`/roles/${id}`, { method:"DELETE" });
    if (!res.ok) { const d = await res.json(); alert(d.error); return; }
    setSelected(null); await refresh();
  };

  if (loading) return <Spinner/>;
  return (
    <Themed className={dark?"theme-dark":""} style={{ width:"100%", height:"100%", display:"flex" }}>
      {showCreate && (
        <Modal title="Create role" onClose={()=>setShowCreate(false)}>
          <form onSubmit={createRole}>
            <div style={{ marginBottom:14 }}>
              <div style={{ fontSize:11, fontWeight:700, color:"var(--ink-mute)", marginBottom:6, letterSpacing:".06em" }}>ROLE NAME</div>
              <input required style={{ width:"100%", padding:"9px 12px", borderRadius:10, border:"var(--border-thin)", background:"var(--paper-deep)", fontSize:14, fontFamily:"var(--font-ui)", color:"var(--ink)", boxSizing:"border-box", outline:"none" }} value={newName} onChange={e=>setNewName(e.target.value)} placeholder="e.g. coordinator"/>
            </div>
            {error && <div style={{ color:"var(--coral)", fontSize:13, marginBottom:12 }}>{error}</div>}
            <div style={{ display:"flex", gap:10, justifyContent:"flex-end" }}>
              <button type="button" onClick={()=>setShowCreate(false)} className="btn btn-ghost">Cancel</button>
              <button type="submit" disabled={saving} className="btn btn-primary">{saving?"Creating…":"Create role"}</button>
            </div>
          </form>
        </Modal>
      )}
      <AdminSidebar active="/app/admin/roles" go={go}/>
      <div style={{ flex:1, display:"flex", flexDirection:"column", minWidth:0, background:"var(--paper)" }}>
        {/* Tab bar */}
        <div style={{ display:"flex", alignItems:"center", gap:0, padding:"0 22px", borderBottom:"var(--border-thin)", background:"var(--paper-card)" }}>
          {[["roles","Roles & Permissions"],["users","User Assignments"]].map(([t,l])=>(
            <button key={t} onClick={()=>setTab(t)} style={{
              padding:"14px 18px", fontSize:13, fontWeight:700, border:"none", background:"transparent", cursor:"pointer",
              color: tab===t ? "var(--ink)" : "var(--ink-mute)",
              borderBottom: tab===t ? "2px solid var(--coral)" : "2px solid transparent",
              marginBottom:-1,
            }}>{l}</button>
          ))}
          <div style={{ flex:1 }}/>
          {tab === "roles" && session.role === "superadmin" && <button onClick={()=>setShowCreate(true)} className="btn btn-primary" style={{ padding:"6px 14px", fontSize:12 }}>{I.plus({size:12})} New role</button>}
        </div>

        {tab === "users" ? (
          <div style={{ flex:1, overflow:"auto", padding:22 }}>
            <div style={{ marginBottom:16 }}>
              <div className="display" style={{ fontSize:18 }}>User Assignments</div>
              <div style={{ fontSize:12, color:"var(--ink-mute)", marginTop:4 }}>Change the role assigned to each user account</div>
            </div>
            {usersLoading ? <Spinner/> : (
              <div className="card-flat" style={{ overflow:"hidden" }}>
                <table style={{ width:"100%", borderCollapse:"collapse" }}>
                  <thead>
                    <tr style={{ background:"var(--paper-deep)" }}>
                      {["Name","Email","Current Role","Change Role"].map(h=>(
                        <th key={h} style={{ padding:"10px 16px", textAlign:"left", fontSize:11, fontWeight:700, color:"var(--ink-mute)", letterSpacing:".06em" }}>{h.toUpperCase()}</th>
                      ))}
                    </tr>
                  </thead>
                  <tbody>
                    {userList.map((u,i)=>{
                      const roleColor = { superadmin:"var(--coral)", admin:"var(--plum)", teacher:"var(--sky)", student:"var(--moss)", parent:"var(--gold)" }[u.role] || "var(--ink-mute)";
                      return (
                        <tr key={u.id} style={{ borderTop: i ? "var(--border-thin)" : "none" }}>
                          <td style={{ padding:"12px 16px" }}>
                            <div style={{ display:"flex", alignItems:"center", gap:10 }}>
                              <Avatar name={(u.name||u.email)[0].toUpperCase()} color={roleColor} size={30}/>
                              <div style={{ fontWeight:700, fontSize:13 }}>{u.name || "—"}</div>
                            </div>
                          </td>
                          <td style={{ padding:"12px 16px", fontSize:12, color:"var(--ink-mute)" }}>{u.email}</td>
                          <td style={{ padding:"12px 16px" }}>
                            <span style={{ padding:"3px 10px", borderRadius:999, fontSize:11, fontWeight:700, background:roleColor, color:"white" }}>{u.role}</span>
                          </td>
                          <td style={{ padding:"12px 16px" }}>
                            <select
                              value={u.role}
                              disabled={changingRole === u.id}
                              onChange={e => changeUserRole(u.id, e.target.value)}
                              style={{ padding:"6px 10px", borderRadius:8, border:"var(--border-thin)", background:"var(--paper-deep)", fontSize:12, fontFamily:"var(--font-ui)", color:"var(--ink)", cursor:"pointer", outline:"none" }}
                            >
                              {["student","parent","teacher","admin","superadmin","content_manager"].map(r=>(
                                <option key={r} value={r}>{r.replace("_"," ")}</option>
                              ))}
                            </select>
                            {changingRole === u.id && <span style={{ marginLeft:8, fontSize:11, color:"var(--ink-mute)" }}>Saving…</span>}
                          </td>
                        </tr>
                      );
                    })}
                  </tbody>
                </table>
              </div>
            )}
          </div>
        ) : (

        <div style={{ flex:1, display:"flex", minWidth:0 }}>
        {/* Role list */}
        <div style={{ width:240, borderRight:"var(--border-thin)", display:"flex", flexDirection:"column", background:"var(--paper-card)" }}>
          <div style={{ padding:"12px 16px", borderBottom:"var(--border-thin)", display:"flex", alignItems:"center", gap:8 }}>
            <div className="display" style={{ fontSize:16, flex:1 }}>Roles</div>
          </div>
          <div style={{ flex:1, overflow:"auto", padding:10 }}>
            {list.map(r=>(
              <button key={r.id} onClick={()=>openRole(r)} style={{ display:"flex", alignItems:"center", gap:10, width:"100%", padding:"10px 12px", borderRadius:8, border:"none", marginBottom:4,
                background: selected===r.id?"var(--paper-deep)":"transparent", cursor:"pointer", textAlign:"left" }}>
                <div style={{ flex:1 }}>
                  <div style={{ fontWeight:700, fontSize:13, color:"var(--ink)" }}>{r.name}</div>
                  <div style={{ fontSize:10, color:"var(--ink-mute)", marginTop:1 }}>{(r.permissions||[]).length} permissions{r.is_system?" · system":""}</div>
                </div>
                {r.is_system && <span style={{ fontSize:9, padding:"2px 6px", borderRadius:999, background:"var(--paper-deep)", color:"var(--ink-mute)", fontWeight:600 }}>SYSTEM</span>}
              </button>
            ))}
          </div>
        </div>

        {/* Permissions editor */}
        {role && editing ? (
          <div style={{ flex:1, display:"flex", flexDirection:"column", overflow:"hidden" }}>
            <div style={{ padding:"12px 22px", borderBottom:"var(--border-thin)", background:"var(--paper-card)", display:"flex", alignItems:"center", gap:12 }}>
              <div>
                <div className="display" style={{ fontSize:18 }}>{role.name}</div>
                <div style={{ fontSize:11, color:"var(--ink-mute)" }}>{editing.length} permissions selected</div>
              </div>
              <div style={{ flex:1 }}/>
              {!role.is_system && <button onClick={()=>deleteRole(role.id)} style={{ fontSize:11, padding:"6px 12px", borderRadius:6, border:"var(--border-thin)", background:"transparent", color:"var(--coral)", cursor:"pointer", fontWeight:600 }}>Delete role</button>}
              <button onClick={savePerms} disabled={saving} className="btn btn-primary" style={{ padding:"6px 16px", fontSize:12 }}>{saving?"Saving…":"Save permissions"}</button>
            </div>
            {error && <div style={{ color:"var(--coral)", fontSize:13, padding:"8px 22px 0" }}>{error}</div>}
            <div style={{ flex:1, overflow:"auto", padding:22 }}>
              <div style={{ display:"grid", gridTemplateColumns:"repeat(auto-fill, minmax(280px,1fr))", gap:10 }}>
                {permList.map(p=>{
                  const active = editing.includes(p.key);
                  return (
                    <button key={p.key} type="button" onClick={()=>!role.is_system && togglePerm(p.key)}
                      title={p.desc || p.key}
                      style={{ display:"flex", alignItems:"center", gap:12, padding:"12px 16px", borderRadius:10, border:`2px solid ${active?"var(--coral)":"var(--rule)"}`,
                        background: active?"rgba(var(--coral-rgb),.07)":"var(--paper-card)",
                        cursor: role.is_system?"default":"pointer", textAlign:"left", width:"100%" }}>
                      <div style={{ width:20, height:20, borderRadius:6, border:`2px solid ${active?"var(--coral)":"var(--rule)"}`, background:active?"var(--coral)":"transparent", flexShrink:0, display:"grid", placeItems:"center" }}>
                        {active && <svg width="10" height="10" viewBox="0 0 12 12"><polyline points="2,6 5,9 10,3" fill="none" stroke="white" strokeWidth="2" strokeLinecap="round"/></svg>}
                      </div>
                      <div style={{ minWidth:0 }}>
                        <div style={{ fontSize:13, fontWeight:700, color:"var(--ink)" }}>{p.label}</div>
                        <div style={{ fontSize:10, color:"var(--ink-mute)", fontFamily:"var(--font-mono)" }}>{p.key}</div>
                      </div>
                    </button>
                  );
                })}
              </div>
            </div>
          </div>
        ) : (
          <div style={{ flex:1, display:"flex", alignItems:"center", justifyContent:"center", color:"var(--ink-mute)", flexDirection:"column", gap:10 }}>
            <div style={{ fontSize:32 }}>🔒</div>
            <div style={{ fontSize:14, fontWeight:600 }}>Select a role to manage permissions</div>
          </div>
        )}
        </div>
        )}
      </div>
    </Themed>
  );
};

// ── Admin: Parents directory ──────────────────────────────────────────────────
const AdminParents = ({ dark = true, go }) => {
  const { data: initParents, loading } = useApi("/parents");
  const [parents, setParents] = React.useState(null);
  const [q, setQ] = React.useState("");
  const [resetFor, setResetFor] = React.useState(null); // child_login_user_id being reset
  const [resetPw, setResetPw] = React.useState("");
  const [msg, setMsg] = React.useState("");
  const list = asArray(parents ?? initParents);

  const refresh = async () => setParents(await apiList("/parents"));

  const filtered = list.filter(p =>
    (p.name||"").toLowerCase().includes(q.toLowerCase()) ||
    (p.email||"").toLowerCase().includes(q.toLowerCase()) ||
    (p.child_name||"").toLowerCase().includes(q.toLowerCase())
  );

  const doReset = async (userId) => {
    setMsg("");
    if (resetPw.length < 8) { setMsg("Min 8 characters."); return; }
    const res = await apiFetch(`/admin/users/${userId}/password`, { method:"PATCH", body: JSON.stringify({ password: resetPw }) });
    const d = await res.json().catch(()=>({}));
    if (!res.ok) { setMsg(d.error || "Failed"); return; }
    setMsg("✓ Password reset."); setResetPw(""); setResetFor(null);
  };

  return (
    <Themed className={dark ? "theme-dark" : ""} style={{ width:"100%", height:"100%", display:"flex" }}>
      <AdminSidebar active="/app/admin/parents" go={go}/>
      <div style={{ flex:1, display:"flex", flexDirection:"column", minWidth:0 }}>
        <div style={{ display:"flex", alignItems:"center", gap:12, padding:"12px 22px", borderBottom:"var(--border-thin)", background:"var(--paper-card)" }}>
          <div>
            <div className="display" style={{ fontSize:22 }}>Parents</div>
            <div className="mono" style={{ fontSize:11, color:"var(--ink-mute)" }}>{list.length} parent account{list.length===1?"":"s"}</div>
          </div>
          <div style={{ flex:1 }}/>
          <input value={q} onChange={e=>setQ(e.target.value)} placeholder="Search name, email, child…"
            style={{ ...inputStyle, width:260 }}/>
        </div>
        <div style={{ flex:1, overflow:"auto", padding:22 }}>
          {loading ? <Spinner/> : filtered.length === 0 ? (
            <div style={{ textAlign:"center", padding:50, color:"var(--ink-mute)" }}>No parents found.</div>
          ) : (
            <table style={{ width:"100%", borderCollapse:"collapse", fontSize:13 }}>
              <thead>
                <tr style={{ textAlign:"left", color:"var(--ink-mute)" }}>
                  {["Parent","Login email","Recovery","Child","Joined",""].map(h=>(
                    <th key={h} style={{ padding:"8px 12px", fontWeight:600, fontSize:11, borderBottom:"var(--border-thin)" }}>{h}</th>
                  ))}
                </tr>
              </thead>
              <tbody>
                {filtered.map(p => (
                  <React.Fragment key={p.id}>
                    <tr style={{ borderTop:"var(--border-thin)" }}>
                      <td style={{ padding:"10px 12px", fontWeight:700 }}>{p.name}</td>
                      <td style={{ padding:"10px 12px", wordBreak:"break-all" }}>{p.email}</td>
                      <td style={{ padding:"10px 12px", color:"var(--ink-mute)" }}>{p.recovery_email || p.recovery_phone || "—"}</td>
                      <td style={{ padding:"10px 12px" }}>{p.child_name ? `${p.child_name}${p.child_age?` · ${p.child_age}`:""}` : "—"}</td>
                      <td style={{ padding:"10px 12px", color:"var(--ink-mute)" }}>{p.created}</td>
                      <td style={{ padding:"10px 12px", textAlign:"right", whiteSpace:"nowrap" }}>
                        <button onClick={()=>{ setResetFor(resetFor===p.id?null:p.id); setResetPw(""); setMsg(""); }} className="btn btn-ghost" style={{ fontSize:11, padding:"4px 10px" }}>Reset password</button>
                      </td>
                    </tr>
                    {resetFor === p.id && (
                      <tr>
                        <td colSpan={6} style={{ padding:"0 12px 12px" }}>
                          <div style={{ display:"flex", alignItems:"center", gap:8, flexWrap:"wrap", background:"var(--paper-deep)", borderRadius:8, padding:10 }}>
                            <span style={{ fontSize:12, color:"var(--ink-mute)" }}>Reset <b>{p.name}</b>'s login password:</span>
                            <input type="password" value={resetPw} onChange={e=>setResetPw(e.target.value)} placeholder="New password (8+)" style={{ ...inputStyle, width:200, padding:"6px 10px" }}/>
                            <button onClick={()=>doReset(p.id)} className="btn btn-primary" style={{ fontSize:12, padding:"6px 14px" }}>Save</button>
                            {p.child_login_user_id && (
                              <button onClick={()=>doReset(p.child_login_user_id)} className="btn btn-ghost" style={{ fontSize:12, padding:"6px 14px" }}>Reset child's login instead</button>
                            )}
                            {msg && <span style={{ fontSize:12, color: msg.startsWith("✓")?"var(--moss)":"var(--coral)" }}>{msg}</span>}
                          </div>
                        </td>
                      </tr>
                    )}
                  </React.Fragment>
                ))}
              </tbody>
            </table>
          )}
        </div>
      </div>
    </Themed>
  );
};

Object.assign(window, { AdminParents });

// ── Admin: Enrollments (payment funnel) ───────────────────────────────────────
const ENR_STATUS = {
  pending: "var(--ink-mute)", awaiting_payment: "var(--gold)", active: "var(--moss)",
  overdue: "var(--coral)", completed: "var(--sky)", cancelled: "var(--ink-mute)",
};
const INST_COLOR = { paid: "var(--moss)", pending: "var(--ink-mute)", overdue: "var(--coral)" };

const AdminEnrollments = ({ dark = true, go }) => {
  const { data: initRows, loading } = useApi("/admin/enrollments");
  const [rows, setRows] = React.useState(null);
  const [msg, setMsg] = React.useState("");
  const list = asArray(rows ?? initRows);

  const refresh = async () => setRows(await apiList("/admin/enrollments"));

  const markPaid = async (instId) => {
    setMsg("");
    const res = await apiFetch(`/admin/enrollments/installments/${instId}/mark-paid`, { method: "POST" });
    const d = await res.json().catch(() => ({}));
    if (!res.ok) { setMsg(d.error || "Failed"); return; }
    setMsg(d.temp_password ? `Provisioned. Temp password (share once): ${d.temp_password}` : "Marked paid.");
    refresh();
  };

  const toggleAccess = async (studentId, locked) => {
    const res = await apiFetch(`/students/${studentId}/access`, { method: "PATCH", body: JSON.stringify({ locked }) });
    if (res.ok) refresh();
  };

  return (
    <Themed className={dark ? "theme-dark" : ""} style={{ width:"100%", height:"100%", display:"flex" }}>
      <AdminSidebar active="/app/admin/enrollments" go={go}/>
      <div style={{ flex:1, display:"flex", flexDirection:"column", minWidth:0 }}>
        <div style={{ display:"flex", alignItems:"center", gap:12, padding:"12px 22px", borderBottom:"var(--border-thin)", background:"var(--paper-card)" }}>
          <div>
            <div className="display" style={{ fontSize:22 }}>Enrollments</div>
            <div className="mono" style={{ fontSize:11, color:"var(--ink-mute)" }}>{list.length} enrollment{list.length===1?"":"s"} · payment funnel</div>
          </div>
        </div>
        {msg && <div style={{ padding:"8px 22px", fontSize:12.5, color:"var(--moss)", background:"var(--paper-deep)", borderBottom:"var(--border-thin)" }}>{msg}</div>}
        <div style={{ flex:1, overflow:"auto", padding:22 }}>
          {loading ? <Spinner/> : list.length === 0 ? (
            <div style={{ textAlign:"center", padding:50, color:"var(--ink-mute)" }}>No enrollments yet. They appear here when someone enrolls from the website.</div>
          ) : (
            <div style={{ display:"flex", flexDirection:"column", gap:12 }}>
              {list.map(e => (
                <div key={e.id} className="card-flat" style={{ padding:14 }}>
                  <div style={{ display:"flex", alignItems:"center", gap:12, flexWrap:"wrap" }}>
                    <div style={{ flex:1, minWidth:180 }}>
                      <div style={{ fontWeight:700, fontSize:14 }}>{e.parent_name} · <span style={{ color:"var(--ink-soft)" }}>{e.child_name}{e.child_age?` (${e.child_age})`:""}</span></div>
                      <div style={{ fontSize:11.5, color:"var(--ink-mute)" }}>{e.email} · {e.plan} · ${e.total_amount} · {e.created}</div>
                    </div>
                    <span style={{ fontSize:11, fontWeight:700, padding:"2px 10px", borderRadius:999, background:ENR_STATUS[e.status]||"var(--ink-mute)", color:"white" }}>{e.status}</span>
                    {e.student_id && (
                      <button onClick={()=>toggleAccess(e.student_id, e.access_status!=='locked')} className="btn btn-ghost" style={{ fontSize:11, padding:"4px 10px", color: e.access_status==='locked'?"var(--moss)":"var(--coral)" }}>
                        {e.access_status==='locked' ? "🔓 Unlock" : "🔒 Lock"}
                      </button>
                    )}
                  </div>
                  <div style={{ display:"flex", gap:8, marginTop:10, flexWrap:"wrap" }}>
                    {asArray(e.installments).map(i => (
                      <div key={i.id} style={{ display:"flex", alignItems:"center", gap:6, padding:"5px 10px", borderRadius:8, background:"var(--paper-deep)", border:"var(--border-thin)" }}>
                        <span style={{ fontSize:10, fontWeight:700, color:INST_COLOR[i.status]||"var(--ink-mute)" }}>#{i.seq} ${i.amount} · {i.status}</span>
                        {i.due_date && i.status!=='paid' && <span style={{ fontSize:10, color:"var(--ink-mute)" }}>due {new Date(i.due_date).toLocaleDateString("en-GB",{day:"numeric",month:"short"})}</span>}
                        {i.status!=='paid' && <button onClick={()=>markPaid(i.id)} style={{ fontSize:10, padding:"2px 8px", borderRadius:6, border:"none", background:"var(--moss)", color:"white", cursor:"pointer", fontWeight:700 }}>Mark paid</button>}
                      </div>
                    ))}
                  </div>
                </div>
              ))}
            </div>
          )}
        </div>
      </div>
    </Themed>
  );
};

Object.assign(window, { AdminEnrollments });
