// Upload — real file selection + parsing. Files are parsed in the browser
// (pdf.js, mammoth.js, native readers) into { kind:'text'|'image', text/image }.
// Once parsing is done, "Generate" stages files and navigates to Generation.

function UploadScreen({ subjectId }) {
  const subjects = useSubjects();
  const subject = subjects.find((s) => s.id === subjectId);
  if (!subject) {
    const loading = !subjectsLoaded();
    return (
      <Page>
        <PageHeader breadcrumb={[{ label: 'Dashboard', to: '/' }, loading ? 'Loading…' : 'Subject not found']} />
        <div style={{ padding: 22 }}>
          {loading ? (
            <div style={{ color: 'var(--ink-mute)', fontSize: 12 }}><span className="pulse">Loading subject…</span></div>
          ) : (
            <>
              <div style={{ fontSize: 13 }}>Subject not found.</div>
              <button className="btn small" style={{ marginTop: 10 }} onClick={() => navigate('/')}>Back to dashboard</button>
            </>
          )}
        </div>
      </Page>
    );
  }
  return <UploadScreenBody subject={subject} />;
}

function UploadScreenBody({ subject }) {
  const back = `/subject/${subject.id}`;

  // entries: { id, file, kind ('pdf'|'doc'|'txt'|'img'|'ppt'), status, parsed, error, pct, stage }
  const [entries, setEntries] = React.useState([]);
  const [dragOver, setDragOver] = React.useState(false);
  const [notes, setNotes] = React.useState('');
  const [mode, setMode] = React.useState('full'); // 'full' | 'flashcards'
  const inputRef = React.useRef(null);
  const idCounter = React.useRef(0);

  const addFiles = async (filesList) => {
    const files = Array.from(filesList);
    const fresh = files.map((file) => ({
      id: ++idCounter.current,
      file,
      name: file.name,
      kind: fileKindFromExt(file.name.split('.').pop()),
      size: formatSize(file.size),
      status: 'parsing',
      parsed: null,
      error: null,
      stage: 'reading',
    }));
    setEntries((prev) => [...prev, ...fresh]);

    for (const e of fresh) {
      try {
        const parsed = await parseFile(e.file);
        setEntries((prev) => prev.map((x) => x.id === e.id ? { ...x, status: 'done', parsed, stage: 'done' } : x));
      } catch (err) {
        setEntries((prev) => prev.map((x) => x.id === e.id ? { ...x, status: 'error', error: err.message, stage: 'error' } : x));
      }
    }
  };

  const onDrop = (ev) => {
    ev.preventDefault();
    setDragOver(false);
    if (ev.dataTransfer?.files?.length) addFiles(ev.dataTransfer.files);
  };

  const remove = (id) => setEntries((prev) => prev.filter((e) => e.id !== id));

  const okFiles = entries.filter((e) => e.status === 'done');
  const parsing = entries.some((e) => e.status === 'parsing');
  const canGenerate = okFiles.length > 0 && !parsing;

  const startGenerate = () => {
    const parsed = okFiles.map((e) => e.parsed);
    stageGeneration(subject.id, { files: parsed, notes, mode });
    const newId = newGuideId();
    navigate(`/subject/${subject.id}/guide/${newId}/generate`);
  };

  return (
    <Page>
      <PageHeader
        breadcrumb={[
          { label: 'Dashboard', to: '/' },
          { label: subject.name, to: back },
          'Add files',
        ]}
        actions={<button className="btn ghost small" onClick={() => navigate(back)}>Cancel</button>}
      />

      <div style={{ flex: 1, overflowY: 'auto', padding: '16px 22px', display: 'grid', gridTemplateColumns: '1.4fr 1fr', gap: 14 }}>
        <div>
          {/* Drop zone */}
          <div
            onDragOver={(e) => { e.preventDefault(); setDragOver(true); }}
            onDragLeave={() => setDragOver(false)}
            onDrop={onDrop}
            onClick={() => inputRef.current?.click()}
            style={{
              border: `2px dashed ${dragOver ? 'var(--blue-deep)' : 'var(--blue)'}`,
              borderRadius: 8,
              background: dragOver ? 'var(--blue-soft)' : 'var(--blue-wash)',
              padding: '28px 22px',
              cursor: 'pointer',
              transition: 'background .12s, border-color .12s',
              minHeight: 160,
              display: 'flex', flexDirection: 'column', justifyContent: 'center', gap: 8,
            }}
          >
            <input
              ref={inputRef}
              type="file"
              multiple
              accept=".pdf,.docx,.txt,.md,.png,.jpg,.jpeg,.webp,.gif"
              style={{ display: 'none' }}
              onChange={(e) => { if (e.target.files?.length) addFiles(e.target.files); e.target.value = ''; }}
            />
            <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
              <div style={{ display: 'flex', alignItems: 'center', gap: 8, color: 'var(--blue-deep)', fontWeight: 600, fontSize: 13 }}>
                <span style={{ width: 8, height: 8, borderRadius: 4, background: 'var(--blue)' }} />
                {dragOver ? 'Drop to add files' : 'Drag files here, or click to browse'}
              </div>
              <span className="mono" style={{ fontSize: 10, color: 'var(--ink-mute)' }}>PDF · DOCX · TXT · MD · IMG</span>
            </div>
            <div style={{ fontSize: 11, color: 'var(--ink-mute)' }}>
              Files are parsed in your browser before being sent to the model. PPTX is not yet supported — export slides as PDF or images for now.
            </div>
          </div>

          {/* List */}
          {entries.length > 0 && (
            <div style={{ marginTop: 14 }}>
              <div style={{ display: 'flex', alignItems: 'baseline', justifyContent: 'space-between', marginBottom: 6 }}>
                <h2 style={{ fontSize: 13, fontWeight: 600, margin: 0 }}>
                  Files <span className="mono" style={{ fontSize: 11, color: 'var(--ink-mute)', fontWeight: 400 }}>· {okFiles.length} of {entries.length} ready</span>
                </h2>
                <button className="btn ghost small" onClick={() => setEntries([])}>Clear</button>
              </div>
              <div style={{ background: 'white', border: '1px solid var(--line)', borderRadius: 8, overflow: 'hidden' }}>
                {entries.map((e, i) => <UploadRow key={e.id} entry={e} last={i === entries.length - 1} onRemove={() => remove(e.id)} />)}
              </div>
            </div>
          )}
        </div>

        {/* Right: settings + generate button */}
        <div>
          <h2 style={{ fontSize: 13, fontWeight: 600, margin: '0 0 8px' }}>Generate</h2>
          <div style={{ background: 'white', border: '1px solid var(--line)', borderRadius: 8, padding: 14, display: 'flex', flexDirection: 'column', gap: 10 }}>
            {/* Output type */}
            <div>
              <div style={{ fontSize: 10, textTransform: 'uppercase', letterSpacing: '0.08em', color: 'var(--ink-mute)', marginBottom: 6 }}>Output</div>
              <div style={{ display: 'flex', gap: 6 }}>
                {[
                  { value: 'full', label: 'Study guide', sub: 'sections + cards + quiz' },
                  { value: 'flashcards', label: 'Flashcards', sub: '16–30 cards only' },
                ].map((opt) => (
                  <button key={opt.value} type="button" onClick={() => setMode(opt.value)}
                    style={{
                      flex: 1, padding: '8px 10px', textAlign: 'left',
                      border: `1.5px solid ${mode === opt.value ? 'var(--blue)' : 'var(--line)'}`,
                      background: mode === opt.value ? 'var(--blue-wash)' : 'white',
                      borderRadius: 6, cursor: 'pointer',
                    }}>
                    <div style={{ fontSize: 12, fontWeight: 600, color: mode === opt.value ? 'var(--blue-deep)' : 'var(--ink)' }}>{opt.label}</div>
                    <div style={{ fontSize: 10, color: 'var(--ink-mute)', marginTop: 1 }}>{opt.sub}</div>
                  </button>
                ))}
              </div>
            </div>

            {/* Notes */}
            <div>
              <div style={{ fontSize: 10, textTransform: 'uppercase', letterSpacing: '0.08em', color: 'var(--ink-mute)', marginBottom: 6 }}>Notes (optional)</div>
              <textarea
                value={notes} onChange={(e) => setNotes(e.target.value)}
                placeholder="e.g. Focus on chapters 3–5. Skip the historical background. Use simple language."
                rows={4}
                style={{
                  width: '100%', resize: 'vertical', padding: 8,
                  border: '1px solid var(--line)', borderRadius: 6,
                  fontSize: 11.5, fontFamily: 'inherit', outline: 'none',
                  boxSizing: 'border-box',
                }}
              />
              <div style={{ fontSize: 10, color: 'var(--ink-mute)', marginTop: 4 }}>
                These notes are sent to the model alongside your files.
              </div>
            </div>

            <div style={{ borderTop: '1px solid var(--line-soft)', paddingTop: 10 }}>
              <div style={{ fontSize: 11.5, color: 'var(--ink-soft)', marginBottom: 6 }}>
                Files will be sent to <span className="mono">gpt-4o-mini</span> with vision.
              </div>
              <div style={{ display: 'flex', justifyContent: 'space-between', fontSize: 11.5, color: 'var(--ink-mute)' }}>
                <span>Sources</span>
                <span className="mono">{okFiles.length}</span>
              </div>
              <div style={{ display: 'flex', justifyContent: 'space-between', fontSize: 11.5, color: 'var(--ink-mute)' }}>
                <span>Total text length</span>
                <span className="mono">{formatChars(okFiles.reduce((n, e) => n + (e.parsed?.text?.length || 0), 0))}</span>
              </div>
            </div>

            <button
              className="btn blue"
              disabled={!canGenerate}
              onClick={startGenerate}
              style={{
                marginTop: 2, justifyContent: 'center',
                opacity: canGenerate ? 1 : 0.5, cursor: canGenerate ? 'pointer' : 'not-allowed',
              }}>
              {Icon.sparkle} {mode === 'flashcards' ? 'Generate flashcards' : 'Generate study guide'}
            </button>
            {parsing && <div style={{ fontSize: 11, color: 'var(--ink-mute)', textAlign: 'center' }}>Parsing files…</div>}
          </div>
        </div>
      </div>
    </Page>
  );
}

function UploadRow({ entry, last, onRemove }) {
  const { name, kind, size, status, error, parsed } = entry;
  const stageText =
    status === 'parsing' ? `Parsing ${kindLabel(kind)}…` :
    status === 'error'   ? `Failed: ${error}` :
    parsed?.kind === 'image' ? 'Ready · vision input' :
    parsed?.text ? `Ready · ${formatChars(parsed.text.length)} of text` :
    'Ready';
  const tone = status === 'error' ? 'var(--coral)' : status === 'done' ? 'var(--mint)' : 'var(--blue)';
  return (
    <div style={{
      display: 'flex', alignItems: 'center', gap: 10,
      padding: '8px 12px',
      borderBottom: last ? 'none' : '1px solid var(--line-soft)',
    }}>
      <FileGlyph kind={kind} />
      <div style={{ flex: 1, minWidth: 0 }}>
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline' }}>
          <div style={{ fontWeight: 500, fontSize: 12, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{name}</div>
          <div className="mono" style={{ fontSize: 10, color: 'var(--ink-mute)' }}>{size}</div>
        </div>
        <div style={{ height: 2, background: 'var(--line-soft)', borderRadius: 999, marginTop: 4, overflow: 'hidden' }}>
          <div style={{ width: status === 'done' ? '100%' : status === 'error' ? '100%' : '60%', height: '100%', background: tone, transition: 'width .2s' }} />
        </div>
        <div style={{ fontSize: 10, color: status === 'error' ? 'var(--coral)' : 'var(--ink-mute)', marginTop: 3 }}>{stageText}</div>
      </div>
      <button onClick={onRemove} style={{ border: 'none', background: 'transparent', color: 'var(--ink-mute)', cursor: 'pointer', fontSize: 16, lineHeight: 1, padding: 4 }} title="Remove">×</button>
    </div>
  );
}

function kindLabel(k) {
  return ({ pdf: 'PDF', doc: 'DOCX', ppt: 'PPTX', img: 'image', txt: 'text' })[k] || k;
}
function formatSize(b) {
  if (b < 1024) return b + ' B';
  if (b < 1024 * 1024) return (b / 1024).toFixed(1) + ' KB';
  return (b / 1024 / 1024).toFixed(1) + ' MB';
}
function formatChars(n) {
  if (n < 1000) return n + ' chars';
  if (n < 1000000) return (n / 1000).toFixed(1) + 'k chars';
  return (n / 1000000).toFixed(2) + 'M chars';
}

Object.assign(window, { UploadScreen });
