// assets/screen_session_detail.jsx — the HERO trace viewer
// 3 variants via t.traceLayout: timeline (Sentry rail), log (Datadog), chat (Cursor)

function ScreenSessionDetail({ id, go, t, setTweak }) {
  // Find session — fallback to first if id isn't matched exactly
  const session = SESSIONS.find(s => s.id === id) || SESSIONS.find(s => s.id.startsWith(id)) || SESSIONS[0];
  const events = React.useMemo(() => mkSessionEvents(session), [session.id]);

  const [filters, setFilters] = React.useState({
    hideSystem: false,
    hideToolResult: false,
    hideHooks: false,
    onlyErrors: false,
  });
  const [search, setSearch] = React.useState('');
  const [expanded, setExpanded] = React.useState(() => new Set(events.filter(e => e.type === 'hook-deny' || e.type === 'error').map(e => e.id)));

  const toggleExpand = (id) => {
    const n = new Set(expanded);
    if (n.has(id)) n.delete(id); else n.add(id);
    setExpanded(n);
  };

  const filteredEvents = events.filter(e => {
    if (filters.hideSystem && e.type === 'system') return false;
    if (filters.hideToolResult && e.type === 'tool-result') return false;
    if (filters.hideHooks && (e.type === 'hook-deny' || e.type === 'hook-soft' || e.type === 'loop')) return false;
    if (filters.onlyErrors && !['error', 'hook-deny'].includes(e.type)) return false;
    if (search) {
      const txt = JSON.stringify(e).toLowerCase();
      if (!txt.includes(search.toLowerCase())) return false;
    }
    return true;
  });

  const hookFires = events.filter(e => e.type === 'hook-deny' || e.type === 'hook-soft');
  const hookSummary = {};
  hookFires.forEach(e => {
    const k = `${e.hook}|${e.decision}`;
    hookSummary[k] = (hookSummary[k] || 0) + 1;
  });

  const toolUse = {};
  events.filter(e => e.type === 'tool-call').forEach(e => toolUse[e.tool] = (toolUse[e.tool] || 0) + 1);
  const toolUseArr = Object.entries(toolUse).map(([label, value]) => ({ label, value })).sort((a, b) => b.value - a.value);

  const filesTouched = [...new Set(events.filter(e => e.type === 'tool-call' && e.args?.path).map(e => e.args.path))];

  const errors = events.filter(e => e.type === 'error');

  const tok = session.tokens;
  const totalTok = tok.in + tok.out + tok.cacheRead + tok.cacheCreate;
  const costBreakdown = {
    in:   tok.in / 1000 * 0.003,
    out:  tok.out / 1000 * 0.015,
    cR:   tok.cacheRead / 1000 * 0.000375,
    cC:   tok.cacheCreate / 1000 * 0.00375,
  };

  return (
    <div className="page" style={{ paddingTop: 12, paddingBottom: 12, height: '100%', display: 'flex', flexDirection: 'column', maxWidth: 'none' }}>
      {/* Header */}
      <div style={{ display: 'flex', alignItems: 'flex-start', gap: 16, marginBottom: 14, flexShrink: 0 }}>
        <div style={{ flex: 1, minWidth: 0 }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 4 }}>
            <span style={{ fontSize: 19, fontWeight: 600, fontFamily: 'var(--font-mono)', letterSpacing: '-.01em', whiteSpace: 'nowrap' }}>{shortId(session.id, 12)}</span>
            <CopyButton text={session.id} />
            <StatusBadge status={session.status} />
            {session.loop_detected && <Badge kind="warning"><Icon name="loop" size={10} /> loop detected</Badge>}
          </div>
          <div style={{ display: 'flex', gap: 16, fontSize: 12, color: 'var(--text-secondary)', flexWrap: 'wrap' }}>
            <span><span className="dim">project</span> <span style={{ color: 'var(--text-primary)' }}>{session.project_name}</span> <Mono dim>{shortId(session.project_id, 12)}</Mono></span>
            <span><span className="dim">merchant</span> <Mono>{session.merchant}</Mono></span>
            <span><span className="dim">model</span> <Mono>{session.model_full}</Mono></span>
            <span><span className="dim">started</span> <Mono>{formatRel(session.started_at)}</Mono></span>
            <span><span className="dim">duration</span> <Mono className={session.duration > 900 ? 'text-danger' : session.duration > 300 ? 'text-warning' : 'text-success'}>{formatDur(session.duration)}</Mono></span>
            <span><span className="dim">cost</span> <Mono className="text-accent" style={{ fontWeight: 600 }}>${session.cost.toFixed(2)}</Mono></span>
          </div>
        </div>
        <div style={{ display: 'flex', gap: 6, flexShrink: 0 }}>
          <a href="#/sessions" className="btn ghost"><Icon name="chevron" size={13} style={{ transform: 'rotate(180deg)' }} /> All sessions</a>
          <button className="btn"><Icon name="external" size={12} /> Open project</button>
          <button className="btn" onClick={() => go('/deployments')}><Icon name="deploy" size={12} /> Deployment</button>
          <button className="btn"><Icon name="copy" size={12} /> Copy as curl</button>
        </div>
      </div>

      {/* Variant switcher in toolbar — also lives in Tweaks */}
      <div className="trace" style={{ flex: 1, minHeight: 0 }}>
        <div className="trace-timeline">
          <div className="trace-toolbar">
            <div className="segmented">
              <button className={t.traceLayout === 'timeline' ? 'active' : ''} onClick={() => setTweak('traceLayout', 'timeline')}>Timeline</button>
              <button className={t.traceLayout === 'log' ? 'active' : ''} onClick={() => setTweak('traceLayout', 'log')}>Log</button>
              <button className={t.traceLayout === 'chat' ? 'active' : ''} onClick={() => setTweak('traceLayout', 'chat')}>Chat</button>
            </div>
            <div style={{ position: 'relative', flex: 1, maxWidth: 320 }}>
              <Icon name="search" size={12} style={{ position: 'absolute', left: 8, top: 7, color: 'var(--text-tertiary)' }} />
              <input className="input" style={{ paddingLeft: 26 }} placeholder="⌘F search events…" value={search} onChange={e => setSearch(e.target.value)} />
            </div>
            <span className="dim fs-11" style={{ marginLeft: 'auto' }}>{filteredEvents.length} / {events.length} events</span>
            <button className={'btn xs ' + (filters.hideSystem ? 'primary' : 'ghost')} onClick={() => setFilters(f => ({ ...f, hideSystem: !f.hideSystem }))}>hide system</button>
            <button className={'btn xs ' + (filters.hideToolResult ? 'primary' : 'ghost')} onClick={() => setFilters(f => ({ ...f, hideToolResult: !f.hideToolResult }))}>hide tool_result</button>
            <button className={'btn xs ' + (filters.hideHooks ? 'primary' : 'ghost')} onClick={() => setFilters(f => ({ ...f, hideHooks: !f.hideHooks }))}>hide hooks</button>
            <button className={'btn xs ' + (filters.onlyErrors ? 'danger' : 'ghost')} onClick={() => setFilters(f => ({ ...f, onlyErrors: !f.onlyErrors }))}>only errors</button>
          </div>

          <div className="trace-list">
            {t.traceLayout === 'timeline' && <TimelineView events={filteredEvents} expanded={expanded} toggleExpand={toggleExpand} iconStyle={t.iconStyle} />}
            {t.traceLayout === 'log'      && <LogView events={filteredEvents} expanded={expanded} toggleExpand={toggleExpand} />}
            {t.traceLayout === 'chat'     && <ChatView events={filteredEvents} expanded={expanded} toggleExpand={toggleExpand} />}
          </div>
        </div>

        <SidePanel session={session} tok={tok} totalTok={totalTok} costBreakdown={costBreakdown}
          toolUseArr={toolUseArr} filesTouched={filesTouched} errors={errors} hookSummary={hookSummary} />
      </div>
    </div>
  );
}

// ─── Timeline view (Sentry-style) ──────────────────────────────────────────
function TimelineView({ events, expanded, toggleExpand, iconStyle }) {
  const baseT = events[0]?.t || 0;
  let prevT = baseT;
  return events.map((e, i) => {
    const rel = e.t - baseT;
    const gap = e.t - prevT;
    prevT = e.t;
    const gapBig = gap > 30;
    const mins = Math.floor(rel / 60), secs = Math.floor(rel % 60);
    return <TimelineEvent key={e.id || i} e={e} rel={rel} mins={mins} secs={secs} gap={gap} gapBig={gapBig} expanded={expanded} toggleExpand={toggleExpand} iconStyle={iconStyle} />;
  });
}

const EVENT_ICONS = {
  user:        { emoji: '🟦', lucide: 'user',     border: 'var(--info)',     cls: 'user', label: 'user' },
  assistant:   { emoji: '🟪', lucide: 'message',  border: '#b07cff',         cls: 'assistant', label: 'assistant' },
  'tool-call': { emoji: '🟧', lucide: 'tools',    border: 'var(--warning)',  cls: 'tool-call', label: 'tool_call' },
  'tool-result':{emoji: '🟩', lucide: 'check2',   border: 'var(--success)',  cls: 'tool-result', label: 'tool_result' },
  'hook-deny': { emoji: '🟥', lucide: 'ban',      border: 'var(--danger)',   cls: 'hook-deny', label: 'hook · DENY' },
  'hook-soft': { emoji: '🟨', lucide: 'shield',   border: 'var(--warning)',  cls: 'hook-soft', label: 'hook · soft' },
  error:       { emoji: '⚠️', lucide: 'alert',    border: 'var(--danger)',   cls: 'error', label: 'error' },
  system:      { emoji: '⚙️', lucide: 'settings', border: 'var(--text-tertiary)', cls: 'system', label: 'system' },
  loop:        { emoji: '🔁', lucide: 'loop',     border: 'var(--warning)',  cls: 'hook-soft', label: 'loop' },
};

function TimelineEvent({ e, rel, mins, secs, gap, gapBig, expanded, toggleExpand, iconStyle }) {
  const meta = EVENT_ICONS[e.type] || EVENT_ICONS.system;
  const isExpanded = expanded.has(e.id);
  const hasDetail = !!(e.content || e.message || (e.tool && e.args));
  return (
    <div className={`trace-event ${e.type === 'hook-deny' ? 'hook-deny' : ''} ${e.type === 'loop' ? 'loop-marker' : ''}`}>
      <div className="trace-event-time">
        {String(mins).padStart(2,'0')}:{String(secs).padStart(2,'0')}
        {gapBig && <span className="gap">+{Math.floor(gap)}s gap</span>}
      </div>
      <div className="trace-event-rail">
        <div className={`trace-event-marker ${meta.cls}`} style={iconStyle === 'border' ? { background: meta.border } : {}}>
          {iconStyle === 'emoji' && <span style={{ fontSize: 9 }}>{meta.emoji}</span>}
          {iconStyle === 'lucide' && <Icon name={meta.lucide} size={10} />}
          {iconStyle === 'border' && null}
        </div>
      </div>
      <div className="trace-event-card" onClick={() => hasDetail && toggleExpand(e.id)} style={{ cursor: hasDetail ? 'pointer' : 'default' }}>
        <div className="row1">
          <span className="type">{meta.label}</span>
          {e.tool && <Badge kind="neutral">{e.tool}</Badge>}
          {e.args?.path && <Mono dim>{e.args.path}</Mono>}
          {e.args?.cmd && <Mono dim>$ {e.args.cmd}</Mono>}
          {e.hook && <Mono>{e.hook}</Mono>}
          {e.decision === 'deny' && <Badge kind="danger">DENY</Badge>}
          {e.decision === 'soft' && <Badge kind="warning">soft</Badge>}
          {e.durationMs && <span className="meta">{e.durationMs}ms</span>}
          {e.tokens && <span className="meta">in {e.tokens.in.toLocaleString()} · out {e.tokens.out.toLocaleString()}</span>}
          {e.ok === false && <Badge kind="danger">failed</Badge>}
          {hasDetail && <Icon name={isExpanded ? 'chevronD' : 'chevron'} size={11} style={{ marginLeft: 'auto', color: 'var(--text-tertiary)', transform: isExpanded ? 'rotate(0)' : 'rotate(0)' }} />}
        </div>
        {(e.content || e.message) && (
          <div className={`preview ${e.type === 'tool-result' ? 'mono' : ''}`}>
            {e.content || e.message}
          </div>
        )}
        {isExpanded && (e.content || e.message) && (
          <div className="expanded">{e.content || e.message}</div>
        )}
      </div>
    </div>
  );
}

// ─── Log view (Datadog APM-style) ──────────────────────────────────────────
function LogView({ events, expanded, toggleExpand }) {
  const baseT = events[0]?.t || 0;
  return (
    <div className="trace-log">
      <div className="log-line" style={{ background: 'var(--bg-elevated)', fontWeight: 600, color: 'var(--text-tertiary)', textTransform: 'uppercase', fontSize: 10, letterSpacing: '.06em', cursor: 'default' }}>
        <div>time</div><div>type</div><div style={{ textAlign: 'right' }}>dur</div><div>message</div>
      </div>
      {events.map((e, i) => {
        const rel = e.t - baseT;
        const mins = Math.floor(rel / 60), secs = Math.floor(rel % 60), ms = Math.floor((rel % 1) * 1000);
        const meta = EVENT_ICONS[e.type] || EVENT_ICONS.system;
        const isExpanded = expanded.has(e.id);
        let msg = '';
        if (e.tool && e.args?.path) msg = `${e.tool} ${e.args.path}`;
        else if (e.tool && e.args?.cmd) msg = `${e.tool} $ ${e.args.cmd}`;
        else if (e.hook) msg = `${e.hook} · ${e.message?.slice(0, 100) || ''}`;
        else msg = (e.content || e.message || '').slice(0, 140);
        return (
          <React.Fragment key={e.id || i}>
            <div className={`log-line ${meta.cls} ${isExpanded ? 'expanded' : ''}`} onClick={() => toggleExpand(e.id)}>
              <span className="log-time">{String(mins).padStart(2,'0')}:{String(secs).padStart(2,'0')}.{String(ms).padStart(3,'0')}</span>
              <span className="log-type">{meta.label.replace(' · ', '.')}</span>
              <span className="log-dur">{e.durationMs ? e.durationMs + 'ms' : (e.tokens ? e.tokens.out + 'o' : '—')}</span>
              <span className="log-msg">{msg}</span>
            </div>
            {isExpanded && (e.content || e.message) && (
              <div style={{ padding: '8px 18px 12px 100px', background: 'var(--bg-base)', borderBottom: '1px solid var(--border-subtle)', fontFamily: 'var(--font-mono)', fontSize: 11.5, whiteSpace: 'pre-wrap', color: 'var(--text-secondary)', maxHeight: 240, overflow: 'auto' }}>
                {e.content || e.message}
              </div>
            )}
          </React.Fragment>
        );
      })}
    </div>
  );
}

// ─── Chat-transcript view (Cursor-style) ───────────────────────────────────
function ChatView({ events, expanded, toggleExpand }) {
  // Group consecutive assistant + tool calls into one bubble.
  const groups = [];
  let cur = null;
  events.forEach(e => {
    if (e.type === 'user') { groups.push({ kind: 'user', e, children: [] }); cur = null; }
    else if (e.type === 'assistant') { cur = { kind: 'assistant', e, children: [] }; groups.push(cur); }
    else if (e.type === 'system') groups.push({ kind: 'system', e, children: [] });
    else if (cur) cur.children.push(e);
    else groups.push({ kind: 'orphan', e, children: [] });
  });

  return (
    <div className="trace-chat">
      {groups.map((g, i) => {
        if (g.kind === 'system') {
          return <div key={i} style={{ alignSelf: 'center', fontSize: 11, color: 'var(--text-tertiary)', fontFamily: 'var(--font-mono)', padding: '4px 12px', background: 'var(--bg-elevated)', borderRadius: 12 }}>
            <Icon name="settings" size={10} style={{ verticalAlign: 'middle', marginRight: 4 }} />
            {g.e.content}
          </div>;
        }
        if (g.kind === 'user') {
          return <div key={i} className="chat-msg user">
            <div className="chat-avatar user">U</div>
            <div className="chat-bubble">{g.e.content}</div>
          </div>;
        }
        if (g.kind === 'assistant') {
          return <div key={i} className="chat-msg">
            <div className="chat-avatar assistant">AI</div>
            <div className="chat-bubble">
              <div>{g.e.content}</div>
              {g.e.tokens && <div style={{ marginTop: 6, fontSize: 10.5, color: 'var(--text-tertiary)', fontFamily: 'var(--font-mono)' }}>in {g.e.tokens.in.toLocaleString()} · out {g.e.tokens.out.toLocaleString()}</div>}
              {g.children.map((c, j) => {
                if (c.type === 'tool-call') {
                  const result = g.children[j + 1];
                  return (
                    <div key={j} className="chat-tool">
                      <div className="tool-head">
                        <Icon name="tools" size={11} />
                        <strong style={{ color: 'var(--accent)' }}>{c.tool}</strong>
                        {c.args?.path && <span style={{ color: 'var(--text-secondary)' }}>{c.args.path}</span>}
                        {c.args?.cmd && <span style={{ color: 'var(--text-secondary)' }}>$ {c.args.cmd}</span>}
                        {c.durationMs && <span style={{ marginLeft: 'auto', color: 'var(--text-tertiary)' }}>{c.durationMs}ms</span>}
                        {result && result.ok === false && <Badge kind="danger">failed</Badge>}
                      </div>
                      {result?.content && <div style={{ marginTop: 4, color: 'var(--text-tertiary)', whiteSpace: 'pre-wrap', maxHeight: 60, overflow: 'hidden', textOverflow: 'ellipsis' }}>{result.content.slice(0, 220)}</div>}
                    </div>
                  );
                }
                if (c.type === 'hook-deny') {
                  return <div key={j} className="chat-hook-deny">
                    <Icon name="ban" size={11} />
                    <strong>{c.hook} DENIED</strong>
                    <span style={{ color: 'var(--danger)', opacity: .8 }}>{c.message}</span>
                  </div>;
                }
                if (c.type === 'hook-soft') {
                  return <div key={j} style={{ marginTop: 6, padding: '4px 10px', background: 'var(--warning-muted)', borderRadius: 6, fontSize: 11.5, color: 'var(--warning)', display: 'flex', gap: 6, alignItems: 'center' }}>
                    <Icon name="shield" size={11} />
                    <Mono>{c.hook}</Mono>
                    <span style={{ opacity: .8 }}>{c.message?.slice(0, 120)}</span>
                  </div>;
                }
                if (c.type === 'loop') {
                  return <div key={j} style={{ marginTop: 6, padding: '6px 10px', background: 'var(--warning-muted)', border: '1px dashed var(--warning)', borderRadius: 6, fontSize: 11.5, color: 'var(--warning)', display: 'flex', gap: 6, alignItems: 'center' }}>
                    <Icon name="loop" size={11} /> <strong>Loop:</strong> {c.message}
                  </div>;
                }
                if (c.type === 'error') {
                  return <div key={j} style={{ marginTop: 6, padding: '6px 10px', background: 'var(--danger-muted)', borderRadius: 6, fontSize: 11.5, color: 'var(--danger)', display: 'flex', gap: 6, alignItems: 'center' }}>
                    <Icon name="alert" size={11} /> <strong>Error:</strong> {c.message}
                  </div>;
                }
                return null;
              })}
            </div>
          </div>;
        }
        return null;
      })}
    </div>
  );
}

// ─── Right detail panel ────────────────────────────────────────────────────
function SidePanel({ session, tok, totalTok, costBreakdown, toolUseArr, filesTouched, errors, hookSummary }) {
  const totalCost = Object.values(costBreakdown).reduce((a, b) => a + b, 0);
  return (
    <div className="trace-side">
      <h4>Token breakdown</h4>
      <div className="token-bar">
        <div style={{ width: `${tok.in/totalTok*100}%`, background: 'var(--chart-1)' }} />
        <div style={{ width: `${tok.out/totalTok*100}%`, background: 'var(--chart-2)' }} />
        <div style={{ width: `${tok.cacheRead/totalTok*100}%`, background: 'var(--chart-4)' }} />
        <div style={{ width: `${tok.cacheCreate/totalTok*100}%`, background: 'var(--chart-5)' }} />
      </div>
      <div style={{ display: 'grid', gridTemplateColumns: 'auto 1fr auto', gap: '4px 12px', fontSize: 11.5, fontFamily: 'var(--font-mono)' }}>
        {[
          ['input',         tok.in,          costBreakdown.in,  'var(--chart-1)'],
          ['output',        tok.out,         costBreakdown.out, 'var(--chart-2)'],
          ['cache read',    tok.cacheRead,   costBreakdown.cR,  'var(--chart-4)'],
          ['cache create',  tok.cacheCreate, costBreakdown.cC,  'var(--chart-5)'],
        ].map(([l, t, c, col]) => (
          <React.Fragment key={l}>
            <span style={{ display: 'flex', alignItems: 'center', gap: 4, color: 'var(--text-secondary)' }}><span style={{ width: 6, height: 6, background: col, borderRadius: 2 }} />{l}</span>
            <span style={{ textAlign: 'right' }}>{t.toLocaleString()}</span>
            <span style={{ color: 'var(--text-tertiary)' }}>${c.toFixed(3)}</span>
          </React.Fragment>
        ))}
        <span style={{ paddingTop: 6, borderTop: '1px solid var(--border-subtle)', color: 'var(--text-secondary)', fontWeight: 600 }}>total</span>
        <span style={{ paddingTop: 6, borderTop: '1px solid var(--border-subtle)', textAlign: 'right', fontWeight: 600 }}>{totalTok.toLocaleString()}</span>
        <span style={{ paddingTop: 6, borderTop: '1px solid var(--border-subtle)', fontWeight: 600, color: 'var(--accent)' }}>${totalCost.toFixed(2)}</span>
      </div>

      <h4>Tool usage</h4>
      <HBarChart data={toolUseArr} maxBars={9} color="var(--chart-3)" />

      <h4>Files touched ({filesTouched.length})</h4>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 2 }}>
        {filesTouched.slice(0, 12).map((f, i) => (
          <div key={i} style={{ display: 'flex', alignItems: 'center', gap: 6, padding: '3px 6px', borderRadius: 4, cursor: 'pointer', fontFamily: 'var(--font-mono)', fontSize: 11, color: 'var(--text-secondary)' }} className="filter-chip">
            <Icon name="fileText" size={11} />
            {f}
          </div>
        ))}
      </div>

      <h4>Hook fires</h4>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 4 }}>
        {Object.entries(hookSummary).map(([k, count]) => {
          const [hook, decision] = k.split('|');
          return (
            <div key={k} style={{ display: 'flex', alignItems: 'center', gap: 6, fontSize: 11.5 }}>
              <Badge kind={decision === 'deny' ? 'danger' : 'warning'}>{decision}</Badge>
              <Mono>{hook}</Mono>
              <span style={{ marginLeft: 'auto', fontFamily: 'var(--font-mono)', color: 'var(--text-tertiary)' }}>×{count}</span>
            </div>
          );
        })}
      </div>

      {errors.length > 0 && (
        <>
          <h4>Errors ({errors.length})</h4>
          {errors.map((e, i) => (
            <div key={i} style={{ padding: 8, background: 'var(--danger-muted)', borderRadius: 6, fontSize: 11.5, marginBottom: 6, color: 'var(--danger)' }}>
              {e.message}
              {e.file && <div className="mono" style={{ fontSize: 10.5, marginTop: 2, color: 'var(--text-tertiary)' }}>{e.file}</div>}
            </div>
          ))}
        </>
      )}
    </div>
  );
}

Object.assign(window, { ScreenSessionDetail });
