// The three surfaces: transcript content + side panel per surface.
const { Composer, StatusLine, ApprovalCard, Badge, Segmented, Card, Thinking, IconButton: SIconButton, Button: SButton } = window.UnknotDesignSystem_fb2a11;
const I = window.UnknotDesignSystem_fb2a11.Icon;

function Column({ children, footer }) {
  const ref = React.useRef(null);
  React.useEffect(() => { if (ref.current) ref.current.scrollTop = ref.current.scrollHeight; });
  return (
    <div style={{ flex: 1, minHeight: 0, display: 'flex', flexDirection: 'column' }}>
      <div ref={ref} style={{ flex: 1, minHeight: 0, overflowY: 'auto', padding: '20px 28px 16px' }}>
        <div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>{children}</div>
      </div>
      <div style={{ padding: '0 28px' }}>{footer}</div>
    </div>
  );
}

/* ---------------- Project ---------------- */
const DIFF = [
  ['h', '', '', '@@ -10,9 +10,12 @@ export function invoiceTotal'],
  ['', '10', '10', 'import { Money } from "../money";'],
  ['-', '11', '', 'import { round } from "../math";'],
  ['+', '', '11', 'import { roundHalfEven, toMinor } from "../math";'],
  ['', '12', '12', ''],
  ['', '13', '13', 'export function invoiceTotal(lines: Line[], taxRate: number) {'],
  ['-', '14', '', '  const subtotal = lines.reduce((s, l) => s + l.qty * l.unitPrice, 0);'],
  ['-', '15', '', '  return round(subtotal * (1 + taxRate), 2);'],
  ['+', '', '14', '  const minor = lines.reduce('],
  ['+', '', '15', '    (s, l) => s + toMinor(l.qty * l.unitPrice), 0);'],
  ['+', '', '16', '  const tax = roundHalfEven(minor * taxRate);'],
  ['+', '', '17', '  return Money.fromMinor(minor + tax);'],
  ['', '16', '18', '}'],
];

function ProjectPanel({ onClose }) {
  const [tab, setTab] = React.useState('changes');
  const [view, setView] = React.useState('inline');
  const [file, setFile] = React.useState(0);
  const files = [['src/invoice/totals.ts', '+6', '-3'], ['src/invoice/totals.test.ts', '+18', ''], ['src/math.ts', 'pending approval', '']];
  return (
    <>
      <PanelHeader value={tab} onChange={setTab} onClose={onClose} tabs={[{ value: 'changes', label: 'Changes', count: 3 }, { value: 'files', label: 'Files' }, { value: 'terminal', label: 'Terminal' }, { value: 'pr', label: 'PR' }]} />
      {tab !== 'changes' ? <div style={{ padding: 28, color: 'var(--color-muted-foreground)' }}>This pane is not part of the UI kit recreation.</div> : (
      <div style={{ flex: 1, minHeight: 0, overflowY: 'auto' }}>
        <div style={{ padding: 12, display: 'flex', flexDirection: 'column', gap: 2, borderBottom: '1px solid var(--color-border)' }}>
          {files.map((f, i) => (
            <button key={f[0]} type="button" onClick={() => setFile(i)} style={{ display: 'flex', alignItems: 'center', gap: 8, height: 30, padding: '0 10px', borderRadius: 'var(--radius-lg)', border: 0, background: file === i ? 'var(--color-muted)' : 'transparent', cursor: 'pointer', color: 'var(--color-foreground)' }}>
              <I name={f[1] === 'pending approval' ? 'file-clock' : 'file-diff'} size={13} style={{ color: f[1] === 'pending approval' ? 'var(--color-warning)' : 'var(--color-muted-foreground)' }} />
              <span className="mono" style={{ fontSize: 'var(--font-size-base-sm)' }}>{f[0]}</span>
              <span className="tabular" style={{ marginLeft: 'auto', fontSize: 'var(--font-size-sm)', color: f[1] === 'pending approval' ? 'var(--color-warning)' : 'var(--color-success)' }}>{f[1]}</span>
              {f[2] ? <span className="tabular" style={{ fontSize: 'var(--font-size-sm)', color: 'var(--color-danger)' }}>{f[2]}</span> : null}
            </button>
          ))}
        </div>
        <div style={{ display: 'flex', alignItems: 'center', height: 44, padding: '0 14px' }}>
          <span className="mono" style={{ fontSize: 'var(--font-size-base-sm)', fontWeight: 600 }}>totals.ts</span>
          <span style={{ marginLeft: 'auto' }}><Segmented label="Diff view" value={view} onChange={setView} options={[{ value: 'inline', label: 'Inline' }, { value: 'split', label: 'Split' }]} /></span>
        </div>
        <div className="mono" style={{ fontSize: 'var(--font-size-base-sm)', lineHeight: 1.7 }}>
          {DIFF.map((d, i) => (
            <div key={i} style={{ display: 'grid', gridTemplateColumns: '34px 34px 14px 1fr', background: d[0] === '+' ? 'var(--color-diff-add)' : d[0] === '-' ? 'var(--color-diff-del)' : 'transparent', color: d[0] === 'h' ? 'var(--color-muted-foreground)' : 'var(--color-foreground)', whiteSpace: 'pre' }}>
              <span style={{ textAlign: 'right', paddingRight: 8, color: d[0] === '-' ? 'var(--color-diff-del-gutter)' : d[0] === '+' ? 'var(--color-diff-add-gutter)' : 'var(--color-faint-foreground)' }}>{d[1]}</span>
              <span style={{ textAlign: 'right', paddingRight: 8, color: d[0] === '+' ? 'var(--color-diff-add-gutter)' : 'var(--color-faint-foreground)' }}>{d[2]}</span>
              <span style={{ color: d[0] === '+' ? 'var(--color-diff-add-gutter)' : 'var(--color-diff-del-gutter)' }}>{d[0] === '+' || d[0] === '-' ? d[0] : ''}</span>
              <span style={{ paddingLeft: d[0] === 'h' ? 0 : 4, gridColumn: d[0] === 'h' ? '1 / -1' : undefined, paddingInlineStart: d[0] === 'h' ? 14 : 4 }}>{d[3]}</span>
            </div>
          ))}
        </div>
      </div>)}
      <div style={{ height: 40, flexShrink: 0, display: 'flex', alignItems: 'center', gap: 6, padding: '0 14px', borderTop: '1px solid var(--color-border)', fontSize: 'var(--font-size-base-sm)', color: 'var(--color-muted-foreground)' }}>
        <I name="git-branch" size={13} /><span style={{ minWidth: 0, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}><span className="mono">unknot/fix-rounding</span> · own worktree · uncommitted</span>
      </div>
    </>
  );
}

function ProjectSession({ setStatus }) {
  const [decision, setDecision] = React.useState(window.__shot && window.__shot.approved ? { d: 'allow' } : null);
  const [queued, setQueued] = React.useState(['also check credit notes use the same helper']);
  const [extra, setExtra] = React.useState([]);
  const decide = (d, grant) => { setDecision({ d, grant }); setStatus(d === 'allow' ? 'running' : 'running'); };
  return (
    <Column footer={<>
      <Composer mode="project" running queued={queued} onRemoveQueued={(i) => setQueued(queued.filter((_, j) => j !== i))} onSend={(t) => setQueued([...queued, t])} />
      <StatusLine cost="$0.84" tokens="412k tokens" extra="4 helpers" />
    </>}>
      <Activity icon="search" verb="Searched">round( · 7 matches in 4 files</Activity>
      <ToolCall command="pnpm vitest run src/invoice" result="exit 1 · 1.8s" defaultOpen
        output={<><span style={{ color: 'var(--color-danger)' }}>FAIL</span>{'  src/invoice/totals.test.ts > invoiceTotal > rounds multi-line invoices\nAssertionError: expected 10.02 to be 10.03\n❯ src/invoice/totals.test.ts:41:32\nTests  '}<span style={{ color: 'var(--color-danger)' }}>1 failed</span>{' | '}<span style={{ color: 'var(--color-success)' }}>11 passed</span>{' (12)'}</>} />
      <Prose>The subtotal is summed in floating point and rounded once at the end, so per-line fractions accumulate. I'll sum in integer minor units and round tax half-even. Handing the edit and a regression test to helpers.</Prose>
      <Helpers count="3 of 4 started" rows={[
        { status: 'done', name: 'Explore', detail: '7 call sites, 2 on the invoice path', cost: '$0.03' },
        { status: decision ? 'running' : 'waiting', name: 'Coding', detail: decision ? 'editing src/math.ts' : 'waiting for approval', cost: '$0.41' },
        { status: 'running', name: 'Test', detail: 'writing regression test', cost: '$0.03', child: true },
        { status: 'idle', name: 'Review', detail: 'not started', cost: '' },
      ]} />
      {decision ? (
        <Activity icon={decision.d === 'allow' ? 'check' : 'x'} verb={decision.d === 'allow' ? 'You approved' : 'You denied'}>
          Write · src/math.ts{decision.grant ? ' · always for this session' : ''}
        </Activity>
      ) : (
        <ApprovalCard effect="write" title="Coding wants to edit a file" aside="src/math.ts" onDecide={decide}
          input={'@@ -1,4 +1,15 @@\n+export function toMinor(amount: number): number {\n+  return Math.round(amount * 100);\n+}\n… 9 more lines · full diff in Changes'}
          review={{ verdict: 'approve', reason: 'Routine edit to a tracked file read earlier in this session, within scope.' }} />
      )}
      {decision ? <Thinking /> : null}
    </Column>
  );
}

/* ---------------- Ask ---------------- */
const TABLE = [['Belgium', '1 Jan 2026', '1 Jan 2026'], ['France', '1 Sep 2026', 'Sep 2026 large and mid-size; Sep 2027 small'], ['Germany', '1 Jan 2025', '2027 above €800k turnover; 2028 all'], ['Poland', '1 Feb 2026', 'Feb 2026 large; Apr 2026 others']];

function AskSession() {
  return (
    <Column footer={<><Composer mode="ask" placeholder="Ask a follow-up…" /><StatusLine cost="$0.03" tokens="9k tokens" extra="web search" /></>}>
      <UserMessage>When does mandatory B2B e-invoicing start in Belgium, France, Germany and Poland? Check the official sources.</UserMessage>
      <Activity icon="search" verb="Searched the web">e-invoicing mandate start dates · 8 results</Activity>
      <Activity icon="globe" verb="Read 4 pages">
        <span style={{ display: 'inline-flex', flexWrap: 'wrap', gap: 6, verticalAlign: 'middle' }}>{['finances.belgium.be', 'impots.gouv.fr', 'bundesfinanzministerium.de', 'ksef.podatki.gov.pl'].map((x, i) => <Badge key={x}>{i + 1} · {x}</Badge>)}</span>
      </Activity>
      <h3 style={{ margin: '4px 0 0', fontSize: 'var(--font-size-md)', fontWeight: 600 }}>Mandatory B2B e-invoicing: start dates</h3>
      <div style={{ border: '1px solid var(--color-border)', borderRadius: 'var(--radius-card)', overflow: 'hidden', background: 'var(--color-card)' }}>
        <table style={{ width: '100%', borderCollapse: 'collapse', fontSize: 'var(--font-size-base)' }}>
          <thead><tr>{['Country', 'Must receive', 'Must issue'].map((h) => <th key={h} style={{ textAlign: 'left', fontWeight: 500, color: 'var(--color-foreground-secondary)', padding: '9px 12px', borderBottom: '1px solid var(--color-border)' }}>{h}</th>)}</tr></thead>
          <tbody>{TABLE.map((r, i) => <tr key={r[0]}>{r.map((c, j) => <td key={j} style={{ padding: '9px 12px', borderTop: i ? '1px solid var(--color-border-subtle)' : 0 }}>{c}{j === 2 ? <sup style={{ color: 'var(--color-muted-foreground)', marginLeft: 2 }}>{i + 1}</sup> : null}</td>)}</tr>)}</tbody>
        </table>
      </div>
      <Prose>France and Germany phase issuing in by company size. The numbers link to each country's official guidance.</Prose>
      <UserMessage>Turn this into a slide for Monday's board meeting.</UserMessage>
      <Card padding={14} style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
        <span style={{ width: 32, height: 32, flexShrink: 0, borderRadius: 'var(--radius-md)', background: 'var(--color-muted)', color: 'var(--color-foreground-secondary)', display: 'grid', placeItems: 'center' }}><I name="list-checks" size={15} /></span>
        <span style={{ display: 'flex', flexDirection: 'column', flex: '1 1 0', minWidth: 0, lineHeight: 1.4 }}><b style={{ fontWeight: 600, fontSize: 'var(--font-size-base)' }}>A slide is a file, so this is work for a Task.</b><span style={{ fontSize: 'var(--font-size-base-sm)', color: 'var(--color-muted-foreground)' }}>Task builds the slide, keeps versions and exports to PowerPoint. This conversation and its sources go with it.</span></span>
        <span style={{ display: 'flex', gap: 6, flexShrink: 0 }}><SButton size="sm">Not now</SButton><SButton size="sm" variant="primary" icon="list-checks">Start a Task</SButton></span>
      </Card>
    </Column>
  );
}

/* ---------------- Task ---------------- */
function MemoPreview() {
  const ref = React.useRef(null);
  const [k, setK] = React.useState(0.6);
  React.useEffect(() => { const el = ref.current; const ro = new ResizeObserver(() => setK(el.clientWidth / 794)); ro.observe(el); return () => ro.disconnect(); }, []);
  return (
    <div ref={ref} style={{ position: 'relative', width: '100%', aspectRatio: '794 / 1123', borderRadius: 4, overflow: 'hidden', boxShadow: 'var(--shadow-card)', border: '1px solid var(--color-border)', background: '#fff' }}>
      <iframe src="../artifacts/view.html#f=reports&a=7c%20executive-memo" title="Decision memo: move the Frankfurt data centre to colocation by Q2 2027" tabIndex={-1} style={{ position: 'absolute', top: 0, left: 0, width: 794, height: 1123, border: 0, transform: 'scale(' + k + ')', transformOrigin: '0 0', pointerEvents: 'none' }} />
    </div>
  );
}

function TaskPanel({ onClose }) {
  const [tab, setTab] = React.useState('documents');
  return (
    <>
      <PanelHeader value={tab} onChange={setTab} onClose={onClose} tabs={[{ value: 'documents', label: 'Documents', count: 2 }, { value: 'workspace', label: 'Workspace' }, { value: 'browser', label: 'Browser' }]} />
      <div style={{ height: 44, display: 'flex', alignItems: 'center', gap: 6, padding: '0 12px', borderBottom: '1px solid var(--color-border)', flexShrink: 0 }}>
        <span style={{ display: 'inline-flex', alignItems: 'center', gap: 6, height: 28, padding: '0 10px', borderRadius: 'var(--radius-md)', background: 'var(--color-muted)', fontSize: 'var(--font-size-base)', fontWeight: 600, whiteSpace: 'nowrap' }}><I name="file-text" size={13} style={{ color: 'var(--color-info)' }} />Frankfurt decision memo.docx</span>
        <span style={{ display: 'inline-flex', alignItems: 'center', gap: 6, height: 28, padding: '0 10px', fontSize: 'var(--font-size-base)', color: 'var(--color-foreground-secondary)', whiteSpace: 'nowrap' }}><I name="sheet" size={13} />cost-model.xlsx</span>
        <span style={{ flex: 1 }} />
        <SIconButton small icon="chevron-left" label="Previous version" /><span style={{ fontSize: 'var(--font-size-base-sm)', color: 'var(--color-muted-foreground)', whiteSpace: 'nowrap' }}>v2 of 2</span><SIconButton small icon="chevron-right" label="Next version" disabled />
        <SButton size="sm" icon="download">Save to…</SButton>
      </div>
      <div style={{ flex: 1, minHeight: 0, overflow: 'hidden', padding: 18, background: 'var(--color-document-canvas)' }}>
        <MemoPreview />
      </div>
    </>
  );
}

function TaskSession() {
  const [queued, setQueued] = React.useState(['add the Dublin lease as a footnote']);
  return (
    <Column footer={<><Composer mode="task" workflow="plan" running queued={queued} onRemoveQueued={(i) => setQueued(queued.filter((_, j) => j !== i))} onSend={(t) => setQueued([...queued, t])} /><StatusLine cost="$0.27" tokens="148k tokens" extra="3 helpers" /></>}>
      <UserMessage>Write a one-page decision memo for the exec committee on moving the Frankfurt data centre. Use the lease, the three colocation quotes and the cost model in the shared folder.</UserMessage>
      <Activity icon="circle-check" verb="You approved">plan revision 1 · 4 steps</Activity>
      <Activity icon="folder-open" verb="Read">9 files in ~/Infrastructure/Frankfurt</Activity>
      <Helpers count="4 of 4 started" rows={[
        { status: 'done', name: 'Data analysis', detail: 'five-year cost by option', cost: '$0.06' },
        { status: 'done', name: 'Research', detail: 'lease terms and notice date', cost: '$0.04' },
        { status: 'done', name: 'Writer', detail: 'memo · executive-memo format', cost: '$0.09' },
        { status: 'running', name: 'Review', detail: 'checking figures against sources', cost: '$0.02' },
      ]} />
      <Activity icon="file-plus" verb="Created">Frankfurt decision memo.docx · v2</Activity>
      <Prose>The memo recommends colocation: $6.8M over five years against $8.7M to renew, and it avoids the $2.1M cooling refit. The chart's source line cites the landlord offer, the three quotes and cost model v3. Review is checking each figure against those files now.</Prose>
      <Thinking label="reviewing · 3 of 7 figures checked" />
    </Column>
  );
}

Object.assign(window, { ProjectSession, ProjectPanel, AskSession, TaskSession, TaskPanel });
