// Generation — kicks off the real OpenAI call. Files were staged by Upload.
// Stages are advanced for UX feedback; the actual API call is one HTTP request.

function GenerationScreen({ subjectId, guideId }) {
  const subjects = useSubjects();
  const subject = subjects.find((s) => s.id === subjectId);
  const subjectPath = subject ? `/subject/${subject.id}` : '/';
  const guidePath = subject && guideId ? `/subject/${subject.id}/guide/${guideId}` : subjectPath;

  // phase: 'preflight' | 'sending' | 'waiting' | 'done' | 'error' | 'no-files'
  const [phase, setPhase] = React.useState('preflight');
  const [error, setError] = React.useState(null);
  const [elapsed, setElapsed] = React.useState(0);
  const [staged] = React.useState(() => peekStagedGeneration(subjectId));
  const files = staged?.files || [];
  const notes = staged?.notes || '';
  const mode = staged?.mode || 'full';
  const [savedTitle, setSavedTitle] = React.useState(null);

  React.useEffect(() => {
    let cancelled = false;
    const tick = setInterval(() => setElapsed((e) => e + 1), 1000);

    (async () => {
      if (!files || files.length === 0) {
        setPhase('no-files');
        return;
      }
      // pop now so a re-mount doesn't re-trigger
      popStagedGeneration(subjectId);
      setPhase('sending');
      await sleep(300);
      if (cancelled) return;
      setPhase('waiting');
      try {
        const content = await generateStudyGuide(files, { subjectName: subject?.name, notes, mode });
        if (cancelled) return;
        const saved = await addGuide({
          subjectId,
          title: content.title || 'Untitled guide',
          sources: files.length,
          content,
        });
        if (cancelled) return;
        setSavedTitle(saved.title);
        setPhase('done');
        const realPath = `/subject/${subjectId}/guide/${saved.id}`;
        setTimeout(() => { if (!cancelled) navigate(realPath); }, 700);
      } catch (err) {
        if (cancelled) return;
        console.error(err);
        setError(err.message || String(err));
        setPhase('error');
      }
    })();

    return () => { cancelled = true; clearInterval(tick); };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  const stages = [
    { label: 'Reading',     sub: 'parse files', state: phase === 'preflight' ? 'working' : 'done' },
    { label: 'Sending',     sub: 'to gpt-4o-mini', state: phase === 'preflight' ? 'queued' : (phase === 'sending' ? 'working' : 'done') },
    { label: 'Generating',  sub: 'structured guide', state: ['preflight','sending'].includes(phase) ? 'queued' : (phase === 'waiting' ? 'working' : (phase === 'error' ? 'error' : 'done')) },
    { label: 'Done',        sub: 'guide ready', state: phase === 'done' ? 'done' : (phase === 'error' ? 'error' : 'queued') },
  ];

  return (
    <Page>
      <PageHeader
        breadcrumb={[
          { label: 'Dashboard', to: '/' },
          { label: subject?.name || 'Subject', to: subjectPath },
          phase === 'done' && savedTitle ? savedTitle : 'New guide',
        ]}
        actions={
          <>
            {phase === 'error' && (
              <button className="btn ghost small" onClick={() => navigate(`${subjectPath}/upload`)}>Try again</button>
            )}
            <button className="btn ghost small" onClick={() => navigate(subjectPath)}>
              {phase === 'done' || phase === 'error' || phase === 'no-files' ? 'Back' : 'Cancel'}
            </button>
            {phase === 'done' && (
              <button className="btn blue small" onClick={() => navigate(guidePath)}>View guide</button>
            )}
          </>
        }
      />

      <div style={{ flex: 1, overflowY: 'auto', padding: '16px 22px' }}>
        {phase === 'no-files' ? (
          <div style={{ background: 'white', border: '1px solid var(--line)', borderRadius: 10, padding: 22, textAlign: 'center' }}>
            <div style={{ fontSize: 14, fontWeight: 600 }}>No files staged for generation</div>
            <div style={{ fontSize: 12, color: 'var(--ink-mute)', margin: '6px 0 14px' }}>This usually means the page was reloaded mid-flow, or the upload step was skipped.</div>
            <button className="btn blue small" onClick={() => navigate(`${subjectPath}/upload`)}>Upload files</button>
          </div>
        ) : (
          <>
            <div style={{ display: 'flex', alignItems: 'center', gap: 12, marginBottom: 14 }}>
              <div style={{ width: 32, height: 32, borderRadius: 8, background: phase === 'error' ? 'var(--coral)' : 'var(--blue)', color: 'white', display: 'grid', placeItems: 'center' }}>{Icon.sparkle}</div>
              <div style={{ flex: 1 }}>
                <div style={{ fontSize: 13, fontWeight: 600 }}>
                  {phase === 'done' ? `Done · ${savedTitle}` :
                   phase === 'error' ? 'Generation failed' :
                   `Generating from ${files.length} source${files.length === 1 ? '' : 's'}…`}
                </div>
                <div style={{ fontSize: 11.5, color: 'var(--ink-mute)' }}>
                  {files.length} source{files.length === 1 ? '' : 's'} · elapsed {elapsed}s
                </div>
              </div>
              <span className={`chip ${phase === 'error' ? 'coral' : 'blue'}`}>
                <span className={phase === 'done' || phase === 'error' ? '' : 'pulse'} style={{ width: 6, height: 6, borderRadius: 3, background: 'currentColor' }} />
                {phase}
              </span>
            </div>

            <div style={{ background: 'white', border: '1px solid var(--line)', borderRadius: 8, padding: 14, marginBottom: 14 }}>
              <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 10 }}>
                {stages.map((s) => <Stage key={s.label} {...s} />)}
              </div>
            </div>

            {error && (
              <div style={{ background: 'var(--coral-soft)', border: '1px solid var(--coral)', borderRadius: 8, padding: 12, marginBottom: 14 }}>
                <div style={{ fontSize: 11, fontWeight: 600, color: '#8a3a20', marginBottom: 4 }}>Error</div>
                <div style={{ fontSize: 11.5, color: '#8a3a20', fontFamily: 'var(--font-mono)', whiteSpace: 'pre-wrap', wordBreak: 'break-word' }}>{error}</div>
                <div style={{ fontSize: 10.5, color: 'var(--ink-mute)', marginTop: 8 }}>
                  Common causes: OpenAI API key missing/invalid on the Worker, rate limit, or input too large. Check the Cloudflare logs.
                </div>
              </div>
            )}

            <div style={{ background: 'white', border: '1px solid var(--line)', borderRadius: 8, padding: 12 }}>
              <div style={{ fontSize: 10, textTransform: 'uppercase', letterSpacing: '0.08em', color: 'var(--ink-mute)', marginBottom: 8 }}>Sources</div>
              {files.length === 0 ? (
                <div style={{ fontSize: 11.5, color: 'var(--ink-mute)' }}>None</div>
              ) : files.map((f, i) => (
                <div key={i} style={{ display: 'flex', alignItems: 'center', gap: 8, padding: '4px 0', fontSize: 11.5 }}>
                  <span className="mono" style={{ color: 'var(--ink-mute)', width: 36, textTransform: 'uppercase', fontSize: 10 }}>{f.kind === 'image' ? 'IMG' : 'TXT'}</span>
                  <span style={{ flex: 1, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{f.name}</span>
                  <span className="mono" style={{ fontSize: 10, color: 'var(--ink-mute)' }}>
                    {f.kind === 'image' ? 'image' : `${f.text?.length || 0} ch`}
                  </span>
                </div>
              ))}
            </div>
          </>
        )}
      </div>
    </Page>
  );
}

function Stage({ label, sub, state }) {
  const color = state === 'done' ? 'var(--mint)' : state === 'working' ? 'var(--blue)' : state === 'error' ? 'var(--coral)' : 'var(--ink-whisper)';
  const pct = state === 'done' ? 100 : state === 'working' ? 60 : state === 'error' ? 100 : 0;
  const detail = state === 'done' ? 'done' : state === 'working' ? 'in progress…' : state === 'error' ? 'failed' : 'queued';
  return (
    <div style={{ borderLeft: `3px solid ${color}`, paddingLeft: 10 }}>
      <div style={{ display: 'flex', alignItems: 'baseline', justifyContent: 'space-between' }}>
        <div style={{ fontSize: 12, fontWeight: 600 }}>{label}</div>
        <div className="mono" style={{ fontSize: 10, color }}>{state === 'done' ? '✓' : state === 'error' ? '✗' : state === 'working' ? '…' : '—'}</div>
      </div>
      <div style={{ fontSize: 10, color: 'var(--ink-mute)', fontFamily: 'var(--font-mono)' }}>{sub}</div>
      <div style={{ height: 2, background: 'var(--line-soft)', borderRadius: 999, marginTop: 6, overflow: 'hidden' }}>
        <div style={{ width: `${pct}%`, height: '100%', background: color, transition: 'width 0.3s' }} />
      </div>
      <div className={state === 'working' ? 'pulse' : ''} style={{ fontSize: 10.5, marginTop: 5, color: state === 'queued' ? 'var(--ink-mute)' : color }}>{detail}</div>
    </div>
  );
}

function sleep(ms) { return new Promise((r) => setTimeout(r, ms)); }

Object.assign(window, { GenerationScreen });
