/* ============================================================
   CURIO — Dedicated full-page module-quiz editor (route: 'quiz')
   ============================================================ */

function qz_findModule(course, moduleId) {
  if (!course || !moduleId) return null;
  const mods = course.modules || [];
  const idx = mods.findIndex(m => m.id === moduleId);
  if (idx < 0) return null;
  return { module: mods[idx], moduleIndex: idx, total: mods.length };
}

function qz_quizFromModule(m) {
  if (!m) return null;
  // The course tree converts an existing quiz into a pseudo-lesson row with _quiz attached.
  const row = (m.lessons || []).find(l => l.type === 'quiz');
  return row && row._quiz ? row._quiz : null;
}

/* ============================================================
   QuizPage — full-page route
   ============================================================ */
function QuizPage({ go, params, user }) {
  const { id: moduleId, courseId: initialCourseId } = params || {};
  const [courseId, setCourseId] = useState(initialCourseId || null);
  const [course, setCourse] = useState(null);
  const [loading, setLoading] = useState(true);
  const [savedAt, setSavedAt] = useState(0);
  const [error, setError] = useState(null);

  const goBack = () => {
    if (courseId) go('creator', { editId: courseId });
    else go('library');
  };

  // If we don't have a courseId, walk back via listCourses to discover it.
  useEffect(() => {
    let cancelled = false;
    if (courseId || !moduleId) return;
    window.API.listCourses()
      .then(async (d) => {
        const list = (d && d.courses) || [];
        for (const c of list) {
          try {
            const full = await window.API.getCourse(c.id);
            if (cancelled) return;
            if ((full.modules || []).some(m => m.id === moduleId)) {
              setCourseId(full.id);
              setCourse(full);
              setLoading(false);
              return;
            }
          } catch (e) {}
        }
        if (!cancelled) {
          setLoading(false);
          setError('Could not find the course for this quiz.');
        }
      })
      .catch(e => { if (!cancelled) { setLoading(false); setError(e?.message || 'Failed to find course'); } });
    return () => { cancelled = true; };
  }, [courseId, moduleId]);

  useEffect(() => {
    let cancelled = false;
    if (!courseId) return;
    setLoading(true);
    window.API.getCourse(courseId)
      .then(c => { if (!cancelled) { setCourse(c); setLoading(false); } })
      .catch(e => { if (!cancelled) { setError(e?.message || 'Failed to load course'); setLoading(false); } });
    return () => { cancelled = true; };
  }, [courseId]);

  useEffect(() => {
    if (!savedAt) return;
    const id = setTimeout(() => setSavedAt(0), 2500);
    return () => clearTimeout(id);
  }, [savedAt]);

  const markSaved = () => setSavedAt(Date.now());
  const refresh = React.useCallback(async () => {
    if (!courseId) return null;
    try {
      const c = await window.API.getCourse(courseId);
      setCourse(c);
      return c;
    } catch (e) {
      setError(e?.message || 'Refresh failed');
      return null;
    }
  }, [courseId]);

  if (loading) {
    return (
      <div data-app-scroll className="scroll" style={{ height: '100vh', overflowY: 'auto', background: 'var(--paper)' }} data-screen-label="Quiz editor">
        <Topbar go={go} title="Loading quiz…" back={goBack} user={user} />
        <div style={{ maxWidth: 1280, margin: '0 auto', padding: 32 }}>
          <div className="card" style={{ padding: 28 }}>
            <div className="skeleton" style={{ height: 12, width: '30%', marginBottom: 14 }} />
            <div className="skeleton" style={{ height: 28, width: '60%', marginBottom: 18 }} />
            <div className="skeleton" style={{ height: 120, marginBottom: 14 }} />
            <div className="skeleton" style={{ height: 120 }} />
          </div>
        </div>
      </div>
    );
  }

  if (!course) {
    return (
      <div data-app-scroll className="scroll" style={{ height: '100vh', overflowY: 'auto', background: 'var(--paper)' }}>
        <Topbar go={go} title="Quiz not found" back={goBack} user={user} />
        <div style={{ maxWidth: 720, margin: '64px auto', padding: 32 }}>
          <div className="card" style={{ padding: 36, textAlign: 'center' }}>
            <div className="center" style={{ width: 56, height: 56, borderRadius: 14, background: 'var(--brand-tint)', color: 'var(--brand-ink)', margin: '0 auto 16px' }}>
              <File size={22} />
            </div>
            <h3 style={{ fontSize: 18, letterSpacing: '-0.01em', marginBottom: 8 }}>We couldn't load this course</h3>
            <p className="muted" style={{ fontSize: 14, lineHeight: 1.55, maxWidth: 420, margin: '0 auto 18px' }}>
              {error || 'The course may have moved or been deleted.'}
            </p>
            <Btn variant="brand" size="sm" onClick={goBack}>Back to course</Btn>
          </div>
        </div>
      </div>
    );
  }

  const found = qz_findModule(course, moduleId);

  if (!found) {
    return (
      <div data-app-scroll className="scroll" style={{ height: '100vh', overflowY: 'auto', background: 'var(--paper)' }}>
        <Topbar go={go} title={course.title} sub="Module not found" back={goBack} user={user} />
        <div style={{ maxWidth: 720, margin: '64px auto', padding: 32 }}>
          <div className="card" style={{ padding: 36, textAlign: 'center' }}>
            <div className="center" style={{ width: 56, height: 56, borderRadius: 14, background: 'var(--brand-tint)', color: 'var(--brand-ink)', margin: '0 auto 16px' }}>
              <File size={22} />
            </div>
            <h3 style={{ fontSize: 18, letterSpacing: '-0.01em', marginBottom: 8 }}>Module not found</h3>
            <p className="muted" style={{ fontSize: 14, lineHeight: 1.55, maxWidth: 420, margin: '0 auto 18px' }}>
              This module may have been deleted. Open another module from the course outline.
            </p>
            <Btn variant="brand" size="sm" onClick={goBack}>Back to course</Btn>
          </div>
        </div>
      </div>
    );
  }

  const showSaved = savedAt > 0 && (Date.now() - savedAt < 2500);
  const sub = `Module ${found.moduleIndex + 1} / ${found.total} · Quiz`;

  return (
    <div style={{ height: '100vh', display: 'flex', flexDirection: 'column', background: 'var(--paper)', minHeight: 0 }} data-screen-label="Quiz editor">
      <Topbar go={go} title={course.title} sub={sub} back={goBack} user={user}>
        {showSaved && <span className="mono fade-in" style={{ fontSize: 12, color: 'var(--green)' }}>Saved ✓</span>}
      </Topbar>

      <QuizPageInner
        key={found.module.id}
        go={go}
        course={course}
        courseId={courseId}
        found={found}
        markSaved={markSaved}
        refresh={refresh}
      />
    </div>
  );
}

/* ============================================================
   QuizPageInner — chat + main editor + action rail
   ============================================================ */
function QuizPageInner({ go, course, courseId, found, markSaved, refresh }) {
  const { module: mod, moduleIndex, total } = found;
  const quiz = qz_quizFromModule(mod);
  const questions = (quiz && quiz.questions) || [];

  const [busy, setBusy] = useState(null); // 'regen'
  const [error, setError] = useState(null);
  const [addingQ, setAddingQ] = useState(false);
  const [addError, setAddError] = useState(null);

  const onAddQuestion = async () => {
    if (!mod.id) return;
    setAddingQ(true);
    setAddError(null);
    try {
      await window.API.addQuizQuestion(mod.id, { stub: true });
      markSaved && markSaved();
      await (refresh && refresh());
    } catch (e) {
      setAddError(e?.message || 'Could not add question');
    } finally {
      setAddingQ(false);
    }
  };

  const onRegenerate = async ({ guidance, questionCount }) => {
    if (!mod.id) return;
    setBusy('regen');
    setError(null);
    try {
      await window.API.regenerateQuiz(mod.id, {
        guidance: (guidance || '').trim() || undefined,
        questionCount: questionCount || undefined,
      });
      markSaved && markSaved();
      await (refresh && refresh());
    } catch (e) {
      setError(e?.message || 'Quiz generation failed');
    } finally {
      setBusy(null);
    }
  };

  const prevMod = moduleIndex > 0 ? course.modules[moduleIndex - 1] : null;
  const nextMod = moduleIndex < total - 1 ? course.modules[moduleIndex + 1] : null;
  const navigateToModuleQuiz = (m) => {
    if (m && m.id) go('quiz', { id: m.id, courseId });
  };

  return (
    <div style={{ flex: 1, minHeight: 0, display: 'grid', gridTemplateColumns: '380px minmax(0,1fr)', overflow: 'hidden' }}>
      {/* LEFT — chat */}
      <QuizChatPanel
        courseId={courseId}
        moduleTitle={mod.title}
        moduleOrder={moduleIndex + 1}
        questionCount={questions.length}
        onCourseUpdated={refresh}
      />

      {/* RIGHT — editor + action rail */}
      <div data-app-scroll className="scroll" style={{ minHeight: 0, overflowY: 'auto' }}>
        <div style={{ maxWidth: 1320, margin: '0 auto', padding: '24px 32px 96px', display: 'grid', gridTemplateColumns: 'minmax(0,1fr) 320px', gap: 28 }}>
          <div style={{ minWidth: 0 }}>
            <div className="row" style={{ gap: 10, flexWrap: 'wrap', minWidth: 0, marginBottom: 10 }}>
              <span className="mono" style={{ fontSize: 11, letterSpacing: '.1em', textTransform: 'uppercase', color: 'var(--brand)' }}>
                Module {moduleIndex + 1} · Quiz <span className="muted" style={{ letterSpacing: 0, textTransform: 'none' }}>/ {total}</span>
              </span>
              <span className="muted" style={{ fontSize: 12.5, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis', maxWidth: 360 }}>{mod.title}</span>
            </div>

            <div style={{ fontSize: 30, fontWeight: 800, letterSpacing: '-0.025em', lineHeight: 1.1, marginBottom: 8 }}>
              Module quiz · {mod.title}
            </div>
            <div className="row muted" style={{ gap: 14, fontSize: 12.5, marginBottom: 22, flexWrap: 'wrap' }}>
              <span className="row" style={{ gap: 5 }}><List size={13} /> {questions.length} questions</span>
            </div>

            {error && (
              <div className="card fade-in" style={{ marginBottom: 16, padding: '10px 14px', background: 'var(--rose-tint, #fde9ee)', color: '#9c1f3c', borderRadius: 'var(--r-sm)', border: '1px solid #f5c2cf', fontSize: 13 }}>
                {error}
              </div>
            )}

            {questions.length === 0 ? (
              <div className="card fade-in" style={{ padding: '36px 28px', textAlign: 'center' }}>
                <div className="center" style={{ width: 56, height: 56, borderRadius: 14, background: 'var(--brand-tint)', color: 'var(--brand-ink)', margin: '0 auto 16px' }}>
                  <Sparkles size={22} />
                </div>
                <h3 style={{ fontSize: 17, letterSpacing: '-0.01em', marginBottom: 6 }}>No quiz yet</h3>
                <p className="muted" style={{ fontSize: 14, lineHeight: 1.55, maxWidth: 420, margin: '0 auto 12px' }}>
                  Coursedy can draft a multiple-choice quiz for this module from its lessons. Use the panel on the right to generate one.
                </p>
              </div>
            ) : (
              <div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
                {questions.map((q, idx) => (
                  <QuestionCard
                    key={q.id}
                    question={q}
                    index={idx}
                    markSaved={markSaved}
                    refresh={refresh}
                  />
                ))}
              </div>
            )}
          </div>

          {/* Action rail */}
          <div style={{ minWidth: 0 }}>
            <div style={{ position: 'sticky', top: 16, display: 'flex', flexDirection: 'column', gap: 14 }}>
              <GenerateQuizPanel
                hasQuestions={questions.length > 0}
                busy={busy === 'regen'}
                onRegenerate={onRegenerate}
              />
              <QuizStructurePanel
                prevMod={prevMod}
                nextMod={nextMod}
                onPrev={() => navigateToModuleQuiz(prevMod)}
                onNext={() => navigateToModuleQuiz(nextMod)}
                addingQ={addingQ}
                addError={addError}
                onAddQuestion={onAddQuestion}
              />
            </div>
          </div>
        </div>
      </div>
    </div>
  );
}

/* ============================================================
   QuestionCard — one editable MCQ
   ============================================================ */
function QuestionCard({ question, index, markSaved, refresh }) {
  const [error, setError] = useState(null);
  const [correct, setCorrect] = useState(question.correctAnswer);

  useEffect(() => {
    setCorrect(question.correctAnswer);
  }, [question.id, question.correctAnswer]);

  const patchField = async (field, value, prev) => {
    if (value === prev) return;
    try {
      await window.API.patchQuestion(question.id, { [field]: value });
      question[field] = value;
      markSaved && markSaved();
    } catch (e) {
      setError(e?.message || 'Save failed');
    }
  };

  const onSetCorrect = async (letter) => {
    if (letter === correct) return;
    const prev = correct;
    setCorrect(letter);
    try {
      await window.API.patchQuestion(question.id, { correctAnswer: letter });
      question.correctAnswer = letter;
      markSaved && markSaved();
    } catch (e) {
      setCorrect(prev);
      setError(e?.message || 'Save failed');
    }
  };

  const optionRow = (letter, field) => {
    const isCorrect = correct === letter;
    return (
      <div className="row" style={{ gap: 10, alignItems: 'flex-start', padding: '6px 0' }}>
        <button
          type="button"
          className="chip"
          onClick={() => onSetCorrect(letter)}
          title={isCorrect ? 'Correct answer' : 'Mark as correct'}
          style={{
            width: 28, height: 28, padding: 0, borderRadius: '50%',
            display: 'flex', alignItems: 'center', justifyContent: 'center',
            background: isCorrect ? 'var(--brand)' : 'var(--surface-2)',
            color: isCorrect ? '#fff' : 'var(--ink)',
            borderColor: isCorrect ? 'var(--brand)' : 'var(--line)',
            fontWeight: 700, fontSize: 12, cursor: 'pointer', flexShrink: 0,
          }}
        >{letter}</button>
        <div
          contentEditable
          suppressContentEditableWarning
          onBlur={(e) => {
            const t = e.currentTarget.innerText.trim();
            patchField(field, t, question[field]);
          }}
          style={{
            flex: 1, minWidth: 0, fontSize: 14, lineHeight: 1.5, padding: '4px 8px',
            outline: 'none', borderRadius: 6,
            border: '1px solid transparent',
            background: 'transparent',
          }}
          onFocus={(e) => { e.currentTarget.style.borderColor = 'var(--line)'; e.currentTarget.style.background = 'var(--surface)'; }}
          onBlurCapture={(e) => { e.currentTarget.style.borderColor = 'transparent'; e.currentTarget.style.background = 'transparent'; }}
        >{question[field]}</div>
      </div>
    );
  };

  return (
    <div className="card" style={{ padding: 18 }}>
      <div className="row" style={{ justifyContent: 'space-between', marginBottom: 8 }}>
        <span className="mono" style={{ fontSize: 10.5, letterSpacing: '.12em', textTransform: 'uppercase', color: 'var(--faint)' }}>Question {index + 1}</span>
        <button
          className="btn btn-icon btn-ghost btn-sm"
          title="Coming soon"
          disabled
          style={{ opacity: 0.4 }}
        >
          <Trash size={14} />
        </button>
      </div>

      {error && (
        <div className="fade-in" style={{ padding: '8px 10px', background: 'var(--rose-tint, #fde9ee)', color: '#9c1f3c', borderRadius: 'var(--r-sm)', fontSize: 12, marginBottom: 10 }}>{error}</div>
      )}

      <div
        contentEditable
        suppressContentEditableWarning
        onBlur={(e) => {
          const t = e.currentTarget.innerText.trim();
          patchField('question', t, question.question);
        }}
        style={{
          fontSize: 16, fontWeight: 600, letterSpacing: '-0.005em', lineHeight: 1.4,
          padding: '6px 8px', marginBottom: 10, outline: 'none', borderRadius: 6,
          border: '1px solid transparent',
        }}
        onFocus={(e) => { e.currentTarget.style.borderColor = 'var(--line)'; e.currentTarget.style.background = 'var(--surface-2)'; }}
        onBlurCapture={(e) => { e.currentTarget.style.borderColor = 'transparent'; e.currentTarget.style.background = 'transparent'; }}
      >{question.question}</div>

      <div style={{ marginBottom: 10 }}>
        {optionRow('A', 'optionA')}
        {optionRow('B', 'optionB')}
        {optionRow('C', 'optionC')}
        {optionRow('D', 'optionD')}
      </div>

      <div className="mono" style={{ fontSize: 10.5, letterSpacing: '.12em', textTransform: 'uppercase', color: 'var(--faint)', marginBottom: 4 }}>Explanation</div>
      <div
        contentEditable
        suppressContentEditableWarning
        onBlur={(e) => {
          const t = e.currentTarget.innerText.trim();
          patchField('explanation', t, question.explanation);
        }}
        style={{
          fontSize: 13.5, lineHeight: 1.55, padding: '8px 10px',
          background: 'var(--surface-2)', borderRadius: 8,
          outline: 'none', border: '1px solid transparent',
        }}
        onFocus={(e) => { e.currentTarget.style.borderColor = 'var(--line)'; e.currentTarget.style.background = 'var(--surface)'; }}
        onBlurCapture={(e) => { e.currentTarget.style.borderColor = 'transparent'; e.currentTarget.style.background = 'var(--surface-2)'; }}
      >{question.explanation}</div>
    </div>
  );
}

/* ============================================================
   Rail: Generate / Regenerate quiz
   ============================================================ */
function GenerateQuizPanel({ hasQuestions, busy, onRegenerate }) {
  const [guidance, setGuidance] = useState('');
  const [count, setCount] = useState(4);
  const [open, setOpen] = useState(!hasQuestions);

  useEffect(() => { if (!hasQuestions) setOpen(true); }, [hasQuestions]);

  const heroMode = !hasQuestions;
  const heading = heroMode ? 'Generate quiz' : 'Regenerate quiz';
  const label = heroMode ? 'Generate this quiz' : 'Regenerate quiz';

  const clampedCount = () => {
    const n = Number(count);
    if (!Number.isFinite(n)) return 4;
    return Math.max(1, Math.min(8, Math.round(n)));
  };

  return (
    <div className="card" style={{ padding: 16, background: heroMode ? 'var(--brand-tint)' : 'var(--surface)', border: heroMode ? '1px solid var(--brand-tint-2, var(--line))' : '1px solid var(--line)' }}>
      <div className="row" style={{ justifyContent: 'space-between', marginBottom: 10 }}>
        <div className="row" style={{ gap: 8 }}>
          <span className="center" style={{ width: 26, height: 26, borderRadius: 8, background: heroMode ? 'var(--brand)' : 'var(--brand-tint)', color: heroMode ? '#fff' : 'var(--brand-ink)', flexShrink: 0 }}>
            <Sparkles size={14} />
          </span>
          <div style={{ fontSize: 13.5, fontWeight: 700, letterSpacing: '-0.01em' }}>{heading}</div>
        </div>
        {!heroMode && (
          <button className="btn btn-icon btn-ghost btn-sm" onClick={() => setOpen(o => !o)} title={open ? 'Collapse' : 'Expand'}>
            <ChevD size={15} style={{ transform: open ? 'rotate(180deg)' : 'none', transition: 'transform .2s' }} />
          </button>
        )}
      </div>

      {open && (
        <>
          <div className="mono" style={{ fontSize: 10.5, letterSpacing: '.12em', textTransform: 'uppercase', color: 'var(--faint)', marginBottom: 6 }}>
            What should this quiz emphasize? (optional)
          </div>
          <textarea
            className="field"
            value={guidance}
            onChange={e => setGuidance(e.target.value)}
            rows={heroMode ? 4 : 3}
            placeholder="e.g. Test the difference between the three core concepts; avoid trivia."
            style={{ width: '100%', resize: 'vertical', fontSize: 13.5, lineHeight: 1.5, padding: 10, background: 'var(--surface)' }}
          />
          <div className="row" style={{ gap: 8, marginTop: 10, alignItems: 'center' }}>
            <span className="muted mono" style={{ fontSize: 11, letterSpacing: '.08em', textTransform: 'uppercase', flexShrink: 0 }}>Questions</span>
            <input
              type="number"
              min={1}
              max={8}
              value={count}
              onChange={e => setCount(e.target.value)}
              className="field"
              style={{ width: 70, height: 32, padding: '0 8px', fontSize: 13.5, background: 'var(--surface)' }}
            />
            <span className="muted" style={{ fontSize: 11.5 }}>max 8</span>
          </div>
          <button
            className={heroMode ? 'btn btn-brand btn-block' : 'btn btn-soft btn-block'}
            style={{ marginTop: 12, height: heroMode ? 44 : 38 }}
            onClick={() => onRegenerate({ guidance, questionCount: clampedCount() })}
            disabled={busy}
          >
            {busy
              ? <span className="spinner" style={{ width: 14, height: 14 }} />
              : <Sparkles size={15} />}
            {label}
          </button>
          {heroMode && (
            <div className="muted" style={{ fontSize: 11.5, marginTop: 8, lineHeight: 1.4 }}>
              Coursedy drafts multiple-choice questions with plausible distractors and explanations.
            </div>
          )}
        </>
      )}
    </div>
  );
}

/* ============================================================
   Rail: Structure (prev/next module + disabled add question)
   ============================================================ */
function QuizStructurePanel({ prevMod, nextMod, onPrev, onNext, addingQ, addError, onAddQuestion }) {
  return (
    <div className="card" style={{ padding: 16 }}>
      <div className="row" style={{ gap: 8, marginBottom: 10 }}>
        <span className="center" style={{ width: 26, height: 26, borderRadius: 8, background: 'var(--brand-tint)', color: 'var(--brand-ink)', flexShrink: 0 }}>
          <List size={14} />
        </span>
        <div style={{ fontSize: 13.5, fontWeight: 700, letterSpacing: '-0.01em' }}>Structure</div>
      </div>
      <button
        className="btn btn-soft btn-block"
        disabled={addingQ}
        onClick={onAddQuestion}
        style={{ marginBottom: 8 }}
      >
        {addingQ
          ? <><span className="spinner" style={{ width: 13, height: 13 }} /> Adding…</>
          : <><Plus size={14} /> Add question</>}
      </button>
      {addError && (
        <div className="card fade-in" style={{ marginBottom: 8, padding: '8px 10px', background: 'var(--rose-tint, #fde9ee)', color: '#9c1f3c', borderRadius: 'var(--r-sm)', border: '1px solid #f5c2cf', fontSize: 12, lineHeight: 1.4 }}>
          {addError}
        </div>
      )}
      <div className="row" style={{ gap: 8 }}>
        <button
          className="btn btn-ghost btn-sm"
          style={{ flex: 1, opacity: prevMod ? 1 : 0.4 }}
          onClick={onPrev}
          disabled={!prevMod}
          title={prevMod ? prevMod.title : 'No previous module'}
        >
          <ChevL size={14} /> Previous
        </button>
        <button
          className="btn btn-ghost btn-sm"
          style={{ flex: 1, opacity: nextMod ? 1 : 0.4 }}
          onClick={onNext}
          disabled={!nextMod}
          title={nextMod ? nextMod.title : 'No next module'}
        >
          Next <ChevR size={14} />
        </button>
      </div>
    </div>
  );
}

/* ============================================================
   QuizChatPanel — left-side assistant (reuses course chat endpoint)
   ============================================================ */
function QuizChatPanel({ courseId, moduleTitle, moduleOrder, questionCount, onCourseUpdated }) {
  const seed = questionCount === 0
    ? { role: 'ai', text: 'Tell me how you want this quiz to test the module — concepts to emphasize, question style, anything off-limits.' }
    : { role: 'ai', text: 'Ask me to refine a question, change difficulty, swap the focus — or just talk through what this quiz should test.' };
  const [messages, setMessages] = useState([seed]);
  const [input, setInput] = useState('');
  const [sending, setSending] = useState(false);
  const scrollRef = useRef(null);

  useEffect(() => {
    setMessages([seed]);
    setInput('');
    setSending(false);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [courseId, moduleTitle]);

  useEffect(() => {
    if (scrollRef.current) scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
  }, [messages]);

  const submit = async () => {
    const val = (input || '').trim();
    if (!val || sending || !courseId) return;
    setInput('');
    setSending(true);
    const focused = `(Focus context: I'm editing the quiz for Module ${moduleOrder} — "${moduleTitle}".)\n\n${val}`;
    setMessages(m => [...m, { role: 'user', text: val }, { role: 'ai', typing: true }]);
    const history = messages
      .filter(x => !x.typing && (x.role === 'user' || x.role === 'ai'))
      .slice(-8)
      .map(x => ({ role: x.role === 'ai' ? 'assistant' : 'user', content: x.text || '' }))
      .filter(x => x.content);
    try {
      const res = await window.API.chatRefine(courseId, focused, history);
      const text = res.message || res.reply || '';
      const actions = Array.isArray(res.actions) ? res.actions : [];
      const errors = Array.isArray(res.errors) ? res.errors : [];
      if (res.course && onCourseUpdated) {
        try { await onCourseUpdated(); } catch (e) {}
      }
      setMessages(m => m.map((x, i) => i === m.length - 1 && x.typing ? { role: 'ai', text, actions, errors } : x));
    } catch (e) {
      setMessages(m => m.map((x, i) => i === m.length - 1 && x.typing ? { role: 'ai', text: 'Sorry — ' + (e?.message || 'something went wrong') + '.' } : x));
    } finally {
      setSending(false);
    }
  };

  return (
    <div style={{ display: 'flex', flexDirection: 'column', borderRight: '1px solid var(--line)', background: 'var(--surface)', minWidth: 0, minHeight: 0, height: '100%' }}>
      <div className="row" style={{ height: 56, padding: '0 16px', borderBottom: '1px solid var(--line)', gap: 11, flexShrink: 0 }}>
        <span className="logo-mark" style={{ width: 28, height: 28 }}><Spark size={15} /></span>
        <div className="grow" style={{ minWidth: 0 }}>
          <div style={{ fontSize: 13.5, fontWeight: 600 }}>Quiz Assistant</div>
          <div className="row" style={{ gap: 5, fontSize: 11, color: 'var(--muted)' }}><span className="live-dot" /> Online</div>
        </div>
      </div>

      <div ref={scrollRef} className="scroll" style={{ flex: 1, minHeight: 0, overflowY: 'auto', padding: 16, display: 'flex', flexDirection: 'column', gap: 14 }}>
        {messages.map((m, i) => <QuizChatMsg key={i} m={m} />)}
      </div>

      <div style={{ padding: 12, borderTop: '1px solid var(--line)', flexShrink: 0 }}>
        <div className="row" style={{ gap: 8, background: 'var(--surface)', border: '1px solid var(--line-strong)', borderRadius: 'var(--r-md)', padding: 7, boxShadow: 'var(--sh-xs)' }}>
          <input
            className="grow"
            style={{ border: 'none', outline: 'none', background: 'transparent', fontSize: 14 }}
            placeholder={questionCount === 0 ? 'What should this quiz emphasize?' : 'Ask the assistant…'}
            value={input}
            onChange={e => setInput(e.target.value)}
            onKeyDown={e => { if (e.key === 'Enter') submit(); }}
            disabled={sending}
          />
          <button
            className="btn btn-icon btn-brand btn-sm"
            onClick={submit}
            disabled={!input.trim() || sending}
            style={{ opacity: (input.trim() && !sending) ? 1 : .5 }}
          >
            {sending ? <span className="spinner" style={{ width: 13, height: 13 }} /> : <Send size={15} />}
          </button>
        </div>
      </div>
    </div>
  );
}

function QuizChatMsg({ m }) {
  if (m.role === 'user') return (
    <div className="row" style={{ justifyContent: 'flex-end', gap: 10 }}>
      <div style={{ maxWidth: '82%', background: 'var(--ink)', color: '#fff', padding: '10px 13px', borderRadius: '14px 14px 4px 14px', fontSize: 13.8, lineHeight: 1.5 }}>{m.text}</div>
    </div>
  );
  return (
    <div className="row" style={{ gap: 9, alignItems: 'flex-start' }}>
      <span className="logo-mark" style={{ width: 24, height: 24, flexShrink: 0 }}><Spark size={13} /></span>
      <div style={{ maxWidth: '88%', minWidth: 0 }}>
        <div style={{ background: 'var(--surface)', border: '1px solid var(--line)', padding: '10px 13px', borderRadius: '4px 14px 14px 14px', fontSize: 13.8, lineHeight: 1.55, boxShadow: 'var(--sh-xs)', wordBreak: 'break-word' }}>
          {m.typing ? <TypingDots /> : m.text}
        </div>
        {m.actions && m.actions.length > 0 && !m.typing && (
          <div className="row" style={{ flexWrap: 'wrap', gap: 6, marginTop: 6 }}>
            {m.actions.map((a, i) => (
              <span key={i} className="chip" style={{ background: 'var(--brand-tint)', borderColor: 'var(--brand-tint-2)', color: 'var(--brand-ink)', cursor: 'default' }}>
                <Check size={11} /> {a.type}
              </span>
            ))}
          </div>
        )}
        {m.errors && m.errors.length > 0 && !m.typing && (
          <div className="muted" style={{ marginTop: 6, fontSize: 11.5, color: 'var(--rose, #c84a4a)', lineHeight: 1.45 }}>
            {m.errors.map((e, i) => <div key={i}>{e.action ? `${e.action}: ` : ''}{e.message}</div>)}
          </div>
        )}
      </div>
    </div>
  );
}

Object.assign(window, { QuizPage });
