// Teacher-facing feature panels: quizzes, homework grading, analytics,
// messaging. Split out of the old features-more.jsx.

// Extract an 11-char YouTube id from any common link form (watch, youtu.be,
// embed, shorts, live) or a bare id. Returns "" if none — keeps the embed URL
// well-formed instead of injecting "null".
const ytId = (url) => {
  if (!url) return "";
  const m = String(url).match(/(?:v=|\/embed\/|\/shorts\/|\/live\/|youtu\.be\/)([a-zA-Z0-9_-]{11})/);
  return m ? m[1] : /^[a-zA-Z0-9_-]{11}$/.test(url) ? url : "";
};

// Fetch a stored course file (base64) and open it in a new tab. PDFs / text /
// images render inline; office formats (ppt/doc) will download — browsers can't
// preview those without an external viewer. MIME resolution is shared + case-
// insensitive (fileMimeType in shared.jsx) so png/webp/gif and odd-cased
// extensions preview instead of downloading.
const openCourseFile = async (courseId, fileId) => {
  if (!courseId || !fileId) return;
  const r = await apiFetch(`/course-files/${courseId}/${fileId}/data`);
  if (!r.ok) { alert("Could not open this file."); return; }
  const { file_data, file_type } = await r.json();
  const bin = atob(file_data), bytes = new Uint8Array(bin.length);
  for (let i = 0; i < bin.length; i++) bytes[i] = bin.charCodeAt(i);
  const url = URL.createObjectURL(new Blob([bytes], { type: fileMimeType(file_type) }));
  window.open(url, "_blank");
  setTimeout(() => URL.revokeObjectURL(url), 60000);
};

// Small icon-button style for inline edit/move/delete/publish controls.
const CTRL_BTN = { background:"none", border:"none", cursor:"pointer", fontSize:13, padding:"2px 5px", borderRadius:6, lineHeight:1 };

// ── Teacher: Quizzes ──────────────────────────────────────────────────────────
const TeacherQuizzes = ({ dark = false, go, session }) => {
  const [quizzes, setQuizzes] = React.useState(null);
  const { data: initQuizzes } = useApi("/quizzes");
  const { data: allBatches } = useApi("/batches");
  const { data: allCourses } = useApi("/courses/list");
  const list = quizzes ?? initQuizzes;

  const [activeQuiz, setActiveQuiz] = React.useState(null);
  const [view, setView] = React.useState("questions"); // "questions" | "results"
  const [questions, setQuestions] = React.useState([]);
  const [quizResults, setQuizResults] = React.useState([]);
  const [showCreate, setShowCreate] = React.useState(false);
  const [form, setForm] = React.useState({ title:"", batch_id:"", course_id:"", questions:"5", time_limit:"20 minutes" });
  const [saving, setSaving] = React.useState(false);
  const [error, setError] = React.useState("");

  // Question builder state
  const [qType, setQType] = React.useState("mcq");
  const [qText, setQText] = React.useState("");
  const [qOpts, setQOpts] = React.useState(["","","",""]);
  const [qCorrect, setQCorrect] = React.useState(0);
  const [qVideo, setQVideo] = React.useState("");
  const [qAdding, setQAdding] = React.useState(false);
  const [showAddQ, setShowAddQ] = React.useState(false);

  // Assignment dialog — mirrors the Homework "Create & assign" targeting so a
  // teacher can point an existing quiz at a whole course or a named few students.
  const [assignQuiz, setAssignQuiz] = React.useState(null);
  const [assignForm, setAssignForm] = React.useState({ course_id:"", batch_id:"" });
  const [assignMode, setAssignMode] = React.useState("all");   // all | selected
  const [roster, setRoster] = React.useState([]);
  const [selectedStudents, setSelectedStudents] = React.useState([]);
  const [assignSaving, setAssignSaving] = React.useState(false);
  const [assignMsg, setAssignMsg] = React.useState(null);

  // Quizzes this teacher has hidden from their own view. Hiding writes only to
  // their account — the Content LMS keeps the quiz for everyone else.
  const [showHidden, setShowHidden] = React.useState(false);
  const [hiddenIds, setHiddenIds] = React.useState([]);

  const quiz = activeQuiz ? list.find(q => q.id === activeQuiz) : null;

  const loadQuestions = (id) => apiFetch(`/quizzes/${id}/questions`).then(r => r.json()).then(setQuestions).catch(() => {});
  const loadResults  = (id) => apiFetch(`/quizzes/${id}/results`).then(r => r.json()).then(setQuizResults).catch(() => {});

  React.useEffect(() => {
    if (!activeQuiz) return;
    loadQuestions(activeQuiz);
    loadResults(activeQuiz);
  }, [activeQuiz]);

  React.useEffect(() => {
    if (allBatches.length && !form.batch_id) setForm(f => ({ ...f, batch_id: String(allBatches[0].id), course_id: String(allBatches[0].course_id || "") }));
  }, [allBatches.length]);

  const refresh = () => apiFetch(`/quizzes${showHidden ? "?include_hidden=1" : ""}`).then(r => r.json()).then(setQuizzes).catch(() => {});
  const refreshHidden = () => apiFetch("/hidden-items").then(r => r.ok ? r.json() : [])
    .then(rows => setHiddenIds((Array.isArray(rows)?rows:[]).filter(r => r.item_type === "quiz").map(r => r.item_id)))
    .catch(() => {});
  React.useEffect(() => { refreshHidden(); }, []);
  React.useEffect(() => { refresh(); }, [showHidden]);

  // ── Assign ─────────────────────────────────────────────────────────────────
  const loadRoster = (courseId) => {
    if (!courseId) { setRoster([]); return Promise.resolve(); }
    return apiFetch(`/courses/${courseId}/roster`).then(r => r.ok ? r.json() : [])
      .then(d => setRoster(Array.isArray(d) ? d : [])).catch(() => setRoster([]));
  };
  const openAssign = async (qz) => {
    setAssignQuiz(qz); setAssignMsg(null);
    setAssignForm({ course_id: qz.course_id ? String(qz.course_id) : "", batch_id: qz.batch_id ? String(qz.batch_id) : "" });
    await loadRoster(qz.course_id);
    const current = await apiFetch(`/quizzes/${qz.id}/assignees`).then(r => r.ok ? r.json() : { student_ids: [] }).catch(() => ({ student_ids: [] }));
    const ids = current.student_ids || [];
    setSelectedStudents(ids);
    setAssignMode(ids.length ? "selected" : "all");
  };
  const onAssignCourse = async (cid) => {
    setAssignForm(f => ({ ...f, course_id: cid }));
    setSelectedStudents([]);
    await loadRoster(cid);
  };
  const saveAssign = async () => {
    if (!assignForm.course_id) { setAssignMsg({ type:"err", text:"Pick a course" }); return; }
    if (assignMode === "selected" && !selectedStudents.length) { setAssignMsg({ type:"err", text:"Pick at least one student, or choose 'All students'." }); return; }
    setAssignSaving(true);
    const res = await apiFetch(`/quizzes/${assignQuiz.id}`, { method:"PATCH", body: JSON.stringify({
      course_id: parseInt(assignForm.course_id),
      batch_id: assignForm.batch_id ? parseInt(assignForm.batch_id) : null,
      student_ids: assignMode === "selected" ? selectedStudents : [],
    })});
    setAssignSaving(false);
    if (!res.ok) { const d = await res.json().catch(()=>({})); setAssignMsg({ type:"err", text: d.error || "Could not assign this quiz" }); return; }
    const who = assignMode === "selected" ? `${selectedStudents.length} student${selectedStudents.length===1?"":"s"}` : "the whole course";
    setAssignMsg({ type:"ok", text:`Assigned to ${who} ✓` });
    await refresh();
    setTimeout(() => setAssignQuiz(null), 900);
  };

  // ── Remove ─────────────────────────────────────────────────────────────────
  // `mine` comes from the server: true only for quizzes this user created. Those
  // can be deleted outright; everything else is Content-LMS material and is only
  // hidden from this teacher's own list.
  const deleteQuiz = async (qz) => {
    if (!confirm(`Delete quiz "${qz.title}"?\n\nYou created it, so this removes it everywhere — questions and student results included.`)) 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; }
    if (activeQuiz === qz.id) setActiveQuiz(null);
    refresh();
  };
  const hideQuiz = async (qz) => {
    if (!confirm(`Hide "${qz.title}" from your quiz list?\n\nIt stays in the Content LMS and students who have it keep it.`)) return;
    const r = await apiFetch("/hidden-items", { method:"POST", body: JSON.stringify({ item_type:"quiz", item_id: qz.id }) });
    if (!r.ok) { alert("Could not hide this quiz."); return; }
    if (activeQuiz === qz.id) setActiveQuiz(null);
    await refreshHidden(); refresh();
  };
  const unhideQuiz = async (qz) => {
    await apiFetch(`/hidden-items/quiz/${qz.id}`, { method:"DELETE" });
    await refreshHidden(); refresh();
  };

  const create = async e => {
    e.preventDefault(); setError(""); setSaving(true);
    const res = await apiFetch("/quizzes", { method:"POST", body: JSON.stringify({ title: form.title, batch_id: parseInt(form.batch_id), course_id: parseInt(form.course_id), questions: parseInt(form.questions)||5, time_limit: form.time_limit }) });
    const data = await res.json();
    if (!res.ok) { setError(data.error||"Failed"); setSaving(false); return; }
    await refresh(); setShowCreate(false); setSaving(false);
    setForm(f => ({ ...f, title:"", questions:"5", time_limit:"20 minutes" }));
  };

  const addQuestion = async () => {
    if (!qText.trim() || !activeQuiz) return;
    if (qType === "mcq" && qOpts.some(o => !o.trim())) { setError("Fill in all four options"); return; }
    if (qType === "video" && !qVideo.trim()) { setError("Add a video URL"); return; }
    setError(""); setQAdding(true);
    const res = await apiFetch(`/quizzes/${activeQuiz}/questions`, {
      method:"POST",
      body: JSON.stringify({ question: qText, type: qType, options: qType==="mcq" ? qOpts : [], correct_ans: qCorrect, video_url: qType==="video" ? qVideo : null })
    });
    if (!res.ok) {
      const d = await res.json().catch(() => ({}));
      setError(d.error || "Failed to add question"); setQAdding(false); return;
    }
    await loadQuestions(activeQuiz);
    await refresh();
    setQText(""); setQOpts(["","","",""]); setQCorrect(0); setQVideo(""); setQAdding(false); setShowAddQ(false);
  };

  const deleteQuestion = async (qid) => {
    await apiFetch(`/quiz-questions/${qid}`, { method:"DELETE" });
    await loadQuestions(activeQuiz);
    await refresh();
  };

  const TYPE_COLORS = { mcq:"var(--coral)", paragraph:"var(--moss)", video:"var(--sky)" };

  return (
    <Themed className={dark ? "theme-dark" : ""} style={{ width:"100%", height:"100%", display:"flex" }}>
      <TeacherSidebar active="/app/teacher/quizzes" go={go} session={session}/>
      <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 }}>Quizzes</div>
            <div className="mono" style={{ fontSize:11, color:"var(--ink-mute)" }}>{list.length} quizzes</div>
          </div>
          <div style={{ flex:1 }}/>
          {hiddenIds.length > 0 && (
            <button className="btn btn-ghost" onClick={() => setShowHidden(v=>!v)} style={{ padding:"6px 14px", fontSize:12 }}
              title="Quizzes you hid from your own list — the Content LMS still has them">
              {showHidden ? "Hide hidden" : `Show hidden (${hiddenIds.length})`}
            </button>
          )}
          <button className="btn btn-primary" onClick={() => setShowCreate(true)} style={{ padding:"6px 14px", fontSize:12 }}>{I.plus({ size:14 })} New quiz</button>
        </div>
        <div style={{ flex:1, display:"flex", overflow:"hidden" }}>
          {/* Quiz list */}
          <div style={{ width:320, borderRight:"var(--border-thin)", overflow:"auto", padding:16, display:"flex", flexDirection:"column", gap:10, flexShrink:0 }}>
            {list.length === 0 ? (
              <div style={{ textAlign:"center", padding:40, color:"var(--ink-mute)" }}>
                <div style={{ fontSize:32, marginBottom:10 }}>📝</div>
                <div style={{ fontWeight:700 }}>No quizzes yet</div>
                <button onClick={() => setShowCreate(true)} className="btn btn-primary" style={{ marginTop:14 }}>{I.plus({ size:14 })} Create quiz</button>
              </div>
            ) : list.map(q => {
              const hidden = hiddenIds.includes(q.id);
              const who = q.assigned_count ? `${q.assigned_count} student${q.assigned_count===1?"":"s"}` : "Whole course";
              return (
              <div key={q.id} onClick={() => { setActiveQuiz(q.id); setShowAddQ(false); setView("questions"); }}
                className="card-flat" style={{ padding:14, cursor:"pointer", borderLeft: activeQuiz===q.id ? "3px solid var(--coral)" : "3px solid transparent", opacity: hidden ? .55 : 1 }}>
                <div style={{ display:"flex", alignItems:"center", gap:10 }}>
                  <div style={{ width:36, height:36, borderRadius:10, background:"var(--plum)", color:"white", display:"grid", placeItems:"center", flexShrink:0 }}>{I.puzzle({ size:16 })}</div>
                  <div style={{ flex:1, minWidth:0 }}>
                    <div style={{ fontWeight:700, fontSize:13, overflow:"hidden", textOverflow:"ellipsis", whiteSpace:"nowrap" }}>{q.title}</div>
                    <div style={{ fontSize:11, color:"var(--ink-mute)" }}>{q.batch || q.course || "—"} · {q.questions} Qs</div>
                  </div>
                  {q.avgScore != null && <span style={{ fontWeight:800, fontSize:13, color:"var(--moss)" }}>{q.avgScore}%</span>}
                </div>
                <div style={{ display:"flex", alignItems:"center", gap:6, marginTop:10, flexWrap:"wrap" }}>
                  <span title={Array.isArray(q.assignees) && q.assignees.length ? q.assignees.join(", ") : ""}
                    style={{ fontSize:10, fontWeight:700, padding:"2px 8px", borderRadius:999, background: q.assigned_count ? "var(--plum)" : "var(--sky)", color:"white" }}>{who}</span>
                  {hidden && <span style={{ fontSize:10, fontWeight:700, padding:"2px 8px", borderRadius:999, background:"var(--ink-mute)", color:"white" }}>hidden for you</span>}
                  {!q.mine && !hidden && <span title="Authored in the Content LMS" style={{ fontSize:10, fontWeight:600, padding:"2px 8px", borderRadius:999, background:"var(--paper-deep)", color:"var(--ink-mute)" }}>content</span>}
                  <div style={{ flex:1 }}/>
                  <button onClick={e=>{ e.stopPropagation(); openAssign(q); }} className="btn btn-ghost" style={{ padding:"3px 10px", fontSize:11 }}>Assign</button>
                  {hidden ? (
                    <button onClick={e=>{ e.stopPropagation(); unhideQuiz(q); }} className="btn btn-ghost" style={{ padding:"3px 10px", fontSize:11, color:"var(--moss)" }}>Unhide</button>
                  ) : q.mine ? (
                    <button onClick={e=>{ e.stopPropagation(); deleteQuiz(q); }} className="btn btn-ghost" style={{ padding:"3px 10px", fontSize:11, color:"var(--coral)" }}>Delete</button>
                  ) : (
                    <button title="Remove from your list — stays in the Content LMS" onClick={e=>{ e.stopPropagation(); hideQuiz(q); }} className="btn btn-ghost" style={{ padding:"3px 10px", fontSize:11, color:"var(--ink-mute)" }}>Hide</button>
                  )}
                </div>
              </div>
            );})}
          </div>

          {/* Detail panel */}
          {quiz ? (
            <div style={{ flex:1, display:"flex", flexDirection:"column", overflow:"hidden" }}>
              <div style={{ padding:"12px 20px", borderBottom:"var(--border-thin)", background:"var(--paper-card)", display:"flex", alignItems:"center", gap:12 }}>
                <div>
                  <div className="display" style={{ fontSize:18 }}>{quiz.title}</div>
                  <div style={{ fontSize:12, color:"var(--ink-mute)" }}>
                    {quiz.batch || "—"} · {quiz.course || "—"} · Assigned {quiz.assigned} · {quiz.assigned_count ? `${quiz.assigned_count} student${quiz.assigned_count===1?"":"s"}` : "whole course"}
                  </div>
                </div>
                <div style={{ flex:1 }}/>
                <button className="btn btn-ghost" onClick={()=>openAssign(quiz)} style={{ padding:"6px 14px", fontSize:12 }}>{I.users({ size:14 })} Assign</button>
                <Tabs items={["Questions","Results"]} active={view==="questions"?"Questions":"Results"} onChange={v=>setView(v==="Questions"?"questions":"results")}/>
              </div>

              {view === "questions" ? (
                <div style={{ flex:1, overflow:"auto", padding:20, display:"flex", flexDirection:"column", gap:12 }}>
                  {questions.length === 0 && !showAddQ && (
                    <div style={{ textAlign:"center", padding:40, color:"var(--ink-mute)" }}>
                      <div style={{ fontSize:32, marginBottom:10 }}>🧩</div>
                      <div style={{ fontWeight:700 }}>No questions yet</div>
                      <div style={{ fontSize:13, marginTop:4 }}>Add your first question below</div>
                    </div>
                  )}
                  {questions.map((qq, i) => (
                    <div key={qq.id} className="card-flat" style={{ padding:14 }}>
                      <div style={{ display:"flex", alignItems:"flex-start", gap:10 }}>
                        <div style={{ width:24, height:24, borderRadius:"50%", background:"var(--paper-deep)", border:"var(--border-thin)", display:"grid", placeItems:"center", fontSize:11, fontWeight:800, flexShrink:0, marginTop:2 }}>{i+1}</div>
                        <div style={{ flex:1 }}>
                          <div style={{ display:"flex", alignItems:"center", gap:8, marginBottom:6 }}>
                            <span style={{ fontSize:10, fontWeight:700, padding:"2px 8px", borderRadius:999, background: TYPE_COLORS[qq.type||"mcq"], color:"white" }}>{(qq.type||"mcq").toUpperCase()}</span>
                          </div>
                          <div style={{ fontWeight:600, fontSize:14, marginBottom:8 }}>{qq.q}</div>
                          {(qq.type||"mcq") === "mcq" && qq.opts && (
                            <div style={{ display:"flex", flexDirection:"column", gap:4 }}>
                              {qq.opts.map((o,oi) => (
                                <div key={oi} style={{ display:"flex", alignItems:"center", gap:8, padding:"5px 10px", borderRadius:8, background: oi===qq.ans ? "var(--paper-card)" : "transparent", border: oi===qq.ans ? "1.5px solid var(--moss)" : "1px solid var(--rule)", fontSize:13 }}>
                                  <span style={{ color: oi===qq.ans ? "var(--moss)" : "var(--ink-mute)", fontWeight:700, fontSize:11 }}>{oi===qq.ans ? "✓" : String.fromCharCode(65+oi)}</span>
                                  {o}
                                </div>
                              ))}
                            </div>
                          )}
                          {(qq.type) === "video" && qq.video_url && (() => {
                            const m = qq.video_url.match(/(?:v=|youtu\.be\/)([a-zA-Z0-9_-]{11})/);
                            const vid = m ? m[1] : null;
                            return vid ? (
                              <div style={{ marginTop:8 }}><SafeYouTube videoId={vid} title="Video"/></div>
                            ) : (
                              <div style={{ fontSize:12, color:"var(--sky)", marginTop:4 }}>▶ {qq.video_url}</div>
                            );
                          })()}
                          {(qq.type) === "paragraph" && (
                            <div style={{ fontSize:12, color:"var(--ink-mute)", fontStyle:"italic" }}>Students write a free-text response</div>
                          )}
                        </div>
                        <button onClick={() => deleteQuestion(qq.id)} style={{ border:"none", background:"transparent", color:"var(--coral)", cursor:"pointer", padding:4, borderRadius:6 }}>{I.x({ size:16 })}</button>
                      </div>
                    </div>
                  ))}

                  {/* Add question form */}
                  {showAddQ ? (
                    <div className="card" style={{ padding:18 }}>
                      <div className="mono" style={{ fontSize:10, color:"var(--ink-mute)", marginBottom:10 }}>ADD QUESTION</div>
                      <div style={{ display:"flex", gap:8, marginBottom:12 }}>
                        {["mcq","paragraph","video"].map(t => (
                          <button key={t} onClick={() => setQType(t)} style={{ padding:"5px 14px", borderRadius:999, border:"var(--border-thin)", fontSize:12, fontWeight:700, cursor:"pointer", background: qType===t ? TYPE_COLORS[t] : "var(--paper-deep)", color: qType===t ? "white" : "var(--ink-mute)" }}>{t.toUpperCase()}</button>
                        ))}
                      </div>
                      <FormField label="QUESTION">
                        <input style={inputStyle} value={qText} onChange={e=>setQText(e.target.value)} placeholder="Enter your question…"/>
                      </FormField>
                      {qType === "mcq" && (
                        <>
                          <div className="mono" style={{ fontSize:10, color:"var(--ink-mute)", marginBottom:6, marginTop:4 }}>OPTIONS · click radio to mark correct</div>
                          {qOpts.map((o,i) => (
                            <div key={i} style={{ display:"flex", alignItems:"center", gap:8, marginBottom:8 }}>
                              <input type="radio" name="correct" checked={qCorrect===i} onChange={() => setQCorrect(i)} style={{ accentColor:"var(--moss)", width:16, height:16 }}/>
                              <input style={{ ...inputStyle, flex:1 }} value={o} onChange={e => { const n=[...qOpts]; n[i]=e.target.value; setQOpts(n); }} placeholder={`Option ${String.fromCharCode(65+i)}`}/>
                            </div>
                          ))}
                        </>
                      )}
                      {qType === "video" && (
                        <FormField label="YOUTUBE URL">
                          <input style={inputStyle} value={qVideo} onChange={e=>setQVideo(e.target.value)} placeholder="https://youtube.com/watch?v=…"/>
                        </FormField>
                      )}
                      {qType === "paragraph" && (
                        <div style={{ fontSize:12, color:"var(--ink-mute)", marginTop:4, padding:"8px 12px", background:"var(--paper-deep)", borderRadius:8 }}>Students will type a paragraph response to this question.</div>
                      )}
                      {error && <div style={{ color:"var(--coral)", fontSize:13, marginTop:10 }}>{error}</div>}
                      <div style={{ display:"flex", gap:8, marginTop:12 }}>
                        <button onClick={addQuestion} disabled={qAdding} className="btn btn-primary" style={{ padding:"8px 18px", fontSize:12 }}>{qAdding ? "Adding…" : "Add question"}</button>
                        <button onClick={() => { setShowAddQ(false); setError(""); }} className="btn btn-ghost" style={{ padding:"8px 14px", fontSize:12 }}>Cancel</button>
                      </div>
                    </div>
                  ) : (
                    <button onClick={() => setShowAddQ(true)} className="btn btn-ghost" style={{ padding:"10px 0", fontSize:13, border:"1.5px dashed var(--rule-bold)", borderRadius:12, width:"100%" }}>
                      {I.plus({ size:14 })} Add question
                    </button>
                  )}
                </div>
              ) : (
                <div style={{ flex:1, overflow:"auto", padding:20 }}>
                  {quizResults.length === 0 ? (
                    <div style={{ textAlign:"center", padding:40, color:"var(--ink-mute)" }}>No submissions yet.</div>
                  ) : quizResults.map((r,i) => (
                    <div key={i} style={{ display:"flex", alignItems:"center", gap:12, padding:"10px 0", borderTop: i ? "var(--border-thin)" : "none" }}>
                      <Avatar name={r.student[0]} color={r.color} size={32}/>
                      <div style={{ flex:1 }}>
                        <div style={{ fontWeight:600, fontSize:13 }}>{r.student}</div>
                        {r.time && <div style={{ fontSize:11, color:"var(--ink-mute)" }}>{r.time}</div>}
                      </div>
                      {r.status==="absent"
                        ? <span className="chip flat" style={{ fontSize:10, background:"var(--coral)", color:"white" }}>absent</span>
                        : <span style={{ fontWeight:800, fontSize:15, color: r.score>=80?"var(--moss)":r.score>=60?"var(--gold)":"var(--coral)" }}>{r.score}%</span>}
                    </div>
                  ))}
                  {quiz.avgScore && (
                    <div style={{ marginTop:20, padding:14, background:"var(--paper-deep)", borderRadius:12, border:"var(--border-thin)", textAlign:"center" }}>
                      <div style={{ fontSize:11, color:"var(--ink-mute)" }}>Class average</div>
                      <div className="display" style={{ fontSize:32, color:"var(--moss)" }}>{quiz.avgScore}%</div>
                    </div>
                  )}
                </div>
              )}
            </div>
          ) : (
            <div style={{ flex:1, display:"flex", alignItems:"center", justifyContent:"center", color:"var(--ink-mute)", flexDirection:"column", gap:10 }}>
              {I.puzzle({ size:32 })}
              <div style={{ fontSize:14 }}>Select a quiz to view and edit questions</div>
            </div>
          )}
        </div>
      </div>
      {assignQuiz && (
        <Modal title={`Assign "${assignQuiz.title}"`} onClose={() => setAssignQuiz(null)}>
          <div style={{ display:"flex", flexDirection:"column", gap:14 }}>
            <FormField label="COURSE">
              <select style={selectStyle} value={assignForm.course_id} onChange={e=>onAssignCourse(e.target.value)}>
                <option value="">Select course…</option>
                {allCourses.map(c => <option key={c.id} value={c.id}>{c.name} · {c.level}</option>)}
              </select>
            </FormField>
            <FormField label="BATCH (OPTIONAL)">
              <select style={selectStyle} value={assignForm.batch_id} onChange={e=>setAssignForm(f=>({...f,batch_id:e.target.value}))}>
                <option value="">No specific batch</option>
                {allBatches.map(b => <option key={b.id} value={b.id}>{b.name}</option>)}
              </select>
            </FormField>
            <FormField label="ASSIGN TO">
              <div style={{ display:"flex", gap:8, marginBottom: assignMode==="selected" ? 10 : 0 }}>
                {[["all","👥 All students in course"],["selected","☑ Selected students"]].map(([m,label])=>(
                  <button key={m} type="button" onClick={()=>setAssignMode(m)}
                    style={{ flex:1, padding:"8px 0", borderRadius:10, border:"var(--border-thin)", fontSize:12, fontWeight:700, cursor:"pointer",
                      background: assignMode===m ? "var(--coral)" : "var(--paper-deep)", color: assignMode===m ? "white" : "var(--ink-mute)" }}>{label}</button>
                ))}
              </div>
              {assignMode==="selected" && (
                <div style={{ border:"var(--border-thin)", borderRadius:8, padding:10, maxHeight:180, overflow:"auto", background:"var(--paper-deep)" }}>
                  {!assignForm.course_id ? (
                    <div style={{ fontSize:12, color:"var(--ink-mute)" }}>Select a course first.</div>
                  ) : roster.length===0 ? (
                    <div style={{ fontSize:12, color:"var(--ink-mute)" }}>No students in this course yet.</div>
                  ) : (
                    <>
                      <label style={{ display:"flex", alignItems:"center", gap:8, fontSize:12, fontWeight:700, paddingBottom:6, marginBottom:6, borderBottom:"var(--border-thin)", cursor:"pointer" }}>
                        <input type="checkbox" checked={selectedStudents.length===roster.length}
                          onChange={e=>setSelectedStudents(e.target.checked ? roster.map(s=>s.id) : [])}/>
                        Select all ({roster.length})
                      </label>
                      {roster.map(s=>(
                        <label key={s.id} style={{ display:"flex", alignItems:"center", gap:8, fontSize:13, padding:"4px 0", cursor:"pointer" }}>
                          <input type="checkbox" checked={selectedStudents.includes(s.id)}
                            onChange={e=>setSelectedStudents(cur => e.target.checked ? [...cur, s.id] : cur.filter(x=>x!==s.id))}/>
                          {s.name}
                        </label>
                      ))}
                      <div style={{ fontSize:11, color:"var(--ink-mute)", marginTop:6 }}>{selectedStudents.length} selected</div>
                    </>
                  )}
                </div>
              )}
            </FormField>
            {assignMsg && <div style={{ fontSize:13, fontWeight:600, color: assignMsg.type==="ok" ? "var(--moss)" : "var(--coral)" }}>{assignMsg.text}</div>}
            <div style={{ display:"flex", gap:10, justifyContent:"flex-end" }}>
              <button type="button" onClick={()=>setAssignQuiz(null)} className="btn btn-ghost">Cancel</button>
              <button type="button" onClick={saveAssign} disabled={assignSaving} className="btn btn-primary">{assignSaving ? "Assigning…" : "Assign quiz"}</button>
            </div>
          </div>
        </Modal>
      )}
      {showCreate && (
        <Modal title="Create quiz" onClose={() => { setShowCreate(false); setError(""); }}>
          <form onSubmit={create}>
            <FormField label="TITLE">
              <input required style={inputStyle} value={form.title} onChange={e=>setForm(f=>({...f,title:e.target.value}))} placeholder="e.g. Functions recap"/>
            </FormField>
            <FormField label="BATCH">
              <select required style={selectStyle} value={form.batch_id} onChange={e => {
                const b = allBatches.find(x => String(x.id) === e.target.value);
                setForm(f => ({ ...f, batch_id: e.target.value, course_id: b?.course_id ? String(b.course_id) : f.course_id }));
              }}>
                <option value="">Select batch…</option>
                {allBatches.map(b => <option key={b.id} value={b.id}>{b.name}</option>)}
              </select>
            </FormField>
            <FormField label="COURSE">
              <select required style={selectStyle} value={form.course_id} onChange={e=>setForm(f=>({...f,course_id:e.target.value}))}>
                <option value="">Select course…</option>
                {allCourses.map(c => <option key={c.id} value={c.id}>{c.name} · {c.level}</option>)}
              </select>
            </FormField>
            <FormField label="TIME LIMIT">
              <input style={inputStyle} value={form.time_limit} onChange={e=>setForm(f=>({...f,time_limit:e.target.value}))} placeholder="20 minutes"/>
            </FormField>
            {error && <div style={{ color:"var(--coral)", fontSize:13, marginBottom:10 }}>{error}</div>}
            <div style={{ display:"flex", gap:10, justifyContent:"flex-end", marginTop:4 }}>
              <button type="button" onClick={() => { setShowCreate(false); setError(""); }} className="btn btn-ghost">Cancel</button>
              <button type="submit" disabled={saving} className="btn btn-primary">{saving ? "Creating…" : "Create quiz"}</button>
            </div>
          </form>
        </Modal>
      )}
    </Themed>
  );
};

// ── Teacher: Homework Grading + Create ───────────────────────────────────────
const TeacherHomework = ({ dark = false, go, session }) => {
  const { data: HW_SUBMISSIONS } = useApi("/hw-submissions");
  const { data: allCourses } = useApi("/courses/list");
  const [tab, setTab] = React.useState("grade");
  const [active, setActive] = React.useState(null);
  const [grades, setGrades] = React.useState({});
  const [saving, setSaving] = React.useState(false);

  const [hwForm, setHwForm] = React.useState({ title:"", course_id:"", due_date:"", xp:"40", type:"paragraph", description:"", video_url:"" });
  const [hwSaving, setHwSaving] = React.useState(false);
  const [hwError, setHwError] = React.useState("");
  const [hwSuccess, setHwSuccess] = React.useState("");
  // Assignment targeting: "all" students in the course, or a "selected" subset.
  const [assignMode, setAssignMode] = React.useState("all");
  const [roster, setRoster] = React.useState([]);
  const [selectedStudents, setSelectedStudents] = React.useState([]);
  // Optional worksheet/reference file the teacher attaches to the homework.
  const [hwFile, setHwFile] = React.useState(null); // { id, title }
  const [hwUploading, setHwUploading] = React.useState(false);
  const attachHwFile = file => {
    if (!file) return;
    if (!hwForm.course_id) { setHwError("Pick a course before attaching a file."); return; }
    setHwError(""); setHwUploading(true);
    const ext = (file.name.split(".").pop() || "").toLowerCase();
    const reader = new FileReader();
    reader.onload = async () => {
      const base64 = String(reader.result).split(",")[1] || "";
      const res = await apiFetch("/course-files", { method:"POST", body: JSON.stringify({ course_id: parseInt(hwForm.course_id), title: file.name, file_type: ext, file_data: base64 }) });
      const d = await res.json().catch(()=>({}));
      if (!res.ok) { setHwError(d.error || "Upload failed"); setHwUploading(false); return; }
      setHwFile({ id: d.id, title: d.title }); setHwUploading(false);
    };
    reader.onerror = () => { setHwError("Could not read file"); setHwUploading(false); };
    reader.readAsDataURL(file);
  };

  // Load the course roster for the "selected students" picker.
  React.useEffect(() => {
    if (!hwForm.course_id) { setRoster([]); setSelectedStudents([]); return; }
    apiFetch(`/courses/${hwForm.course_id}/roster`).then(r=>r.ok?r.json():[]).then(d=>setRoster(Array.isArray(d)?d:[])).catch(()=>setRoster([]));
    setSelectedStudents([]);
  }, [hwForm.course_id]);

  // "Manage homework" list.
  const { data: initHwList } = useApi("/homework/manage");
  const [hwListLocal, setHwListLocal] = React.useState(null);
  const hwList = hwListLocal ?? (Array.isArray(initHwList) ? initHwList : []);
  const refreshHwList = () => apiFetch("/homework/manage").then(r=>r.json()).then(setHwListLocal).catch(()=>{});
  const deleteHw = async (id, title) => {
    if (!confirm(`Delete homework "${title}"? This also removes its submissions.`)) return;
    const r = await apiFetch(`/homework/${id}`, { method:"DELETE" });
    if (r.ok) refreshHwList();
  };

  const saveGrade = async () => {
    if (active == null || !grades[active]) return;
    const sub = HW_SUBMISSIONS[active];
    if (!sub) return;
    setSaving(true);
    await apiFetch(`/hw-submissions/${sub.id}`, { method:"PATCH", body: JSON.stringify({ grade: grades[active] }) }).catch(()=>{});
    setSaving(false);
    setActive(null);
  };

  const createHw = async e => {
    e.preventDefault(); setHwError(""); setHwSuccess("");
    if (assignMode === "selected" && !selectedStudents.length) { setHwError("Pick at least one student, or choose 'All students'."); return; }
    setHwSaving(true);
    const payload = { title: hwForm.title, course_id: parseInt(hwForm.course_id), due_date: hwForm.due_date || null, xp: parseInt(hwForm.xp)||40, type: hwForm.type||"paragraph", description: hwForm.description||"" };
    if (hwFile) payload.file_id = hwFile.id;
    if (assignMode === "selected") payload.student_ids = selectedStudents;
    const res = await apiFetch("/homework", { method:"POST", body: JSON.stringify(payload) });
    const data = await res.json();
    if (!res.ok) { setHwError(data.error||"Failed"); setHwSaving(false); return; }
    const who = assignMode === "selected" ? `${selectedStudents.length} student${selectedStudents.length===1?"":"s"}` : "the whole course";
    setHwSuccess(`"${hwForm.title}" assigned to ${who}!`);
    setHwForm({ title:"", course_id: hwForm.course_id, due_date:"", xp:"40", type:"paragraph", description:"", video_url:"" });
    setHwFile(null);
    setSelectedStudents([]); setAssignMode("all");
    setHwSaving(false);
    refreshHwList();
  };

  const sub = active != null ? HW_SUBMISSIONS[active] : null;
  return (
    <Themed className={dark ? "theme-dark" : ""} style={{ width:"100%", height:"100%", display:"flex" }}>
      <TeacherSidebar active="/app/teacher/homework" go={go} session={session}/>
      <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 }}>Homework</div>
            <div className="mono" style={{ fontSize:11, color:"var(--ink-mute)" }}>{HW_SUBMISSIONS.filter(s=>!s.grade).length} pending review · {HW_SUBMISSIONS.filter(s=>s.grade).length} graded</div>
          </div>
          <div style={{ flex:1 }}/>
          <Tabs items={["Grade submissions","Create & assign","Manage"]} active={tab==="grade"?"Grade submissions":tab==="create"?"Create & assign":"Manage"} onChange={v=>setTab(v==="Grade submissions"?"grade":v==="Create & assign"?"create":"manage")}/>
        </div>
        {tab === "create" ? (
          <div style={{ flex:1, overflow:"auto", padding:32, display:"flex", justifyContent:"center" }}>
            <div style={{ width:"100%", maxWidth:520 }}>
              <div className="display" style={{ fontSize:20, marginBottom:20 }}>Create homework</div>
              <form onSubmit={createHw} style={{ display:"flex", flexDirection:"column", gap:14 }}>
                <FormField label="TYPE">
                  <div style={{ display:"flex", gap:8 }}>
                    {[["paragraph","📝 Paragraph"],["mcq","🔘 MCQ"],["video","▶ Video"]].map(([t,label]) => (
                      <button key={t} type="button" onClick={() => setHwForm(f=>({...f,type:t}))}
                        style={{ flex:1, padding:"8px 0", borderRadius:10, border:"var(--border-thin)", fontSize:12, fontWeight:700, cursor:"pointer",
                          background: (hwForm.type||"paragraph")===t ? "var(--coral)" : "var(--paper-deep)",
                          color: (hwForm.type||"paragraph")===t ? "white" : "var(--ink-mute)" }}>{label}</button>
                    ))}
                  </div>
                </FormField>
                <FormField label="TITLE">
                  <input required style={inputStyle} value={hwForm.title} onChange={e=>setHwForm(f=>({...f,title:e.target.value}))} placeholder="e.g. Build a simple calculator"/>
                </FormField>
                <FormField label="INSTRUCTIONS">
                  <textarea style={{ ...inputStyle, minHeight:80, resize:"vertical" }} value={hwForm.description||""} onChange={e=>setHwForm(f=>({...f,description:e.target.value}))} placeholder="Describe what students need to do…"/>
                </FormField>
                {(hwForm.type||"paragraph") === "video" && (
                  <FormField label="VIDEO URL">
                    <input style={inputStyle} value={hwForm.video_url||""} onChange={e=>setHwForm(f=>({...f,video_url:e.target.value}))} placeholder="https://youtube.com/watch?v=…"/>
                  </FormField>
                )}
                <FormField label="COURSE">
                  <select required style={selectStyle} value={hwForm.course_id} onChange={e=>setHwForm(f=>({...f,course_id:e.target.value}))}>
                    <option value="">Select course…</option>
                    {allCourses.map(c => <option key={c.id} value={c.id}>{c.name} · {c.level}</option>)}
                  </select>
                </FormField>
                {(hwForm.type||"paragraph") !== "video" && (
                  <FormField label="ATTACH FILE (OPTIONAL)">
                    {hwFile ? (
                      <div style={{ display:"flex", alignItems:"center", gap:8, padding:"8px 10px", borderRadius:8, border:"var(--border-thin)", background:"var(--paper-deep)" }}>
                        <span style={{ fontSize:16 }}>📎</span>
                        <span style={{ flex:1, fontSize:13, fontWeight:600, overflow:"hidden", textOverflow:"ellipsis", whiteSpace:"nowrap" }}>{hwFile.title}</span>
                        <button type="button" onClick={()=>setHwFile(null)} className="btn btn-ghost" style={{ padding:"3px 10px", fontSize:11, color:"var(--coral)" }}>Remove</button>
                      </div>
                    ) : (
                      <label style={{ display:"flex", alignItems:"center", gap:8, padding:"10px 12px", borderRadius:8, border:"1.5px dashed var(--rule-bold)", cursor: hwUploading?"default":"pointer", fontSize:13, color:"var(--ink-mute)" }}>
                        {I.plus({ size:14 })} {hwUploading ? "Uploading…" : "Attach a worksheet / reference file"}
                        <input type="file" disabled={hwUploading} style={{ display:"none" }} onChange={e=>{ attachHwFile(e.target.files[0]); e.target.value=""; }}/>
                      </label>
                    )}
                    <div style={{ fontSize:11, color:"var(--ink-mute)", marginTop:4 }}>Students can download this when they open the homework.</div>
                  </FormField>
                )}
                <FormField label="ASSIGN TO">
                  <div style={{ display:"flex", gap:8, marginBottom: assignMode==="selected"?10:0 }}>
                    {[["all","👥 All students in course"],["selected","☑ Selected students"]].map(([m,label])=>(
                      <button key={m} type="button" onClick={()=>setAssignMode(m)}
                        style={{ flex:1, padding:"8px 0", borderRadius:10, border:"var(--border-thin)", fontSize:12, fontWeight:700, cursor:"pointer",
                          background: assignMode===m ? "var(--coral)" : "var(--paper-deep)", color: assignMode===m ? "white" : "var(--ink-mute)" }}>{label}</button>
                    ))}
                  </div>
                  {assignMode==="selected" && (
                    <div style={{ border:"var(--border-thin)", borderRadius:8, padding:10, maxHeight:180, overflow:"auto", background:"var(--paper-deep)" }}>
                      {!hwForm.course_id ? (
                        <div style={{ fontSize:12, color:"var(--ink-mute)" }}>Select a course first.</div>
                      ) : roster.length===0 ? (
                        <div style={{ fontSize:12, color:"var(--ink-mute)" }}>No students in this course yet.</div>
                      ) : (
                        <>
                          <label style={{ display:"flex", alignItems:"center", gap:8, fontSize:12, fontWeight:700, paddingBottom:6, marginBottom:6, borderBottom:"var(--border-thin)", cursor:"pointer" }}>
                            <input type="checkbox" checked={selectedStudents.length===roster.length}
                              onChange={e=>setSelectedStudents(e.target.checked ? roster.map(s=>s.id) : [])}/>
                            Select all ({roster.length})
                          </label>
                          {roster.map(s=>(
                            <label key={s.id} style={{ display:"flex", alignItems:"center", gap:8, fontSize:13, padding:"4px 0", cursor:"pointer" }}>
                              <input type="checkbox" checked={selectedStudents.includes(s.id)}
                                onChange={e=>setSelectedStudents(cur => e.target.checked ? [...cur, s.id] : cur.filter(x=>x!==s.id))}/>
                              {s.name}
                            </label>
                          ))}
                          <div style={{ fontSize:11, color:"var(--ink-mute)", marginTop:6 }}>{selectedStudents.length} selected</div>
                        </>
                      )}
                    </div>
                  )}
                </FormField>
                <div style={{ display:"grid", gridTemplateColumns:"1fr 1fr", gap:12 }}>
                  <FormField label="DUE DATE">
                    <input type="date" style={inputStyle} value={hwForm.due_date} onChange={e=>setHwForm(f=>({...f,due_date:e.target.value}))}/>
                  </FormField>
                  <FormField label="XP REWARD">
                    <input type="number" min="0" style={inputStyle} value={hwForm.xp} onChange={e=>setHwForm(f=>({...f,xp:e.target.value}))}/>
                  </FormField>
                </div>
                {hwError && <div style={{ color:"var(--coral)", fontSize:13 }}>{hwError}</div>}
                {hwSuccess && <div style={{ color:"var(--moss)", fontSize:13, fontWeight:700 }}>✓ {hwSuccess}</div>}
                <button type="submit" disabled={hwSaving} className="btn btn-primary" style={{ padding:"12px 0", fontSize:14 }}>{hwSaving ? "Assigning…" : "Assign homework"}</button>
              </form>
            </div>
          </div>
        ) : tab === "manage" ? (
          <div style={{ flex:1, overflow:"auto", padding:24 }}>
            {hwList.length === 0 ? (
              <div style={{ padding:"60px 0", textAlign:"center", color:"var(--ink-mute)" }}>
                <div style={{ fontSize:32, marginBottom:10 }}>📋</div>
                <div style={{ fontWeight:700 }}>No homework created yet</div>
                <div style={{ fontSize:13, marginTop:6 }}>Use “Create &amp; assign” to add homework.</div>
              </div>
            ) : (
              <div style={{ display:"flex", flexDirection:"column", gap:10, maxWidth:820, margin:"0 auto" }}>
                {hwList.map(h => {
                  const who = h.assigned_count === 0 ? "All students in course" : `${h.assigned_count} student${h.assigned_count===1?"":"s"}`;
                  const names = Array.isArray(h.assignees) && h.assignees.length ? h.assignees.join(", ") : "";
                  return (
                    <div key={h.id} className="card-flat" style={{ padding:16, display:"flex", alignItems:"flex-start", gap:14 }}>
                      <div style={{ flex:1, minWidth:0 }}>
                        <div style={{ display:"flex", alignItems:"center", gap:8, flexWrap:"wrap" }}>
                          <span style={{ fontWeight:700, fontSize:14 }}>{h.title}</span>
                          <span className="chip flat" style={{ fontSize:9, padding:"1px 6px", background:"var(--paper-deep)", textTransform:"uppercase" }}>{h.type}</span>
                        </div>
                        <div style={{ fontSize:12, color:"var(--ink-mute)", marginTop:4 }}>{h.course}{h.due?` · due ${h.due}`:""} · {h.xp} XP</div>
                        <div style={{ display:"flex", alignItems:"center", gap:10, marginTop:8, flexWrap:"wrap" }}>
                          <span title={names} style={{ fontSize:11, fontWeight:700, padding:"2px 8px", borderRadius:999, background: h.assigned_count===0?"var(--sky)":"var(--plum)", color:"white" }}>{who}</span>
                          <span style={{ fontSize:11, color:"var(--ink-mute)" }}>{h.submission_count} submission{h.submission_count===1?"":"s"}</span>
                          {h.file_id && (
                            <button onClick={()=>openCourseFile(h.file_course_id, h.file_id)} className="btn btn-ghost" style={{ padding:"2px 8px", fontSize:11, display:"inline-flex", alignItems:"center", gap:4 }}>📎 {h.file_name || "Attachment"}</button>
                          )}
                          {names && <span style={{ fontSize:11, color:"var(--ink-mute)", overflow:"hidden", textOverflow:"ellipsis", whiteSpace:"nowrap", maxWidth:320 }}>({names})</span>}
                        </div>
                      </div>
                      <button onClick={()=>deleteHw(h.id, h.title)} className="btn btn-ghost" style={{ padding:"4px 10px", fontSize:11, color:"var(--coral)", flexShrink:0 }}>Delete</button>
                    </div>
                  );
                })}
              </div>
            )}
          </div>
        ) : (
        <div style={{ flex:1, display:"grid", gridTemplateColumns: sub ? "1fr 1.6fr" : "1fr", overflow:"hidden" }}>
          <div style={{ overflow:"auto", padding:18, display:"flex", flexDirection:"column", gap:8 }}>
            {HW_SUBMISSIONS.length === 0 ? (
              <div style={{ padding:"60px 0", textAlign:"center", color:"var(--ink-mute)" }}>
                <div style={{ fontSize:32, marginBottom:10 }}>📭</div>
                <div style={{ fontWeight:700 }}>No submissions yet</div>
                <div style={{ fontSize:13, marginTop:6 }}>Students haven't submitted homework yet</div>
              </div>
            ) : HW_SUBMISSIONS.map((s,i) => (
              <div key={i} onClick={() => setActive(active===i?null:i)} className="card-flat" style={{ padding:14, cursor:"pointer", borderLeft: active===i ? "3px solid var(--coral)" : "3px solid transparent", background: active===i ? "var(--paper-card)" : "transparent" }}>
                <div style={{ display:"flex", alignItems:"center", gap:10 }}>
                  <Avatar name={s.student[0]} color={s.color} size={32}/>
                  <div style={{ flex:1 }}>
                    <div style={{ fontWeight:700, fontSize:13 }}>{s.student}</div>
                    <div style={{ fontSize:12, color:"var(--ink-mute)" }}>{s.hw} · {s.submitted}</div>
                  </div>
                  {grades[i] || s.grade
                    ? <span className="chip flat" style={{ fontSize:11, background:"var(--moss)", color:"white" }}>{grades[i] || s.grade}</span>
                    : <span className="chip flat" style={{ fontSize:10, background:"var(--gold)", color:"white" }}>review</span>}
                </div>
              </div>
            ))}
          </div>
          {sub && (
            <div style={{ borderLeft:"var(--border-thin)", padding:22, overflow:"auto", background:"var(--paper-card)", display:"flex", flexDirection:"column", gap:16 }}>
              <div style={{ display:"flex", alignItems:"center", gap:10 }}>
                <Avatar name={sub.student[0]} color={sub.color} size={36}/>
                <div>
                  <div className="display" style={{ fontSize:18 }}>{sub.student}</div>
                  <div style={{ fontSize:12, color:"var(--ink-mute)" }}>{sub.hw} · submitted {sub.submitted}</div>
                </div>
              </div>
              <div>
                <div className="mono" style={{ fontSize:10, color:"var(--ink-mute)", marginBottom:6 }}>SUBMISSION</div>
                {sub.code && (
                  <pre style={{ margin:0, padding:16, background:"oklch(0.18 0.02 250)", color:"oklch(0.92 0.01 250)", borderRadius:10, fontSize:13, lineHeight:1.7, overflowX:"auto", border:"var(--border-thin)" }}>
                    {sub.code}
                  </pre>
                )}
                {sub.drive_link && (
                  <a href={sub.drive_link} target="_blank" rel="noreferrer" style={{ display:"inline-flex", alignItems:"center", gap:6, marginTop:8, fontSize:13, color:"var(--sky)", fontWeight:600 }}>🔗 {sub.drive_link}</a>
                )}
                {sub.file_id && (
                  <button onClick={()=>openCourseFile(sub.file_course_id, sub.file_id)} className="btn btn-ghost" style={{ marginTop:8, padding:"6px 12px", fontSize:12, display:"inline-flex", alignItems:"center", gap:6 }}>📎 {sub.file_name || "Download submitted file"}</button>
                )}
                {!sub.code && !sub.drive_link && !sub.file_id && (
                  <div style={{ fontSize:13, color:"var(--ink-mute)" }}>No content submitted.</div>
                )}
              </div>
              <div>
                <div className="mono" style={{ fontSize:10, color:"var(--ink-mute)", marginBottom:8 }}>GRADE</div>
                <div style={{ display:"flex", gap:8, flexWrap:"wrap", marginBottom:8 }}>
                  {["100%","90%","80%","70%","60%","Needs redo"].map(g => (
                    <button key={g} onClick={() => setGrades(gr => ({ ...gr, [active]:g }))} style={{ padding:"6px 14px", borderRadius:999, border:"var(--border-thin)", background: (grades[active]||sub.grade)===g ? "var(--coral)" : "var(--paper-deep)", color: (grades[active]||sub.grade)===g ? "white" : "var(--ink)", fontSize:12, fontWeight:700, cursor:"pointer" }}>{g}</button>
                  ))}
                </div>
                <textarea placeholder="Feedback (optional)…" style={{ width:"100%", minHeight:72, padding:"10px 12px", border:"var(--border-thin)", borderRadius:8, background:"var(--paper-deep)", fontSize:13, fontFamily:"var(--font-ui)", color:"var(--ink)", resize:"none", outline:"none", boxSizing:"border-box" }}/>
                <button className="btn btn-primary" onClick={saveGrade} disabled={saving || !grades[active]} style={{ marginTop:10, width:"100%", padding:"10px 0", fontSize:13 }}>{saving ? "Saving…" : "Save grade & notify parent"}</button>
              </div>
            </div>
          )}
        </div>
        )}
      </div>
    </Themed>
  );
};

// ── Teacher: Analytics ────────────────────────────────────────────────────────
const TeacherAnalytics = ({ dark = false, go, session }) => {
  const tid = session?.teacherId;
  const { data: dash } = useApi(tid ? `/teacher/dashboard/${tid}` : "/teacher/dashboard/0", {});
  const batches = dash.batches || [];
  const [activeBatch, setActiveBatch] = React.useState(null);
  const batchId = activeBatch || (batches[0] ? batches[0].id : null);
  const activeBatchData = batches.find(b => b.id === batchId) || batches[0] || {};
  const { data: students } = useApi(batchId ? `/students?batch=${batchId}` : "/students");
  return (
  <Themed className={dark ? "theme-dark" : ""} style={{ width:"100%", height:"100%", display:"flex" }}>
    <TeacherSidebar active="/app/teacher/analytics" go={go} session={session}/>
    <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 }}>Analytics</div>
          <div className="mono" style={{ fontSize:11, color:"var(--ink-mute)" }}>My batches · performance overview</div>
        </div>
        <div style={{ flex:1 }}/>
        {batches.length > 0 && <Tabs items={batches.map(b=>b.name)} active={activeBatchData.name || ""} onChange={name => { const b = batches.find(x=>x.name===name); if(b) setActiveBatch(b.id); }}/>}
      </div>
      <div style={{ flex:1, overflow:"auto", padding:22, display:"flex", flexDirection:"column", gap:18 }}>
        {batches.length === 0 ? (
          <div style={{ textAlign:"center", padding:60, color:"var(--ink-mute)" }}>
            <div style={{ fontSize:32, marginBottom:12 }}>📊</div>
            <div style={{ fontWeight:700, fontSize:16 }}>No batches assigned yet</div>
          </div>
        ) : (
        <>
        <div style={{ display:"grid", gridTemplateColumns:"repeat(3,1fr)", gap:14 }}>
          {[
            { l:"BATCH STUDENTS", v: activeBatchData.students ?? 0, c:"var(--moss)" },
            { l:"TOTAL BATCHES",  v: batches.length,                 c:"var(--sky)" },
            { l:"AVG XP",         v: students.length ? Math.round(students.reduce((a,s)=>a+(s.xp||0),0)/students.length) : 0, c:"var(--coral)" },
          ].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>
        <div className="card-flat" style={{ padding:18 }}>
          <SectionHead eyebrow={`${activeBatchData.name || "BATCH"} · ${activeBatchData.course || ""}`} title="Student performance"/>
          <div style={{ display:"flex", flexDirection:"column", gap:10 }}>
            {students.length === 0 ? (
              <div style={{ padding:"24px 0", textAlign:"center", color:"var(--ink-mute)", fontSize:13 }}>No students in this batch yet.</div>
            ) : students.map((r,i) => (
              <div key={i} style={{ display:"flex", alignItems:"center", gap:14 }}>
                <Avatar name={r.name[0]} color={r.color || "var(--coral)"} size={28}/>
                <div style={{ width:80, fontSize:13, fontWeight:600 }}>{r.name}</div>
                <div style={{ flex:1, display:"grid", gridTemplateColumns:"1fr 1fr", gap:8 }}>
                  {[["XP", r.xp ?? 0, "var(--coral)"], ["Status", r.status || "active", r.status==="at-risk"?"var(--gold)":r.status==="churning"?"var(--coral)":"var(--moss)"]].map(([l,v,c])=>(
                    <div key={l} style={{ display:"flex", flexDirection:"column" }}>
                      <div style={{ fontSize:10, color:"var(--ink-mute)" }}>{l}</div>
                      <div style={{ fontWeight:700, fontSize:13, color:c }}>{v}</div>
                    </div>
                  ))}
                </div>
                <div style={{ width:100 }}>
                  <div className="progress" style={{ height:6 }}><i style={{ width:`${Math.min(100, Math.round((r.xp||0)/10))}%`, background:"var(--coral)" }}/></div>
                </div>
              </div>
            ))}
          </div>
        </div>
        <div className="card-flat" style={{ padding:18 }}>
          <SectionHead eyebrow="AT RISK" title="Students to watch"/>
          {students.filter(r => r.status === "at-risk" || r.status === "churning").length === 0 ? (
            <div style={{ padding:"18px 0", textAlign:"center", color:"var(--ink-mute)", fontSize:13 }}>No at-risk students right now.</div>
          ) : students.filter(r => r.status === "at-risk" || r.status === "churning").map((r,i) => (
            <div key={i} style={{ display:"flex", alignItems:"center", gap:10, padding:"8px 0", borderTop: i?"var(--border-thin)":"none" }}>
              <Avatar name={r.name[0]} color={r.color || "var(--coral)"} size={26}/>
              <div style={{ flex:1, fontSize:13 }}>{r.name}</div>
              <span className="chip flat" style={{ fontSize:10, background:"var(--gold)", color:"white" }}>{r.status}</span>
              <button className="btn btn-ghost" style={{ padding:"2px 8px", fontSize:11 }}>Notify</button>
            </div>
          ))}
        </div>
        </>
        )}
      </div>
    </div>
  </Themed>
  );
};

// ── Teacher: Messages ─────────────────────────────────────────────────────────
const TeacherMessages = ({ dark = false, go, session }) => {
  const [convos, setConvos] = React.useState(null);
  const { data: initConvos } = useApi("/conversations");
  const list = convos ?? initConvos;
  const [active, setActive] = React.useState(null);
  const [input, setInput] = React.useState("");
  const [localMsgs, setLocalMsgs] = React.useState([]);
  const [showCompose, setShowCompose] = React.useState(false);
  const [composeForm, setComposeForm] = React.useState({ name:"" });
  const [composeSaving, setComposeSaving] = React.useState(false);
  const thread = list.find(m => m.id === active);

  React.useEffect(() => {
    if (!active) return;
    apiFetch(`/conversations/${active}/messages`)
      .then(r => r.json())
      .then(msgs => setLocalMsgs(msgs.map(m => ({ from: m.fromMe ? "me" : "them", text: m.text }))))
      .catch(() => {});
  }, [active]);

  const send = () => {
    if (!input.trim() || !active) return;
    const text = input;
    setLocalMsgs(m => [...m, { from:"me", text }]);
    setInput("");
    apiFetch(`/conversations/${active}/messages`, {
      method:"POST", body: JSON.stringify({ from_me: true, text })
    }).catch(() => {});
  };

  const compose = async e => {
    e.preventDefault();
    if (!composeForm.name.trim()) return;
    setComposeSaving(true);
    const res = await apiFetch("/conversations", { method:"POST", body: JSON.stringify({ name: composeForm.name }) });
    const data = await res.json();
    setComposeSaving(false);
    if (res.ok) {
      setConvos(c => [...(c ?? initConvos), data]);
      setActive(data.id);
      setLocalMsgs([]);
      setShowCompose(false);
      setComposeForm({ name:"" });
    }
  };

  return (
    <Themed className={dark ? "theme-dark" : ""} style={{ width:"100%", height:"100%", display:"flex" }}>
      <TeacherSidebar active="/app/teacher/messages" go={go} session={session}/>
      <div style={{ flex:1, display:"flex", minWidth:0, overflow:"hidden" }}>
        {/* Sidebar */}
        <div style={{ width:260, borderRight:"var(--border-thin)", display:"flex", flexDirection:"column", background:"var(--paper-card)", flexShrink:0 }}>
          <div style={{ padding:"12px 16px", borderBottom:"var(--border-thin)", display:"flex", alignItems:"center", gap:8 }}>
            <div className="display" style={{ fontSize:18, flex:1 }}>Messages</div>
            <button onClick={() => setShowCompose(true)} className="btn btn-primary" style={{ padding:"5px 10px", fontSize:11 }}>{I.plus({ size:13 })} New</button>
          </div>
          <div style={{ flex:1, overflow:"auto" }}>
            {list.length === 0 ? (
              <div style={{ padding:24, textAlign:"center", color:"var(--ink-mute)" }}>
                <div style={{ fontSize:28, marginBottom:8 }}>💬</div>
                <div style={{ fontSize:13, fontWeight:600 }}>No conversations yet</div>
                <button onClick={() => setShowCompose(true)} className="btn btn-ghost" style={{ marginTop:12, fontSize:12 }}>Start one</button>
              </div>
            ) : list.map(m => (
              <div key={m.id} onClick={() => setActive(m.id)} style={{ display:"flex", gap:10, padding:"12px 16px", cursor:"pointer", borderBottom:"var(--border-thin)", background: active===m.id ? "var(--paper-deep)" : "transparent" }}>
                <Avatar name={m.avatar||m.name[0]} color={m.color||"var(--coral)"} size={36}/>
                <div style={{ flex:1, minWidth:0 }}>
                  <div style={{ fontWeight:700, fontSize:13 }}>{m.name}</div>
                  <div style={{ fontSize:11, color:"var(--ink-mute)", overflow:"hidden", textOverflow:"ellipsis", whiteSpace:"nowrap" }}>{m.last_msg || "No messages yet"}</div>
                </div>
                {m.unread > 0 && <span style={{ width:18, height:18, borderRadius:"50%", background:"var(--coral)", color:"white", fontSize:10, fontWeight:700, display:"grid", placeItems:"center", flexShrink:0, alignSelf:"center" }}>{m.unread}</span>}
              </div>
            ))}
          </div>
        </div>

        {/* Thread */}
        {thread ? (
          <div style={{ flex:1, display:"flex", flexDirection:"column", background:"var(--paper)" }}>
            <div style={{ padding:"12px 20px", borderBottom:"var(--border-thin)", background:"var(--paper-card)", display:"flex", alignItems:"center", gap:10 }}>
              <Avatar name={thread.avatar||thread.name[0]} color={thread.color||"var(--coral)"} size={32}/>
              <div className="display" style={{ fontSize:16 }}>{thread.name}</div>
            </div>
            <div style={{ flex:1, overflow:"auto", padding:20, display:"flex", flexDirection:"column", gap:10 }}>
              {localMsgs.length === 0 && (
                <div style={{ textAlign:"center", padding:40, color:"var(--ink-mute)", fontSize:13 }}>No messages yet. Say hello!</div>
              )}
              {localMsgs.map((m,i) => (
                <div key={i} style={{ display:"flex", justifyContent: m.from==="me"?"flex-end":"flex-start" }}>
                  <div style={{ maxWidth:"70%", padding:"10px 14px", borderRadius:14, background: m.from==="me"?"var(--coral)":"var(--paper-card)", color: m.from==="me"?"white":"var(--ink)", fontSize:14, lineHeight:1.5, border: m.from==="me"?"none":"var(--border-thin)" }}>
                    {m.text}
                  </div>
                </div>
              ))}
            </div>
            <div style={{ padding:"12px 20px", borderTop:"var(--border-thin)", display:"flex", gap:10 }}>
              <input value={input} onChange={e=>setInput(e.target.value)} onKeyDown={e=>e.key==="Enter"&&send()} placeholder="Type a message…" style={{ flex:1, padding:"10px 14px", border:"var(--border-thin)", borderRadius:999, background:"var(--paper-card)", fontSize:14, fontFamily:"var(--font-ui)", color:"var(--ink)", outline:"none" }}/>
              <button onClick={send} className="btn btn-primary" style={{ padding:"10px 18px", fontSize:13 }}>{I.send({ size:16 })}</button>
            </div>
          </div>
        ) : (
          <div style={{ flex:1, display:"flex", alignItems:"center", justifyContent:"center", color:"var(--ink-mute)", flexDirection:"column", gap:12 }}>
            {I.send({ size:32 })}
            <div style={{ fontSize:14 }}>Select a conversation to start messaging</div>
          </div>
        )}
      </div>

      {showCompose && (
        <Modal title="New conversation" onClose={() => setShowCompose(false)}>
          <form onSubmit={compose}>
            <FormField label="RECIPIENT NAME">
              <input required style={inputStyle} value={composeForm.name} onChange={e=>setComposeForm(f=>({...f,name:e.target.value}))} placeholder="e.g. Priya Sharma (Parent)"/>
            </FormField>
            <div style={{ display:"flex", gap:10, justifyContent:"flex-end", marginTop:4 }}>
              <button type="button" onClick={() => setShowCompose(false)} className="btn btn-ghost">Cancel</button>
              <button type="submit" disabled={composeSaving} className="btn btn-primary">{composeSaving ? "Creating…" : "Start conversation"}</button>
            </div>
          </form>
        </Modal>
      )}
    </Themed>
  );
};
