// AiWorkspace.jsx — Arbeidsflaten (§4): chat-panel venstre + forhåndsvisning
// høyre, statusmeldinger (§5), feilkort (§9), godkjenningsknapper og admin
// API-logg (§10). Funksjonsuavhengig skall — previews velges per result.kind.

const { useState: useWsState, useEffect: useWsEffect, useRef: useWsRef } = React;

const AI_WS_TITLES = {
  'prioritize.day_plan': 'Dagsplan',
  'prioritize.week_plan': 'Ukeplan',
  'prioritize.revise_todos': 'Rydd todo-listen',
};

// Ferdig-status som blir stående i dashboard-baren etter en vellykket kjøring
// (i stedet for å falle tilbake til «Hva skal jeg hjelpe med i dag?») — se
// useDashAiTypedGreet i Dashboard.jsx.
const AI_WS_DONE_LABELS = {
  'prioritize.day_plan': 'Dagsplan utarbeidet',
  'prioritize.week_plan': 'Ukeplan utarbeidet',
  'prioritize.revise_todos': 'Opprydding klar',
};

function AiWorkspace({ action, wpFilter, instruction, scheduleHint, onClose, onApplied, onAllDone }) {
  const [turns, setTurns] = useWsState([]);
  const [result, setResult] = useWsState(null);
  const [aliasMap, setAliasMap] = useWsState({});
  const [aliasTitles, setAliasTitles] = useWsState({});
  const [aliasTables, setAliasTables] = useWsState({});
  const [aliasParents, setAliasParents] = useWsState({});
  const [warnings, setWarnings] = useWsState([]);
  const [running, setRunning] = useWsState(false);
  const [statusText, setStatusText] = useWsState('');
  const [error, setError] = useWsState(null);        // { code, message, runId }
  const [emptyState, setEmptyState] = useWsState(null);
  const [selection, setSelection] = useWsState({ activeOps: [], rejected: [] });
  const [applied, setApplied] = useWsState(null);     // kvittering
  const [applying, setApplying] = useWsState(false);
  const [confirmDiscard, setConfirmDiscard] = useWsState(false);
  const [debugOpen, setDebugOpen] = useWsState(false);
  const [mobView, setMobView] = useWsState('preview');

  const rotTimer = useWsRef(null);
  const lastRunId = useWsRef(null);
  const chatScroll = useWsRef(null);
  const startedRef = useWsRef(false);
  const abortRef = useWsRef(null);
  const cancelledRef = useWsRef(false);
  const doneRef = useWsRef(false);

  const title = AI_WS_TITLES[action] || 'AI';

  // ── Statuskanal (§5) — teksten kringkastes også til dashboard-baren
  // («Hva skal jeg hjelpe med i dag?») så statusen alltid er synlig der,
  // uansett hvor i arbeidsflaten brukeren har scrollet.
  function clearRot() { if (rotTimer.current) { clearInterval(rotTimer.current); rotTimer.current = null; } }
  function broadcastStatus(text, isRunning) {
    try { window.dispatchEvent(new CustomEvent('el-ai-status', { detail: { text: text || '', running: !!isRunning } })); } catch (e) { /* ignore */ }
  }
  function handleStatus(phase) {
    clearRot();
    if (phase === 'thinking') {
      const rot = window.elAiStatus.makeRotator();
      const first = rot.next();
      setStatusText(first);
      broadcastStatus(first, true);
      rotTimer.current = setInterval(() => {
        const next = rot.next();
        setStatusText(next);
        broadcastStatus(next, true);
      }, 3400);
    } else {
      const label = phase === 'done'
        ? (AI_WS_DONE_LABELS[action] || window.elAiStatus.phaseLabel('done'))
        : window.elAiStatus.phaseLabel(phase);
      setStatusText(label);
      broadcastStatus(label, phase !== 'done' && phase !== 'error');
    }
  }

  // Nullstill dashboard-baren når arbeidsflaten forlates.
  useWsEffect(() => () => broadcastStatus('', false), []);

  // ── Avbryt (§1) — kanskje man ikke vil allikevel ────────────────────────
  function cancelRun() {
    if (!running) return;
    cancelledRef.current = true;
    if (abortRef.current) { try { abortRef.current.abort(); } catch (e) { /* ignore */ } }
    clearRot();
    broadcastStatus('', false);
    setRunning(false);
    onClose && onClose();
  }
  useWsEffect(() => {
    function onCancelEvt() { cancelRun(); }
    window.addEventListener('el-ai-cancel', onCancelEvt);
    return () => window.removeEventListener('el-ai-cancel', onCancelEvt);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [running]);

  // ── Kjøring ─────────────────────────────────────────────────────────────
  async function runOnce(userText) {
    if (running) return;
    setError(null); setEmptyState(null); setApplied(null); setRunning(true);
    cancelledRef.current = false;
    let hadError = false;
    const controller = (typeof AbortController !== 'undefined') ? new AbortController() : null;
    abortRef.current = controller;

    let nextTurns = turns;
    if (userText) { nextTurns = [...turns, { role: 'user', text: userText }]; setTurns(nextTurns); }
    const transcript = window.elAiRun.toTranscript(nextTurns);

    try {
      const res = await window.elAiRun.run({
        action, wpFilter, instruction, scheduleHint,
        transcript, rejectedOps: selection.rejected, onStatus: handleStatus,
        signal: controller ? controller.signal : undefined,
      });
      if (cancelledRef.current) return;
      lastRunId.current = res.runId;
      setResult(res.result);
      setAliasMap(res.aliasMap || {});
      setAliasTitles(res.aliasTitles || {});
      setAliasTables(res.aliasTables || {});
      setAliasParents(res.aliasParents || {});
      setWarnings(res.warnings || []);
      setSelection({ activeOps: (res.result && res.result.ops) || [], rejected: [] });
      setTurns(t => [...t, { role: 'assistant', say: res.say, status: res.status, result: res.result, warnings: res.warnings }]);
    } catch (e) {
      if (cancelledRef.current || e.code === 'CANCELLED') return;
      hadError = true;
      if (e.code === 'CONTEXT_EMPTY') setEmptyState(e.message);
      else setError({ code: e.code || 'PROVIDER_ERROR', message: e.message, runId: lastRunId.current });
    } finally {
      clearRot();
      if (!cancelledRef.current) {
        setRunning(false);
        // Vellykket kjøring: la ferdig-statusen («Dagsplan utarbeidet») fra
        // handleStatus('done') bli stående i baren i stedet for å nullstille
        // den her — ellers rekker den aldri å vises (§ rapportert bug).
        if (hadError) broadcastStatus('', false);
      }
    }
  }

  // Første kjøring ved mount.
  useWsEffect(() => {
    if (startedRef.current) return;
    startedRef.current = true;
    runOnce();
    return () => clearRot();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  // Rull chatten ned ved nye meldinger.
  useWsEffect(() => {
    if (chatScroll.current) chatScroll.current.scrollTop = chatScroll.current.scrollHeight;
  }, [turns, statusText, running]);

  // ── Godkjenning / apply ─────────────────────────────────────────────────
  // «OK, gjør endringer» er endelig (§4): ingen ekstra «Ferdig»-klikk trengs —
  // statusen tastes ut («Topp — jeg gjør endringene…»), så flipper AI-baren
  // seg selv tilbake til dashbordet (onAllDone), som igjen har friskt opp
  // dagskortet via el-today-refresh (onApplied).
  function finishAndClose() {
    if (doneRef.current) return;
    doneRef.current = true;
    broadcastStatus('', false);
    if (onAllDone) onAllDone();
    else onClose && onClose();
  }
  async function approve() {
    const ops = selection.activeOps || [];
    if (!ops.length || applying) return;
    setApplying(true);
    broadcastStatus('Topp – jeg gjør endringene…', true);
    try {
      const res = await window.elAiApply.apply({ ops, aliasMap, aliasTables, wpFilter });
      setApplied(res);
      onApplied && onApplied(res);
      setTimeout(finishAndClose, 1400);
    } catch (e) {
      broadcastStatus('', false);
      setError({ code: 'APPLY_PARTIAL', message: e.message, runId: lastRunId.current });
    } finally {
      setApplying(false);
    }
  }

  function requestDiscard() {
    if (turns.length > 1 && !applied) setConfirmDiscard(true);
    else onClose && onClose();
  }

  const lastDebug = (window.elAiRun && window.elAiRun.getLastDebug && window.elAiRun.getLastDebug()) || null;
  const applyCount = (selection.activeOps || []).length;
  const approveLabel = action === 'prioritize.revise_todos'
    ? `OK, gjør ${applyCount} ${applyCount === 1 ? 'endring' : 'endringer'}`
    : 'OK, gjør endringer';

  function renderPreview() {
    if (!result) return null;
    const common = { result, aliasTitles, aliasTables, aliasParents, onChangeSelection: setSelection };
    if (result.kind === 'day_plan') return <AiPreviewDayPlan {...common} />;
    if (result.kind === 'week_plan') return <AiPreviewWeekPlan {...common} />;
    if (result.kind === 'todo_revision') return <AiPreviewRevision {...common} />;
    return <div className="ai-pv-empty">Ukjent forslagstype.</div>;
  }

  return (
    <div className="ai-ws" data-mob={mobView}>
      {/* Header = statuskanal (§5) */}
      <div className="ai-ws-head">
        <button className="ai-ws-back" onClick={requestDiscard} aria-label="Tilbake"><i className="ti ti-arrow-left"></i></button>
        <div className="ai-ws-head-txt">
          <div className="ai-ws-title">{title}</div>
          {/* Kjøre-status (§5) vises KUN i dashboard-toppbaren via broadcastStatus —
              her viser vi bare den ferdige tilstanden, ikke den roterende teksten,
              så statusmeldingen ikke dupliseres flere steder. */}
          {!running && (
            <div className="ai-ws-status">
              {error ? 'Noe gikk galt — se detaljer' : 'Forslag klart — juster eller godkjenn'}
            </div>
          )}
        </div>
        {running && (
          <button className="ai-ws-cancel-btn" onClick={cancelRun} title="Avbryt"><i className="ti ti-x"></i>Avbryt</button>
        )}
        {lastDebug && lastDebug.debug && (
          <button className="ai-ws-debug-btn" onClick={() => setDebugOpen(true)} title="API-logg (admin)"><i className="ti ti-code"></i></button>
        )}
      </div>

      {/* Mobil-faner */}
      <div className="ai-ws-tabs">
        <button className={mobView === 'chat' ? 'is-on' : ''} onClick={() => setMobView('chat')}>Chat</button>
        <button className={mobView === 'preview' ? 'is-on' : ''} onClick={() => setMobView('preview')}>Forslag</button>
      </div>

      <div className={`ai-ws-body${result && result.kind === 'day_plan' && !error && !emptyState ? ' ai-ws-body-3col' : ''}`}>
        {/* CHAT venstre */}
        <div className="ai-ws-chat">
          <div className="ai-ws-chat-scroll" ref={chatScroll}>
            {turns.map((t, i) => (
              t.role === 'user'
                ? <div key={i} className="ai-ws-msg is-user">{t.text}</div>
                : <div key={i} className="ai-ws-msg is-ai"><span className="ai-ws-msg-ic">AI</span><span>{t.say || '…'}</span></div>
            ))}
            {running && (
              <div className="ai-ws-msg is-ai is-typing">
                <span className="ai-ws-msg-ic">AI</span>
                <span className="ai-ws-dots" aria-label="Skriver…"><span></span><span></span><span></span></span>
              </div>
            )}
            {!!warnings.length && !running && (
              <div className="ai-ws-warns">
                {warnings.map((w, i) => <div key={i} className="ai-ws-warn"><i className="ti ti-alert-triangle"></i>{w}</div>)}
              </div>
            )}
          </div>
          <div className="ai-ws-chat-input">
            <QuickAdd
              placeholder="Skriv for å justere…"
              buttonTitle="Send"
              size="md"
              maxLength={2000}
              onAdd={(text) => { if (!running) runOnce(text); }}
            />
          </div>
        </div>

        {/* FORHÅNDSVISNING høyre */}
        <div className="ai-ws-preview">
          <div className="ai-ws-preview-scroll">
            {error && (
              <div className="ai-ws-errorcard">
                <div className="ai-ws-errorcard-ic"><i className="ti ti-alert-circle"></i></div>
                <div className="ai-ws-errorcard-msg">{error.message || 'Noe gikk galt.'}</div>
                {error.code !== 'MONTHLY_LIMIT_REACHED' && error.code !== 'PLAN_LIMIT_REACHED' && (
                  <button className="ai-ws-btn ai-ws-btn-pri" onClick={() => runOnce()}><i className="ti ti-refresh"></i>Prøv igjen</button>
                )}
                {error.runId && <div className="ai-ws-runid">ref: {String(error.runId).slice(0, 8)}</div>}
              </div>
            )}
            {emptyState && !error && (
              <div className="ai-ws-empty-friendly">
                <div className="ai-ws-empty-ic"><i className="ti ti-checkbox"></i></div>
                <div>{emptyState}</div>
              </div>
            )}
            {!error && !emptyState && (result ? renderPreview() : (
              <div className="ai-pv-loading">
                <div className="ai-pv-skel"></div><div className="ai-pv-skel"></div><div className="ai-pv-skel"></div>
              </div>
            ))}
          </div>

          {/* Godkjenning */}
          {result && !error && !emptyState && (
            <div className="ai-ws-actions">
              {applied ? (
                <div className="ai-ws-receipt">
                  <i className="ti ti-circle-check"></i>
                  <span>{applied.summary}</span>
                  <button className="ai-ws-btn ai-ws-btn-pri" onClick={finishAndClose}>Ferdig</button>
                </div>
              ) : (
                <>
                  <button className="ai-ws-btn ai-ws-btn-pri" onClick={approve} disabled={!applyCount || applying}>
                    <i className="ti ti-check"></i>{applying ? 'Utfører…' : approveLabel}
                  </button>
                  <button className="ai-ws-btn ai-ws-btn-ghost" onClick={requestDiscard}><i className="ti ti-x"></i>Forkast</button>
                </>
              )}
            </div>
          )}
        </div>
      </div>

      {confirmDiscard && ReactDOM.createPortal(
        <div className="is-wrap" onClick={() => setConfirmDiscard(false)}>
          <div className="is-card" onClick={e => e.stopPropagation()}>
            <div className="is-head"><span className="is-title">Forkaste forslaget?</span>
              <button className="is-close" onClick={() => setConfirmDiscard(false)} aria-label="Lukk"><i className="ti ti-x"></i></button>
            </div>
            <div className="is-body">
              <p className="gd-confirm-msg">Du har en samtale i gang. Forkast forslaget og lukk?</p>
              <div className="is-actions">
                <div style={{ flex: 1 }} />
                <button className="is-btn-cancel" onClick={() => setConfirmDiscard(false)}>Avbryt</button>
                <button className="is-btn-del" onClick={() => { setConfirmDiscard(false); onClose && onClose(); }}><i className="ti ti-trash"></i><span>Forkast</span></button>
              </div>
            </div>
          </div>
        </div>, document.body)}

      {debugOpen && lastDebug && lastDebug.debug && (
        <AiDebugModal debug={lastDebug.debug} onClose={() => setDebugOpen(false)} />
      )}
    </div>
  );
}

// Admin API-logg-modal (§10) — input/output som formatert tekst + Kopier.
function AiDebugModal({ debug, onClose }) {
  const text = JSON.stringify(debug, null, 2);
  const [copied, setCopied] = useWsState(false);
  function copy() {
    try { navigator.clipboard.writeText(text); setCopied(true); setTimeout(() => setCopied(false), 1500); } catch (e) { /* ignore */ }
  }
  return ReactDOM.createPortal(
    <div className="is-wrap" onClick={onClose}>
      <div className="is-card ai-dbg-card" onClick={e => e.stopPropagation()}>
        <div className="is-head">
          <span className="is-title">API-logg <span className="ai-dbg-runid">{debug.run_id ? String(debug.run_id).slice(0, 8) : ''}</span></span>
          <button className="is-close" onClick={onClose} aria-label="Lukk"><i className="ti ti-x"></i></button>
        </div>
        <div className="is-body">
          <div className="ai-dbg-bar">
            <span className="ai-dbg-meta">{debug.model} · {debug.usage ? debug.usage.total_tokens : 0} tokens · {debug.repairs || 0} reparasjon{(debug.repairs || 0) === 1 ? '' : 'er'}</span>
            <button className="ai-ws-btn ai-ws-btn-ghost" onClick={copy}><i className="ti ti-copy"></i>{copied ? 'Kopiert' : 'Kopier'}</button>
          </div>
          <pre className="ai-dbg-pre">{text}</pre>
        </div>
      </div>
    </div>, document.body);
}

window.AiWorkspace = AiWorkspace;
window.AiDebugModal = AiDebugModal;
