// Missions — live data, real SSE chat, real mission creation
const { useState: msUseState, useEffect: msUseEffect, useCallback: msUseCallback } = React;

function Missions({ goto, openId }) {
  const [missions, setMissions] = msUseState([]);
  const [loading, setLoading] = msUseState(true);
  const [creating, setCreating] = msUseState(false);
  const [activeMission, setActiveMission] = msUseState(null);
  const [detailLoading, setDetailLoading] = msUseState(false);

  msUseEffect(() => {
    fnGetCached('missions')
      .then(r => {
        const list = (r.missions || []).map(transformMission);
        setMissions(list);
        window.MISSIONS = list;
      })
      .catch(e => console.error('missions:', e))
      .finally(() => setLoading(false));
  }, []);

  msUseEffect(() => {
    if (!openId) { setActiveMission(null); return; }
    setDetailLoading(true);
    fnGet(`missions?id=${openId}`)
      .then(r => {
        if (r.mission) setActiveMission(transformMissionDetail({
          ...r.mission,
          mission_tasks: r.tasks || [],
          mission_volumes: r.volumes || [],
        }));
      })
      .catch(e => console.error('mission detail:', e))
      .finally(() => setDetailLoading(false));
  }, [openId]);

  function handleMissionCreated(newMission) {
    invalidateCache('missions');
    setMissions(m => [newMission, ...m]);
    window.MISSIONS = [newMission, ...(window.MISSIONS || [])];
  }

  if (openId) {
    if (detailLoading || !activeMission) {
      return (
        <div className="content">
          <div className="empty" style={{ padding: 80 }}><span className="spinner" /> Loading mission…</div>
        </div>
      );
    }
    return (
      <MissionView
        mission={activeMission}
        onBack={() => goto('missions')}
        goto={goto}
        onTaskToggle={(taskId) => {
          setActiveMission(m => ({
            ...m,
            todayTasks: m.todayTasks.map(t => t.id === taskId ? { ...t, done: !t.done } : t),
          }));
        }}
      />
    );
  }

  return (
    <>
      <Topbar
        crumbs={['Missions']}
        actions={<>
          <button className="btn primary" onClick={() => setCreating(true)}>
            <I.Plus size={11} strokeWidth={2.6} /> New Mission
          </button>
        </>}
      />

      <div className="content">
        <div style={{ padding: '18px 28px 64px', maxWidth: 1280, margin: '0 auto' }}>
          <div className="section-header">
            <div>
              <div className="section-title">Active missions</div>
              <div className="section-sub">{missions.length} mission{missions.length === 1 ? '' : 's'} · sorted by due date</div>
            </div>
          </div>

          {loading ? (
            <div className="empty" style={{ padding: 64 }}><span className="spinner" /> Loading…</div>
          ) : missions.length === 0 ? (
            <div className="empty" style={{ padding: 64 }}>
              No missions yet. Create one to start a study plan.
            </div>
          ) : (
            <div className="mission-grid">
              {missions.sort((a, b) => a.daysLeft - b.daysLeft).map(m => (
                <div key={m.id} className="mission-card" onClick={() => goto('mission', { id: m.id })}>
                  <div className="hstack" style={{ marginBottom: 8, gap: 6 }}>
                    <SubjectTag subject={m.subject} />
                    <Badge>{m.type}</Badge>
                    <span style={{ marginLeft: 'auto', fontSize: 11.5, color: m.daysLeft <= 7 ? 'var(--warn)' : 'var(--fg-3)' }}>
                      {m.daysLeft}d
                    </span>
                  </div>
                  <div style={{ fontSize: 13, fontWeight: 500, marginBottom: 4 }}>{m.title}</div>
                  <div className="muted" style={{ fontSize: 11.5, lineHeight: 1.5, marginBottom: 14, minHeight: 32 }}>
                    {m.description}
                  </div>
                  <div className="hstack" style={{ fontSize: 11.5, color: 'var(--fg-3)', marginBottom: 6 }}>
                    <I.Calendar size={11} /><span>Due {m.due}</span>
                    <span style={{ marginLeft: 'auto' }} className="tnum">{Math.round(m.progress * 100)}%</span>
                  </div>
                  <div className="progress">
                    <div className="progress-fill" style={{ width: `${m.progress * 100}%` }} />
                  </div>
                </div>
              ))}
            </div>
          )}
        </div>
      </div>

      {creating && (
        <NewMissionModal
          onClose={() => setCreating(false)}
          onCreated={(m) => { handleMissionCreated(m); goto('mission', { id: m.id }); }}
        />
      )}
    </>
  );
}

function NewMissionModal({ onClose, onCreated }) {
  const [stage, setStage] = msUseState('upload'); // 'upload' | 'analysing' | 'confirm' | 'creating'
  const [file, setFile] = msUseState(null);       // { name, base64, media_type }
  const [pastedText, setPastedText] = msUseState('');
  const [dragOver, setDragOver] = msUseState(false);
  const [parsed, setParsed] = msUseState(null);   // { title, subject, mission_type, due_date, description }
  const [dueDate, setDueDate] = msUseState('');
  const [extraContext, setExtraContext] = msUseState('');
  const [error, setError] = msUseState('');
  const fileInputRef = React.useRef(null);

  function readAsBase64(f) {
    return new Promise((resolve, reject) => {
      const reader = new FileReader();
      reader.onload = e => resolve(e.target.result.split(',')[1]);
      reader.onerror = reject;
      reader.readAsDataURL(f);
    });
  }

  async function extractDocxText(f) {
    const zip = await JSZip.loadAsync(await f.arrayBuffer());
    const xmlFile = zip.file('word/document.xml');
    if (!xmlFile) return '';
    const xml = await xmlFile.async('string');
    return xml
      .replace(/<w:p[ >]/g, '\n')
      .replace(/<w:t[^>]*>([^<]*)<\/w:t>/g, '$1 ')
      .replace(/<[^>]+>/g, '')
      .replace(/\s+/g, ' ')
      .trim();
  }

  async function handleFile(f) {
    if (!f) return;
    setError('');
    const isPdf = f.type === 'application/pdf';
    const isImage = f.type.startsWith('image/');
    const isDocx = f.name.endsWith('.docx') || f.name.endsWith('.doc')
      || f.type.includes('wordprocessingml') || f.type === 'application/msword';

    if (isPdf || isImage) {
      // Send as base64 — Claude reads these natively on the server
      const base64 = await readAsBase64(f);
      setFile({ name: f.name, base64, media_type: f.type });
    } else if (isDocx) {
      // Extract text client-side via JSZip; server gets plain text
      try {
        const text = await extractDocxText(f);
        setFile({ name: f.name, extractedText: text });
      } catch {
        setError('Could not read this Word document. Try pasting the text instead.');
      }
    } else {
      // Plain text files (.txt, .md, .csv, etc.)
      try {
        const text = await f.text();
        setFile({ name: f.name, extractedText: text });
      } catch {
        setError('Could not read this file type. Try pasting the text instead.');
      }
    }
  }

  function onDrop(e) {
    e.preventDefault();
    setDragOver(false);
    handleFile(e.dataTransfer.files?.[0]);
  }

  async function analyse() {
    if (!file && !pastedText.trim()) { setError('Upload a file or paste the assessment text.'); return; }
    setStage('analysing');
    setError('');
    try {
      const body = {};
      if (file?.base64) {
        // PDF or image — server sends to Claude natively
        body.file = { name: file.name, base64: file.base64, media_type: file.media_type };
      } else if (file?.extractedText) {
        // Docx or text file extracted client-side
        if (!file.extractedText.trim()) {
          setError('Could not extract text from this file. Try pasting the text instead.');
          setStage('upload');
          return;
        }
        body.text = file.extractedText;
      }
      if (pastedText.trim()) body.text = pastedText.trim();
      // ~600k chars ≈ 150k tokens — safely under Haiku's 200k limit even with prompt overhead
      if (body.text && body.text.length > 600_000) body.text = body.text.slice(0, 600_000);
      const result = await fnPost('mission-parse', body);
      setParsed(result);
      setDueDate(result.due_date || '');
      setStage('confirm');
    } catch (e) {
      setError(`Parse failed: ${e.message}. Try pasting the text instead.`);
      setStage('upload');
    }
  }

  async function create() {
    if (!dueDate) { setError('Please enter a due date.'); return; }
    setStage('creating');
    setError('');
    try {
      const desc = [parsed.description, extraContext.trim()].filter(Boolean).join('\n\n');
      const r = await fnPost('mission-create', {
        subject: parsed.subject,
        mission_type: parsed.mission_type,
        title: parsed.title,
        description: desc,
        due_date: dueDate,
      });
      onCreated(transformMission({
        id: r.missionId,
        subject: parsed.subject,
        mission_type: parsed.mission_type,
        title: parsed.title,
        description: desc,
        due_date: dueDate,
        mission_tasks: [],
      }));
      onClose();
    } catch (e) {
      setError(e.message || 'Failed to create mission.');
      setStage('confirm');
    }
  }

  const canAnalyse = file || pastedText.trim();

  return (
    <div className="overlay" onClick={onClose}>
      <div className="panel" style={{ width: 480 }} onClick={e => e.stopPropagation()}>
        <div className="panel-head">
          <div className="panel-title">New Mission</div>
          <button className="icon-btn" style={{ marginLeft: 'auto' }} onClick={onClose}><I.X size={12} /></button>
        </div>

        {/* ── Upload ── */}
        {stage === 'upload' && (
          <>
            <div className="panel-body" style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
              <div
                className={`drop-zone${dragOver ? ' dz-over' : ''}${file ? ' dz-filled' : ''}`}
                onDragOver={e => { e.preventDefault(); setDragOver(true); }}
                onDragLeave={() => setDragOver(false)}
                onDrop={onDrop}
                onClick={() => !file && fileInputRef.current?.click()}
              >
                <input
                  ref={fileInputRef}
                  type="file"
                  style={{ display: 'none' }}
                  onChange={e => handleFile(e.target.files?.[0])}
                />
                {file ? (
                  <div className="hstack" style={{ gap: 7, justifyContent: 'center' }}>
                    <I.File size={13} />
                    <span style={{ fontSize: 12.5 }}>{file.name}</span>
                    <button className="icon-btn" style={{ marginLeft: 2 }} onClick={e => { e.stopPropagation(); setFile(null); }}>
                      <I.X size={10} />
                    </button>
                  </div>
                ) : (
                  <>
                    <I.Upload size={18} className="dim" style={{ marginBottom: 6 }} />
                    <div style={{ fontSize: 12.5, color: 'var(--fg-2)' }}>Drop PDF or image</div>
                    <div className="dim" style={{ fontSize: 11.5, marginTop: 2 }}>or click to browse</div>
                  </>
                )}
              </div>

              <div className="hstack" style={{ gap: 8 }}>
                <div style={{ flex: 1, height: 1, background: 'var(--border)' }} />
                <span className="dim" style={{ fontSize: 11 }}>or paste text</span>
                <div style={{ flex: 1, height: 1, background: 'var(--border)' }} />
              </div>

              <textarea
                className="textarea"
                rows={5}
                placeholder="Paste the assessment notification here…"
                value={pastedText}
                onChange={e => setPastedText(e.target.value)}
              />

              {error && <div style={{ fontSize: 12, color: 'var(--danger)' }}>{error}</div>}
            </div>
            <div className="panel-foot">
              <button className="btn ghost" onClick={onClose}>Cancel</button>
              <button className="btn primary" style={{ marginLeft: 'auto' }} disabled={!canAnalyse} onClick={analyse}>
                Analyse <I.ArrowRight size={11} />
              </button>
            </div>
          </>
        )}

        {/* ── Analysing ── */}
        {stage === 'analysing' && (
          <div className="panel-body" style={{ padding: '52px 24px', textAlign: 'center' }}>
            <span className="spinner" style={{ marginBottom: 10 }} />
            <div style={{ fontSize: 13, color: 'var(--fg-2)' }}>Reading assessment…</div>
          </div>
        )}

        {/* ── Creating ── */}
        {stage === 'creating' && (
          <div className="panel-body" style={{ padding: '52px 24px', textAlign: 'center' }}>
            <span className="spinner" style={{ marginBottom: 10 }} />
            <div style={{ fontSize: 13, color: 'var(--fg-2)' }}>Building study plan…</div>
          </div>
        )}

        {/* ── Confirm ── */}
        {stage === 'confirm' && parsed && (
          <>
            <div className="panel-body" style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
              <div style={{ padding: '12px 14px', background: 'var(--bg-1)', borderRadius: 'var(--r-2)', border: '1px solid var(--border)' }}>
                <div className="hstack" style={{ gap: 6, marginBottom: 8 }}>
                  <SubjectTag subject={parsed.subject} />
                  <Badge>{parsed.mission_type === 'test' ? 'Test / Exam' : 'Project / Essay'}</Badge>
                </div>
                <div style={{ fontSize: 14, fontWeight: 500, marginBottom: 2 }}>{parsed.title}</div>
                {dueDate && (
                  <div className="dim" style={{ fontSize: 11.5 }}>
                    Due {new Date(dueDate + 'T00:00:00').toLocaleDateString('en', { weekday: 'short', day: 'numeric', month: 'long' })}
                  </div>
                )}
              </div>

              {!dueDate && (
                <div>
                  <label className="label">Due date <span style={{ color: 'var(--danger)' }}>*</span></label>
                  <input
                    className="input"
                    type="date"
                    value={dueDate}
                    onChange={e => setDueDate(e.target.value)}
                    min={new Date().toISOString().split('T')[0]}
                    autoFocus
                  />
                </div>
              )}

              {parsed.mission_type === 'project' && (
                <div>
                  <label className="label">Anything to add? <span className="dim" style={{ fontWeight: 400 }}>· optional</span></label>
                  <textarea
                    className="textarea"
                    rows={3}
                    placeholder="e.g. word limit, specific focus areas, rubric details…"
                    value={extraContext}
                    onChange={e => setExtraContext(e.target.value)}
                    autoFocus
                  />
                </div>
              )}

              {error && <div style={{ fontSize: 12, color: 'var(--danger)' }}>{error}</div>}
            </div>
            <div className="panel-foot">
              <button className="btn ghost" onClick={() => setStage('upload')}>← Back</button>
              <button className="btn primary" style={{ marginLeft: 'auto' }} disabled={!dueDate} onClick={create}>
                Create mission
              </button>
            </div>
          </>
        )}
      </div>
    </div>
  );
}

function MissionView({ mission, onBack, goto, onTaskToggle }) {
  const [tasks, setTasks] = msUseState(mission.todayTasks || []);
  const [orchOpen, setOrchOpen] = msUseState(false);

  // Sync tasks when mission prop changes
  msUseEffect(() => { setTasks(mission.todayTasks || []); }, [mission.id]);

  const toggleTask = (t) => {
    setTasks(ts => ts.map(x => x.id === t.id ? { ...x, done: !x.done } : x));
    onTaskToggle && onTaskToggle(t.id);
    fnPost('complete-task', { task_id: t.id, mission_id: mission.id, task_type: 'mission' }).catch(() => {
      setTasks(ts => ts.map(x => x.id === t.id ? { ...x, done: t.done } : x));
    });
  };

  return (
    <>
      <Topbar
        crumbs={[
          <span key="b" style={{ cursor: 'pointer' }} onClick={onBack}>Missions</span>,
          mission.title,
        ]}
        actions={<>
          <button
            className="btn ghost"
            onClick={() => goto('flashcards', { missionId: mission.id })}
            disabled={(mission.volumes || []).reduce((a, v) => a + (v.flashcards?.length || 0), 0) === 0}
          >
            <I.Cards size={11} /> Flashcards
          </button>
          <button className="btn ghost"><I.More size={12} /></button>
        </>}
      />

      <div className="mission-view">
        <div className="mv-col mv-left">
          <div className="mv-col-head">
            <span>Today</span>
            <span className="dim tnum" style={{ fontSize: 10.5 }}>{tasks.filter(t => t.done).length}/{tasks.length}</span>
          </div>
          <div className="mv-col-body">
            <div style={{ marginBottom: 18 }}>
              {tasks.length === 0 ? (
                <div className="empty" style={{ padding: 24, fontSize: 12 }}>No tasks scheduled for today.</div>
              ) : tasks.map(t => (
                <div key={t.id} className="hstack" style={{ padding: '6px 0', alignItems: 'flex-start', gap: 9 }}>
                  <Checkbox checked={t.done} onChange={() => toggleTask(t)} />
                  <div style={{ flex: 1, minWidth: 0 }}>
                    <div style={{ fontSize: 12.5, color: t.done ? 'var(--fg-3)' : 'var(--fg)', textDecoration: t.done ? 'line-through' : 'none', lineHeight: 1.4 }}>
                      {t.label}
                    </div>
                    <div className="hstack dim" style={{ fontSize: 11, gap: 4, marginTop: 2 }}>
                      <I.Clock size={9} /> {t.est}
                    </div>
                  </div>
                </div>
              ))}
            </div>

            <div style={{ fontSize: 10.5, color: 'var(--fg-3)', textTransform: 'uppercase', letterSpacing: '0.05em', marginBottom: 10, fontWeight: 500 }}>
              Roadmap → {mission.due}
            </div>
            <div>
              {(mission.roadmap || []).map((d, i) => (
                <div key={i} className={`roadmap-day ${d.state}`}>
                  <div className="pip" />
                  <div className="day-content">
                    <div className="day-label">
                      <span>{d.label}</span>
                      <span className="day-date">· {d.date}</span>
                    </div>
                    {d.tasks && <div className="day-tasks">{d.tasks}</div>}
                    {d.notes && d.notes.length > 0 && (
                      <div className="day-chips">
                        {d.notes.map((n, ni) => (
                          <NotionChip key={ni} title={n} onClick={() => window.open('about:blank', '_blank')} />
                        ))}
                      </div>
                    )}
                  </div>
                </div>
              ))}
            </div>
          </div>
        </div>

        <div className="mv-col">
          <div style={{ overflowY: 'auto', flex: 1, padding: '24px 36px 80px', maxWidth: 880, width: '100%', alignSelf: 'center' }}>
            <div className="hstack" style={{ marginBottom: 4 }}>
              <SubjectTag subject={mission.subject} />
              <Badge>{mission.type}</Badge>
              <span className="dim" style={{ fontSize: 11.5 }}>· Due {mission.due} · {mission.daysLeft}d left</span>
            </div>
            <h1 style={{ fontSize: 22, fontWeight: 500, letterSpacing: '-0.018em', margin: '4px 0 6px' }}>{mission.title}</h1>
            <p className="muted" style={{ fontSize: 13, lineHeight: 1.6, margin: '0 0 22px', maxWidth: 640 }}>{mission.description}</p>

            <div className="hstack" style={{ marginBottom: 18, gap: 14, padding: '12px 0', borderTop: '1px solid var(--border)', borderBottom: '1px solid var(--border)' }}>
              <div className="hstack" style={{ gap: 5 }}>
                <I.Layers size={11} className="dim" />
                <span className="dim" style={{ fontSize: 12 }}>{(mission.volumes || []).length} volumes</span>
              </div>
              <div style={{ flex: 1 }} />
              <div className="dim tnum" style={{ fontSize: 11.5 }}>{Math.round(mission.progress * 100)}%</div>
              <div style={{ width: 80 }} className="progress">
                <div className="progress-fill" style={{ width: `${mission.progress * 100}%` }} />
              </div>
            </div>

            <div style={{ fontSize: 10.5, color: 'var(--fg-3)', textTransform: 'uppercase', letterSpacing: '0.05em', marginBottom: 8, fontWeight: 500 }}>
              Study plan
            </div>

            {(mission.volumes || []).map((v, i) => (
              <div
                key={v.id}
                className="volume-row"
                onClick={() => v.notionUrl && window.open(v.notionUrl, '_blank', 'noopener')}
              >
                <span className="dim mono" style={{ fontSize: 10.5, width: 22 }}>V{i + 1}</span>
                <div style={{ flex: 1, minWidth: 0 }}>
                  <div className="hstack" style={{ gap: 6 }}>
                    <span style={{ fontSize: 13, fontWeight: 500 }}>{v.title}</span>
                    {v.done && <span className="hstack dim" style={{ fontSize: 11, gap: 3 }}><I.Check size={10} strokeWidth={2.6} /> Read</span>}
                  </div>
                  <div className="dim ellipsis" style={{ fontSize: 11.5, marginTop: 2 }}>{v.summary}</div>
                </div>
                {v.notionUrl && (
                  <span className="badge"><span className="nc-mark" style={{ width: 9, height: 9, fontSize: 7 }}>N</span> Notion</span>
                )}
                {v.notionUrl && <I.External size={11} className="faint" />}
              </div>
            ))}

            {(mission.volumes || []).length === 0 && (
              <div className="empty" style={{ padding: 32 }}>Study volumes are being generated…</div>
            )}
          </div>
        </div>
      </div>

      <button className="orch-trigger" onClick={() => setOrchOpen(true)}>
        <span className="pulse-dot" />
        Ask Lynxe
      </button>

      {orchOpen && <OrchestratorPanel mission={mission} onClose={() => setOrchOpen(false)} />}
    </>
  );
}

function OrchestratorPanel({ mission, onClose }) {
  const initText = `Full context on "${mission.title}". I can answer questions, help you understand volumes, or search the web for practice resources. What's on your mind?`;
  const [msgs, rawSend, streamIdx, busy] = useSSEChat(initText);

  const send = msUseCallback((text) => {
    rawSend(text, 'mission-chat', { missionId: mission.id, message: text });
  }, [rawSend, mission.id]);

  return (
    <>
      <div className="orch-overlay" onClick={onClose} />
      <div className="orch-panel">
        <div className="mv-col-head" style={{ height: 40 }}>
          <span className="hstack" style={{ gap: 6, color: 'var(--fg)', textTransform: 'none', letterSpacing: 0, fontSize: 12.5, fontWeight: 500 }}>
            <I.Sparkle size={11} />
            Ask Lynxe
            <span className="hstack dim" style={{ fontSize: 11, gap: 4, marginLeft: 6 }}>
              <span style={{ width: 5, height: 5, borderRadius: 3, background: 'var(--ok)' }} />
              Live
            </span>
          </span>
          <button className="icon-btn" onClick={onClose}><I.X size={12} /></button>
        </div>

        <div className="hstack" style={{ padding: '8px 12px', borderBottom: '1px solid var(--border)', gap: 5, flexWrap: 'wrap' }}>
          <button className="btn ghost" style={{ height: 24, padding: '0 8px', fontSize: 11.5 }} onClick={() => send('How should I approach this assessment?')}><I.Sparkle size={10} /> Strategy</button>
          <button className="btn ghost" style={{ height: 24, padding: '0 8px', fontSize: 11.5 }} onClick={() => send('Search the web for practice resources')}><I.Globe size={10} /> Web</button>
          <button className="btn ghost" style={{ height: 24, padding: '0 8px', fontSize: 11.5 }} onClick={() => send('Summarise the key concepts I need to know')}><I.Layers size={10} /> Summary</button>
        </div>

        <ChatThread messages={msgs} streamingIndex={streamIdx} />
        <ChatInput placeholder="Tell Lynxe…" onSend={send} disabled={busy} />
      </div>
    </>
  );
}

window.Missions = Missions;
