/* Krytz · Architecture playground
 *
 * 19 systems arranged in a grid. Click any to inspect; sample indicators
 * tick (throughput, p99, queue, errors). Tiny "metric chips" fly
 * out from the click site as a delightful confirmation.
 */

(function () {
  const { useState, useEffect, useRef, useMemo } = React;

  const SYSTEMS = [
    { id: 'parser',      name: 'Text parser',          group: 'capture', desc: 'Tokenize and normalize incoming text. <50ms p99, runs locally.' },
    { id: 'voice',       name: 'Voice transcriber',    group: 'capture', desc: 'Stream audio → text. Speaker-diarized, chunk-buffered.' },
    { id: 'vision',      name: 'Image · PDF reader',   group: 'capture', desc: 'Layout-aware extraction from screenshots, PDFs, and photos.' },
    { id: 'nlu',         name: 'NLU extractor',        group: 'understand', desc: 'Tasks, dates, blockers, commitments — structured at ingest.' },
    { id: 'entity',      name: 'Entity resolver',      group: 'understand', desc: 'Coalesce "Sam", "Samira", "@samira" → one canonical entity.' },
    { id: 'dedup',       name: 'Dedup system',         group: 'understand', desc: 'Near-duplicate detection. similarity grouping.' },
    { id: 'state',       name: 'Workspace map',          group: 'state', desc: 'Organized view of items, blockers, relationships, and status.' },
    { id: 'event',       name: 'Chronological history',       group: 'state', desc: 'Every state mutation logged. Time-travel and replay.' },
    { id: 'priority layer',      name: 'Multi-signal priority layer',  group: 'decide', desc: 'Clear priority signal across 7 signals. Stability-clamped.' },
    { id: 'antijitter',  name: 'Anti-jitter',          group: 'decide', desc: 'Settling rules on rank moves. No jitter.' },
    { id: 'capacity',    name: 'Capacity model',       group: 'decide', desc: 'Per-day budgets, protected slots, slack.' },
    { id: 'connected apps',  name: 'Connected app mesh',       group: 'act', desc: 'Calendar, email, project tools. Read + write, idempotent.' },
    { id: 'queue',       name: 'Action queue',         group: 'act', desc: 'Bounded queue, primary commit, retry with jitter.' },
    { id: 'learner',     name: 'Pattern learner',      group: 'learn', desc: 'Spots regularities in your behavior over time.' },
    { id: 'override',    name: 'Override memory',      group: 'learn', desc: 'Remembers your corrections, applies as rules.' },
    { id: 'memory',      name: 'Semantic memory',      group: 'remember', desc: 'Vectorized event store. Sourced semantic recall.' },
    { id: 'recall',      name: 'Causal recall',        group: 'remember', desc: '"What blocked X?" → state at the moment of stall.' },
    { id: 'budgeter',    name: 'AI budgeter',          group: 'ops', desc: 'Caps spend per user. Graceful degradation.' },
    { id: 'audit',       name: 'Activity history',            group: 'ops', desc: 'Every decision provenanced. Exportable, deletable.' },
  ];

  const GROUP_NUM = {
    capture: '01', understand: '02', state: '03', decide: '04',
    act: '05', learn: '06', remember: '07', ops: '08',
  };

  // Plausible-looking metric ranges per system type
  function metricRange(system) {
    const m = {
      capture:    { tpsBase: 12,  tpsVar: 6,   p99: 38,  qBase: 4,  err: 0.002 },
      understand: { tpsBase: 8,   tpsVar: 5,   p99: 92,  qBase: 6,  err: 0.004 },
      state:      { tpsBase: 24,  tpsVar: 8,   p99: 14,  qBase: 2,  err: 0.001 },
      decide:     { tpsBase: 6,   tpsVar: 4,   p99: 124, qBase: 3,  err: 0.003 },
      act:        { tpsBase: 3,   tpsVar: 2,   p99: 220, qBase: 2,  err: 0.006 },
      learn:      { tpsBase: 0.6, tpsVar: 0.4, p99: 480, qBase: 1,  err: 0.002 },
      remember:   { tpsBase: 4,   tpsVar: 2,   p99: 65,  qBase: 1,  err: 0.001 },
      ops:        { tpsBase: 1,   tpsVar: 0.5, p99: 18,  qBase: 0,  err: 0.0005 },
    };
    return m[system.group] || m.capture;
  }

  function FlyChip({ id, label, x, y, dx, dy }) {
    return (
      <div
        className="ep-fly"
        style={{
          left: x, top: y,
          '--dx': `${dx}px`, '--dy': `${dy}px`,
        }}
      >
        {label}
      </div>
    );
  }

  function Spark({ data, color = '#a99af0' }) {
    if (!data || data.length === 0) return null;
    const W = 320, H = 60;
    const max = Math.max(...data, 1);
    const min = Math.min(...data);
    const range = Math.max(max - min, 1);
    const pts = data.map((v, i) => {
      const x = (i / (data.length - 1)) * W;
      const y = H - ((v - min) / range) * (H - 8) - 4;
      return `${x.toFixed(1)},${y.toFixed(1)}`;
    }).join(' ');
    const areaPath = `M0,${H} L${pts.split(' ').join(' L')} L${W},${H} Z`;
    return (
      <svg className="ep-spark" viewBox={`0 0 ${W} ${H}`} preserveAspectRatio="none">
        <defs>
          <linearGradient id="ep-spark-grad" x1="0" y1="0" x2="0" y2="1">
            <stop offset="0%" stopColor={color} stopOpacity="0.45" />
            <stop offset="100%" stopColor={color} stopOpacity="0" />
          </linearGradient>
        </defs>
        <path d={areaPath} fill="url(#ep-spark-grad)" />
        <polyline points={pts} fill="none" stroke={color} strokeWidth="1.6" strokeLinejoin="round" strokeLinecap="round" />
      </svg>
    );
  }

  function SystemsPlayground() {
    const [activeId, setActiveId] = useState('priority layer');
    const active = SYSTEMS.find((e) => e.id === activeId);
    const range = metricRange(active);

    // Sample indicators for the active system
    const [tps, setTps] = useState(range.tpsBase);
    const [p99, setP99] = useState(range.p99);
    const [queue, setQueue] = useState(range.qBase);
    const [errors, setErrors] = useState(0);
    const [calls, setCalls] = useState(Math.floor(Math.random() * 2000 + 500));
    const [history, setHistory] = useState([]);
    const [pop, setPop] = useState(false);

    // Reset history when switching systems
    useEffect(() => {
      const r = metricRange(active);
      setTps(r.tpsBase);
      setP99(r.p99);
      setQueue(r.qBase);
      setErrors(0);
      setCalls(Math.floor(Math.random() * 2000 + 500));
      const seed = Array.from({ length: 24 }, () => r.tpsBase + (Math.random() - 0.5) * r.tpsVar * 2);
      setHistory(seed);
    }, [activeId]);

    // Tick
    useEffect(() => {
      const r = metricRange(active);
      const id = setInterval(() => {
        const nextTps = Math.max(0, r.tpsBase + (Math.random() - 0.5) * r.tpsVar * 2);
        setTps(nextTps);
        setP99(Math.max(1, r.p99 + (Math.random() - 0.5) * r.p99 * 0.3));
        setQueue(Math.max(0, Math.round(r.qBase + (Math.random() - 0.5) * 4)));
        setErrors((e) => Math.random() < r.err * 100 ? e + 1 : e);
        setCalls((c) => c + Math.round(nextTps));
        setHistory((h) => [...h.slice(-23), nextTps]);
        setPop(true);
        setTimeout(() => setPop(false), 220);
      }, 1200);
      return () => clearInterval(id);
    }, [activeId]);

    // Flying chips on click
    const [flies, setFlies] = useState([]);
    const layerRef = useRef(null);

    const onCardClick = (system, ev) => {
      const cardRect = ev.currentTarget.getBoundingClientRect();
      const cx = cardRect.left + cardRect.width / 2;
      const cy = cardRect.top + cardRect.height / 2;
      const r = metricRange(system);
      const chips = [
        `${r.tpsBase.toFixed(1)} tps`,
        `${r.p99}ms p99`,
        `queue ${r.qBase}`,
        '✓ healthy',
      ];
      const id = Date.now();
      const items = chips.map((label, i) => {
        const angle = (-90 + (i - 1.5) * 22) * Math.PI / 180;
        return {
          id: `${id}-${i}`,
          label,
          x: cx,
          y: cy,
          dx: Math.cos(angle) * 90,
          dy: Math.sin(angle) * 90,
        };
      });
      setFlies((f) => [...f, ...items]);
      setTimeout(() => {
        setFlies((f) => f.filter((x) => !items.find((it) => it.id === x.id)));
      }, 1200);
      setActiveId(system.id);
    };

    return (
      <div className="ep-wrap">
        <div className="ep-inner">
          <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', marginBottom: 24, flexWrap: 'wrap', gap: 16 }}>
            <div>
              <div className="eyebrow" style={{ color: 'var(--g-mid)' }}>Architecture playground</div>
              <h2 style={{ color: '#fff', fontSize: 'clamp(28px, 3.4vw, 40px)', fontWeight: 600, letterSpacing: '-0.025em', lineHeight: 1.1, marginTop: 8 }}>
                <span>{SYSTEMS.length} systems.</span> <em style={{ color: 'var(--g-mid)', fontStyle: 'normal' }}>Click any to preview.</em>
              </h2>
            </div>
            <div style={{ fontFamily: 'var(--mono)', fontSize: 11, color: 'rgba(255,255,255,0.55)', letterSpacing: '0.06em', textAlign: 'right' }}>
              <div>SYS · UPTIME 99.97%</div>
              <div>BUILD 2026.05.14</div>
            </div>
          </div>

          <div className="ep-layout">
            <div className="ep-grid">
              {SYSTEMS.map((e) => (
                <div
                  key={e.id}
                  className={`ep-card ${e.id === activeId ? 'is-on' : ''}`}
                  onClick={(ev) => onCardClick(e, ev)}
                >
                  <div className="ep-dot" />
                  <div className="ep-num">{GROUP_NUM[e.group]} · {e.group}</div>
                  <div className="ep-name">{e.name}</div>
                  <div className="ep-meta">{metricRange(e).tpsBase.toFixed(1)} tps · {metricRange(e).p99}ms</div>
                </div>
              ))}
            </div>

            <div className="ep-detail">
              <div className="ep-detail-head">
                <span className="num">{GROUP_NUM[active.group]} · {active.group}</span>
                <span className="name">{active.name}</span>
              </div>
              <div className="ep-detail-desc">{active.desc}</div>

              <div className="ep-metric-row">
                <span className="l">Throughput</span>
                <span className={`v ${pop ? 'pop' : ''}`}>{tps.toFixed(1)}<span className="u">tps</span></span>
              </div>
              <div className="ep-metric-row">
                <span className="l">p99 latency</span>
                <span className="v">{Math.round(p99)}<span className="u">ms</span></span>
              </div>
              <div className="ep-metric-row">
                <span className="l">Queue depth</span>
                <span className="v">{queue}</span>
              </div>
              <div className="ep-metric-row">
                <span className="l">Errors / 1k</span>
                <span className="v">{(range.err * 1000).toFixed(2)}</span>
              </div>
              <div className="ep-metric-row">
                <span className="l">Calls · 24h</span>
                <span className="v">{calls.toLocaleString()}</span>
              </div>

              <Spark data={history} color="#a99af0" />

              <div style={{ marginTop: 14, fontFamily: 'var(--mono)', fontSize: 10.5, color: 'rgba(255,255,255,0.45)', letterSpacing: '0.06em' }}>
                ◇ STREAM · live · 1.2s tick
              </div>
            </div>
          </div>
        </div>

        <div className="ep-fly-layer" ref={layerRef}>
          {flies.map((f) => (
            <FlyChip key={f.id} {...f} />
          ))}
        </div>
      </div>
    );
  }

  window.SystemsPlayground = SystemsPlayground;
})();
