// forensic-engine.jsx — Direction 1: "The Forensic Engine"
//
// 12s loop, 16:9. Premium institutional pacing.
//
// Beats:
// 0.0 - 1.5s   Establish: dot grid, faint logo center, copy fades in
// 1.5 - 4.0s   Ingestion: raw tx hashes stream in from edges toward hub
// 4.0 - 7.5s   Processing: classifiers light up in sequence around the hub
// 7.5 - 10.5s  Emission: clean ledger rows emit out the right side
// 10.5 - 12s   Resolve: full ledger settles, "audit-ready" stamp, fade
//
// Loops cleanly: end state matches start (everything fades back).

function ForensicEngine({ palette = 'default' }) {
  const time = useTime();

  // Stage geometry — 1920×1080 working canvas
  const W = 1920, H = 1080;
  const HUB = { x: 960, y: 540 };

  // ── Establishing copy (top-left) ──────────────────────────────────────────
  // Stripe-style monospace eyebrow + display headline.
  const headlineOpacity = animate({ from: 0, to: 1, start: 0.3, end: 1.4 })(time)
                        * animate({ from: 1, to: 0, start: 10.8, end: 11.8 })(time);

  // ── Background grid intensity (calmer at start, brighter mid-arc) ────────
  const gridOpacity = interpolate([0, 1.5, 7, 11], [0.4, 0.8, 1, 0.4], Easing.easeInOutCubic)(time);

  // ── Ingestion: 14 tx particles streaming from edges to hub ───────────────
  // Each particle has: spawn time, origin angle (around hub), hash seed.
  const txCount = 16;
  const ingestStart = 1.4;
  const ingestEnd = 6.5;
  const txParticles = React.useMemo(() => {
    return Array.from({ length: txCount }, (_, i) => {
      const seed = i + 1;
      const stagger = (i / txCount) * (ingestEnd - ingestStart - 1.2);
      const angle = (i * 137.5) % 360; // golden-angle distribution
      const startRadius = 720 + (seed % 5) * 30;
      return {
        seed,
        spawn: ingestStart + stagger,
        travel: 1.4 + (seed % 3) * 0.2, // each takes ~1.4s to reach hub
        angle: angle * Math.PI / 180,
        startRadius,
        hash: makeHash(seed * 73, 12),
      };
    });
  }, []);

  // ── Classifier activation schedule ───────────────────────────────────────
  // Six classifiers light up in a cascade between 3.5s and 7s.
  const classifierStart = 3.5;
  const classifierStagger = 0.45;
  // Stack all six chips in a single left column so the right side stays
  // clear for the ledger panel. Hub sits to the right of the column.
  const classifiers = [
    { x: 290, y: 280, label: 'FUNCTION DECODER' },
    { x: 290, y: 380, label: 'CHAIN DETECT' },
    { x: 290, y: 480, label: 'PROTOCOL INTEL' },
    { x: 290, y: 580, label: 'RULE LIBRARY' },
    { x: 290, y: 680, label: 'CONSENSUS CHECK' },
    { x: 290, y: 780, label: 'CLASSIFICATION CACHE' },
  ];

  // Per-classifier active value 0..1 (peaks then holds high)
  const classifierActive = classifiers.map((_, i) => {
    const s = classifierStart + i * classifierStagger;
    const ramp = animate({ from: 0, to: 1, start: s, end: s + 0.35, ease: Easing.easeOutBack })(time);
    const fade = animate({ from: 1, to: 0.6, start: 9.8, end: 11.5 })(time);
    return ramp * fade;
  });

  // ── Logo node activation derived from classifier states + hub pulse ──────
  const hubPulse = interpolate(
    [0, 1.5, 3.5, 6, 8.5, 11, 12],
    [0.2, 0.4, 0.7, 1.0, 1.0, 0.5, 0.2],
    Easing.easeInOutSine
  )(time);
  const logoIntensity = interpolate(
    [0, 1, 3, 7, 10.5, 11.8],
    [0.4, 0.7, 0.95, 1, 0.85, 0.4],
    Easing.easeInOutCubic
  )(time);

  // Map 7 logo nodes to staggered activation pulses
  const nodeActivation = Array.from({ length: 7 }, (_, i) => {
    const s = classifierStart - 0.4 + i * 0.32;
    return animate({ from: 0.3, to: 1, start: s, end: s + 0.5, ease: Easing.easeOutCubic })(time)
         * animate({ from: 1, to: 0.5, start: 10, end: 11.8 })(time);
  });

  // ── Ledger emission — rows appear from 6.5s onward, right side ───────────
  const ledgerX = 1180;
  const ledgerY = 280;
  const ledgerW = 660;
  const ledgerRows = React.useMemo(() => {
    const rows = [
      { date: '03/14/26', asset: 'ETH',   amount: '2.4500',   type: 'SWAP',    confidence: 99, taxTag: 'Sched D · ST' },
      { date: '03/15/26', asset: 'USDC',  amount: '12,400',   type: 'BRIDGE',  confidence: 97, taxTag: 'Cost basis' },
      { date: '03/18/26', asset: 'stETH', amount: '0.084',    type: 'REWARD',  confidence: 96, taxTag: 'Ord. income' },
      { date: '03/22/26', asset: 'ARB',   amount: '1,250.0',  type: 'AIRDROP', confidence: 92, taxTag: 'Ord. income' },
      { date: '03/24/26', asset: 'WBTC',  amount: '0.0312',   type: 'TRADE',   confidence: 99, taxTag: 'Sched D · LT' },
      { date: '03/27/26', asset: 'AAVE',  amount: '4.812',    type: 'STAKE',   confidence: 98, taxTag: 'Cost basis' },
      { date: '03/29/26', asset: 'LINK',  amount: '88.40',    type: 'SWAP',    confidence: 99, taxTag: 'Sched D · ST' },
      { date: '04/02/26', asset: 'OP',    amount: '320.0',    type: 'AIRDROP', confidence: 94, taxTag: 'Ord. income' },
    ];
    return rows;
  }, []);

  const emissionStart = 6.4;
  const rowStagger = 0.32;

  return (
    <>
      {/* Background field */}
      <div style={{ position: 'absolute', inset: 0, background: CTE.bg1 }} />
      <GridBackground opacity={gridOpacity} />

      {/* Faint scanning vertical sheen — adds depth */}
      <div style={{
        position: 'absolute', inset: 0,
        background: `linear-gradient(90deg, transparent 0%, ${CTE.teal}05 ${(time * 12) % 100}%, transparent 100%)`,
        pointerEvents: 'none',
      }} />

      {/* Eyebrow + headline (top, spanning width) */}
      <div style={{
        position: 'absolute',
        left: 80, top: 80,
        right: 80,
        opacity: headlineOpacity,
        transform: `translateY(${(1 - headlineOpacity) * 8}px)`,
      }}>
        <div style={{
          fontFamily: FONTS.mono,
          fontSize: 13,
          letterSpacing: '0.28em',
          color: CTE.teal,
          marginBottom: 14,
        }}>
          ◆ &nbsp; CLASSIFICATION ENGINE
        </div>
        <div style={{
          fontFamily: FONTS.display,
          fontSize: 52,
          fontWeight: 600,
          color: CTE.text,
          letterSpacing: '-0.025em',
          lineHeight: 1.05,
        }}>
          Verified classifications, <span style={{ color: CTE.teal }}>derived from raw chain.</span>
        </div>
      </div>

      {/* Stats — bottom left */}
      <BottomStats time={time} />

      {/* Center glow */}
      <CenterGlow x={HUB.x} y={HUB.y} time={time} intensity={logoIntensity} size={620} />

      {/* Classifier chips */}
      {classifiers.map((c, i) => (
        <ClassifierChip
          key={c.label}
          x={c.x} y={c.y}
          label={c.label}
          active={classifierActive[i]}
          status={classifierActive[i] > 0.6 ? 'ok' : 'idle'}
          width={232}
        />
      ))}

      {/* Connector lines from each classifier (left col) to hub */}
      <svg width={W} height={H} style={{ position: 'absolute', inset: 0, pointerEvents: 'none' }}>
        {classifiers.map((c, i) => {
          const act = classifierActive[i];
          // From right edge of chip, bend at a fixed gutter, into hub left edge.
          const fromX = c.x + 116;
          const fromY = c.y;
          const bendX = 560;
          const hubLeftX = HUB.x - 150;
          const path = `M ${fromX} ${fromY} L ${bendX} ${fromY} L ${bendX} ${HUB.y} L ${hubLeftX} ${HUB.y}`;
          return (
            <g key={i}>
              <path d={path} fill="none" stroke={`${CTE.teal}40`} strokeWidth={1.5} />
              <path
                d={path}
                fill="none"
                stroke={CTE.teal}
                strokeWidth={2}
                strokeDasharray="6 14"
                strokeDashoffset={-time * 60}
                opacity={act * 0.9}
                style={{ filter: `drop-shadow(0 0 6px ${CTE.teal})` }}
              />
            </g>
          );
        })}
      </svg>

      {/* Tx particles streaming in */}
      {txParticles.map((p) => {
        const localT = (time - p.spawn) / p.travel;
        if (localT < -0.05 || localT > 1.15) return null;
        const t = clamp(localT, 0, 1);
        const eased = Easing.easeInCubic(t);
        const r = p.startRadius * (1 - eased);
        const px = HUB.x + Math.cos(p.angle) * r;
        const py = HUB.y + Math.sin(p.angle) * r;
        const opacity = t < 0.1
          ? t * 10
          : t > 0.85
            ? Math.max(0, 1 - (t - 0.85) * 6.5)
            : 1;
        const scale = 0.7 + 0.3 * (1 - t);
        return (
          <React.Fragment key={p.seed}>
            <TxParticle
              x={px} y={py}
              hash={p.hash}
              opacity={opacity * 0.85}
              scale={scale}
              color={t > 0.5 ? CTE.teal : CTE.textDim}
            />
            {t > 0.6 && (
              <EnergyPulse x={px} y={py} color={CTE.teal} size={4 + 4 * (1 - t)} glow={1 - t} />
            )}
          </React.Fragment>
        );
      })}

      {/* Logo at hub */}
      <LogoEngine
        x={HUB.x} y={HUB.y}
        size={320}
        nodeActivation={nodeActivation}
        hubPulse={hubPulse}
        intensity={logoIntensity}
      />

      {/* Ledger panel — emerges from the right at emission start */}
      <LedgerPanel
        x={ledgerX} y={ledgerY}
        width={ledgerW}
        rows={ledgerRows}
        time={time}
        emissionStart={emissionStart}
        rowStagger={rowStagger}
      />

      {/* Verified stamp at end */}
      <VerifiedStamp time={time} x={1500} y={920} />
    </>
  );
}

// Ledger panel — appears progressively from the right
function LedgerPanel({ x, y, width, rows, time, emissionStart, rowStagger }) {
  const panelOpacity = animate({ from: 0, to: 1, start: emissionStart - 0.4, end: emissionStart + 0.6, ease: Easing.easeOutCubic })(time)
                     * animate({ from: 1, to: 0, start: 11.2, end: 11.9 })(time);
  const panelTranslate = (1 - animate({ from: 0, to: 1, start: emissionStart - 0.4, end: emissionStart + 0.5 })(time)) * 40;

  return (
    <div style={{
      position: 'absolute',
      left: x, top: y,
      width,
      opacity: panelOpacity,
      transform: `translateX(${panelTranslate}px)`,
    }}>
      {/* Panel shell */}
      <div style={{
        position: 'relative',
        background: `${CTE.bg1}EE`,
        border: `1px solid ${CTE.teal}33`,
        borderRadius: 8,
        boxShadow: `0 30px 80px ${CTE.bg0}, 0 0 60px ${CTE.teal}15`,
        backdropFilter: 'blur(6px)',
        overflow: 'hidden',
      }}>
        {/* Panel header */}
        <div style={{
          padding: '14px 18px',
          borderBottom: `1px solid ${CTE.bg3}`,
          display: 'flex',
          alignItems: 'center',
          gap: 10,
          fontFamily: FONTS.mono,
          fontSize: 11,
          letterSpacing: '0.2em',
          color: CTE.textDim,
        }}>
          <span style={{
            width: 8, height: 8, borderRadius: 4,
            background: CTE.ok,
            boxShadow: `0 0 8px ${CTE.ok}`,
          }} />
          <span style={{ color: CTE.text }}>CLASSIFIED LEDGER</span>
          <span style={{ flex: 1 }} />
          <span style={{ color: CTE.textMuted }}>v2026.Q1</span>
        </div>

        {/* Column header */}
        <div style={{
          display: 'grid',
          gridTemplateColumns: '92px 90px 110px 110px 64px 1fr',
          gap: 10,
          padding: '10px 18px',
          fontFamily: FONTS.mono,
          fontSize: 10,
          letterSpacing: '0.18em',
          color: CTE.textMuted,
          background: CTE.bg2,
          borderBottom: `1px solid ${CTE.bg3}`,
        }}>
          <span>DATE</span>
          <span>ASSET</span>
          <span>AMOUNT</span>
          <span>TYPE</span>
          <span>CONF.</span>
          <span>TAX TAG</span>
        </div>

        {/* Rows */}
        <div>
          {rows.map((row, i) => {
            const rowStart = emissionStart + 0.3 + i * rowStagger;
            const rowEnd = rowStart + 0.5;
            const rowOpacity = animate({ from: 0, to: 1, start: rowStart, end: rowEnd, ease: Easing.easeOutCubic })(time);
            const rowTx = (1 - animate({ from: 0, to: 1, start: rowStart, end: rowEnd })(time)) * 24;
            const highlight = animate({ from: 1, to: 0, start: rowStart, end: rowStart + 1.4, ease: Easing.easeInOutCubic })(time);

            const typeColor = ({
              SWAP: CTE.swap, BRIDGE: CTE.bridge, STAKE: CTE.stake,
              AIRDROP: CTE.airdrop, FEE: CTE.fee, TRADE: CTE.swap,
              INCOME: CTE.teal, REWARD: CTE.airdrop,
            })[row.type] || CTE.teal;

            return (
              <div key={i} style={{
                display: 'grid',
                gridTemplateColumns: '92px 90px 110px 110px 64px 1fr',
                gap: 10,
                padding: '11px 18px',
                fontFamily: FONTS.mono,
                fontSize: 13,
                color: CTE.text,
                opacity: rowOpacity,
                transform: `translateX(${rowTx}px)`,
                background: highlight > 0
                  ? `linear-gradient(90deg, ${CTE.teal}${Math.round(highlight * 40).toString(16).padStart(2,'0')} 0%, transparent 60%)`
                  : 'transparent',
                borderBottom: i < rows.length - 1 ? `1px solid ${CTE.bg3}` : 'none',
              }}>
                <span style={{ color: CTE.textDim, fontVariantNumeric: 'tabular-nums' }}>{row.date}</span>
                <span style={{ fontWeight: 600 }}>{row.asset}</span>
                <span style={{ fontVariantNumeric: 'tabular-nums' }}>{row.amount}</span>
                <span>
                  <span style={{
                    color: typeColor,
                    background: `${typeColor}1F`,
                    border: `1px solid ${typeColor}55`,
                    borderRadius: 3,
                    padding: '3px 8px',
                    fontSize: 10,
                    letterSpacing: '0.14em',
                  }}>{row.type}</span>
                </span>
                <span style={{
                  color: row.confidence >= 95 ? CTE.ok : row.confidence >= 80 ? CTE.warn : CTE.err,
                  fontVariantNumeric: 'tabular-nums',
                }}>{row.confidence}%</span>
                <span style={{ color: CTE.textDim }}>{row.taxTag}</span>
              </div>
            );
          })}
        </div>
      </div>
    </div>
  );
}

// "Verified" stamp animates in toward the end
function VerifiedStamp({ time, x, y }) {
  const opacity = animate({ from: 0, to: 1, start: 9.4, end: 10.2, ease: Easing.easeOutBack })(time)
                * animate({ from: 1, to: 0, start: 11.3, end: 11.9 })(time);
  const scale = 0.85 + 0.15 * animate({ from: 0, to: 1, start: 9.4, end: 10.2, ease: Easing.easeOutBack })(time);

  return (
    <div style={{
      position: 'absolute',
      left: x, top: y,
      transform: `translate(-50%, -50%) scale(${scale})`,
      opacity,
      display: 'flex',
      alignItems: 'center',
      gap: 12,
      padding: '14px 20px',
      background: `${CTE.bg2}EE`,
      border: `1.5px solid ${CTE.teal}`,
      borderRadius: 8,
      boxShadow: `0 0 32px ${CTE.teal}55`,
      fontFamily: FONTS.mono,
      fontSize: 12,
      letterSpacing: '0.22em',
      color: CTE.teal,
    }}>
      <svg width="16" height="16" viewBox="0 0 16 16" fill="none">
        <path d="M3 8L7 12L13 4" stroke={CTE.teal} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
      </svg>
      VERIFIED · KOINLY-READY
    </div>
  );
}

function BottomStats({ time }) {
  const opacity = animate({ from: 0, to: 1, start: 0.6, end: 1.6 })(time)
                * animate({ from: 1, to: 0, start: 10.8, end: 11.8 })(time);

  // Animated counters
  const txCount = Math.floor(interpolate([0, 4, 8, 11], [0, 1247, 14228, 14228])(time));
  const protocols = Math.floor(interpolate([0, 5, 9, 11], [0, 12, 47, 47])(time));
  const accuracy = interpolate([0, 6, 9, 11], [0, 96.2, 99.4, 99.4])(time);

  const Stat = ({ label, value, suffix = '' }) => (
    <div>
      <div style={{
        fontFamily: FONTS.mono,
        fontSize: 11,
        letterSpacing: '0.22em',
        color: CTE.textMuted,
        marginBottom: 8,
      }}>{label}</div>
      <div style={{
        fontFamily: FONTS.display,
        fontSize: 38,
        fontWeight: 500,
        color: CTE.text,
        letterSpacing: '-0.02em',
        fontVariantNumeric: 'tabular-nums',
      }}>{value}{suffix && <span style={{ color: CTE.teal, fontSize: 24, marginLeft: 4 }}>{suffix}</span>}</div>
    </div>
  );

  return (
    <div style={{
      position: 'absolute',
      left: 80, bottom: 80,
      opacity,
      display: 'flex',
      gap: 64,
    }}>
      <Stat label="TRANSACTIONS PARSED" value={txCount.toLocaleString()} />
      <Stat label="PROTOCOLS DETECTED" value={protocols} />
      <Stat label="CLASSIFIER ACCURACY" value={accuracy.toFixed(1)} suffix="%" />
    </div>
  );
}

Object.assign(window, { ForensicEngine });
