// reconciliation.jsx — Direction 3: "The Reconciliation"
//
// 10s loop. Single dramatic beat: chaos → snap to order.
//
// Beats:
// 0.0 - 2.0s   Chaos: 60+ raw tx hashes scattered across the canvas, drifting
// 2.0 - 3.5s   Logo "wakes up" at center, glow expands
// 3.5 - 5.5s   The hashes are pulled toward the hub (centripetal), tightening
// 5.5 - 7.0s   Snap! They burst out the right side as a clean sorted ledger
// 7.0 - 9.5s   Hold on the clean state, gentle pulse
// 9.5 - 10s    Soft fade for loop

function Reconciliation({ chromeless = false }) {
  const time = useTime();
  const W = 1920, H = 1080;
  // Hub centered between hero copy column (right edge ≈ x=840) and viewport right edge (1920),
  // and lifted slightly above vertical-center so the ledger reveal sits in the optical center.
  const HUB = { x: 1420, y: 480 };

  // Generate scattered tx particles. Each has a starting (chaos) position,
  // drifts gently, gets sucked into hub, then re-emerges as a row.
  const PARTICLES = React.useMemo(() => {
    return Array.from({ length: 64 }, (_, i) => {
      // Pseudo-random scatter across the right ~⅔ of the canvas (where the hub now lives).
      const seed = i * 17 + 3;
      const r1 = (seed * 9301 + 49297) % 233280 / 233280;
      const r2 = (r1 * 9301 + 49297) % 1;
      const r3 = ((r2 * 100) * 9301 + 49297) % 1;

      const xRange = [720, 1880];
      const yRange = [120, 960];
      const startX = xRange[0] + r1 * (xRange[1] - xRange[0]);
      const startY = yRange[0] + r2 * (yRange[1] - yRange[0]);

      return {
        seed: i,
        startX, startY,
        driftAngle: r3 * Math.PI * 2,
        hash: makeHash(i * 41 + 7, 10 + (i % 4)),
        delay: r1 * 0.8,
      };
    });
  }, []);

  // Rows that emerge after the snap
  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' },
    { date: '04/05/26', asset: 'UNI',   amount: '64.20',    type: 'STAKE',   confidence: 98, taxTag: 'Cost basis' },
  ];

  const SNAP = 5.5; // moment when chaos resolves
  const SUCK_START = 3.3;
  const SUCK_END = 5.4;

  // Logo intensity arc — emit center-glow flash at SNAP, then HARD fade off so the
  // ledger fully replaces the logo footprint during the 5.5–9.5s payoff window.
  const logoIntensity = interpolate(
    [0, 2, 3.5, 5.5, 5.9, 6.3, 9.5, 10],
    [0.2, 0.45, 0.85, 1.0, 0.4, 0.0, 0.0, 0.2],
    Easing.easeInOutCubic
  )(time);
  const hubPulse = interpolate(
    [0, 2, 3.5, 5.5, 5.7, 7, 10],
    [0.2, 0.5, 0.85, 1.0, 1.4, 0.8, 0.3],
    Easing.easeOutCubic
  )(time);
  const nodeActivation = Array.from({ length: 7 }, (_, i) =>
    interpolate(
      [0, 2 + i * 0.1, 4 + i * 0.05, 5.5, 7, 10],
      [0.2, 0.4, 0.85, 1, 0.85, 0.4],
      Easing.easeInOutCubic
    )(time)
  );

  // Headline copy
  const introOpacity = animate({ from: 0, to: 1, start: 0.2, end: 1.2 })(time)
                     * animate({ from: 1, to: 0, start: 4.5, end: 5.4 })(time);
  const outroOpacity = animate({ from: 0, to: 1, start: 6.0, end: 6.8 })(time)
                     * animate({ from: 1, to: 0, start: 9.4, end: 9.9 })(time);

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

      {/* Intro headline (chaos phase) */}
      {!chromeless && (
      <div style={{
        position: 'absolute',
        right: 100, top: 120,
        textAlign: 'right',
        opacity: introOpacity,
      }}>
        <div style={{
          fontFamily: FONTS.mono,
          fontSize: 13,
          letterSpacing: '0.28em',
          color: CTE.warn,
          marginBottom: 18,
        }}>
          ◆ &nbsp; 14,228 UNCLASSIFIED TRANSACTIONS
        </div>
        <div style={{
          fontFamily: FONTS.display,
          fontSize: 60,
          fontWeight: 600,
          color: CTE.text,
          letterSpacing: '-0.025em',
          lineHeight: 1.05,
        }}>
          A year of crypto<br/>activity.<br/>
          <span style={{ color: CTE.warn }}>Untagged.</span>
        </div>
      </div>
      )}

      {/* Outro headline (resolved phase) */}
      {!chromeless && (
      <div style={{
        position: 'absolute',
        right: 100, top: 120,
        textAlign: 'right',
        opacity: outroOpacity,
      }}>
        <div style={{
          fontFamily: FONTS.mono,
          fontSize: 13,
          letterSpacing: '0.28em',
          color: CTE.teal,
          marginBottom: 18,
        }}>
          ◆ &nbsp; 99.4% CONFIDENCE · KOINLY-READY
        </div>
        <div style={{
          fontFamily: FONTS.display,
          fontSize: 60,
          fontWeight: 600,
          color: CTE.text,
          letterSpacing: '-0.025em',
          lineHeight: 1.05,
        }}>
          Same year.<br/>
          <span style={{ color: CTE.teal }}>Classified.</span><br/>
          Filing-ready.
        </div>
      </div>
      )}

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

      {/* Particles — chaos → suck → resolved */}
      {PARTICLES.map((p) => {
        const driftT = time + p.delay;
        // Gentle drift in chaos phase
        const driftX = Math.cos(p.driftAngle + driftT * 0.6) * 22;
        const driftY = Math.sin(p.driftAngle * 1.3 + driftT * 0.4) * 18;

        // Suck phase — particle accelerates toward hub
        const suckT = clamp((time - SUCK_START - p.delay * 0.4) / (SUCK_END - SUCK_START), 0, 1);
        const eased = Easing.easeInQuart(suckT);

        let px = p.startX + driftX;
        let py = p.startY + driftY;
        if (suckT > 0) {
          px = p.startX + driftX + (HUB.x - p.startX - driftX) * eased;
          py = p.startY + driftY + (HUB.y - p.startY - driftY) * eased;
        }

        // Visibility: fade out as we hit hub
        let opacity;
        if (time < 0.4) {
          opacity = animate({ from: 0, to: 0.6, start: 0, end: 0.6 + p.delay })(time);
        } else if (time < SUCK_START) {
          opacity = 0.55 + 0.15 * Math.sin(driftT * 2 + p.seed);
        } else {
          opacity = 0.6 * (1 - Math.pow(suckT, 2.5));
        }

        if (time > SNAP) opacity = 0;

        const scale = 1 - 0.4 * suckT;
        const color = suckT > 0.5 ? CTE.teal : suckT > 0.2 ? CTE.cyan : CTE.textDim;

        return (
          <TxParticle
            key={p.seed}
            x={px} y={py}
            hash={p.hash}
            opacity={opacity}
            scale={scale}
            color={color}
          />
        );
      })}

      {/* Snap flash at SNAP */}
      <SnapFlash time={time} hubX={HUB.x} hubY={HUB.y} snapAt={SNAP} />

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

      {/* Resolved ledger emerges from hub after snap */}
      <ResolvedLedger time={time} rows={ROWS} snapAt={SNAP} hubX={HUB.x} hubY={HUB.y} />
    </>
  );
}

function SnapFlash({ time, hubX, hubY, snapAt }) {
  const t = time - snapAt;
  if (t < -0.05 || t > 0.6) return null;
  const ring = clamp(t / 0.6, 0, 1);
  const radius = ring * 900;
  const opacity = ring < 0.05 ? 0 : (1 - ring) * 0.85;

  // Central white flash
  const flashOpacity = t < 0.18 ? Math.max(0, 1 - t / 0.18) * 0.85 : 0;

  return (
    <>
      {flashOpacity > 0 && (
        <div style={{
          position: 'absolute',
          left: hubX - 240, top: hubY - 240,
          width: 480, height: 480,
          borderRadius: 240,
          background: `radial-gradient(circle, ${CTE.ice} 0%, ${CTE.teal}88 40%, transparent 70%)`,
          opacity: flashOpacity,
          mixBlendMode: 'screen',
          pointerEvents: 'none',
        }} />
      )}
      <div style={{
        position: 'absolute',
        left: hubX - radius, top: hubY - radius,
        width: radius * 2, height: radius * 2,
        borderRadius: radius,
        border: `2px solid ${CTE.teal}`,
        opacity,
        boxShadow: `0 0 40px ${CTE.teal}AA`,
        pointerEvents: 'none',
      }} />
    </>
  );
}

function ResolvedLedger({ time, rows, snapAt, hubX, hubY }) {
  const width = 680;
  const headerH = 44;
  const filterH = 34;
  const rowH = 41;
  const totalH = headerH + filterH + rows.length * rowH;
  // Ledger right-aligned to the canvas with extra breathing room from the headline copy
  // column at narrower viewports. Vertically centered on the hub.
  const x = 1860 - width;  // → x=1180, right edge at 1860
  const y = hubY - totalH / 2;

  const panelOpacity = animate({ from: 0, to: 1, start: snapAt, end: snapAt + 0.8, ease: Easing.easeOutCubic })(time)
                     * animate({ from: 1, to: 0, start: 9.5, end: 9.95 })(time);
  const panelTranslate = (1 - animate({ from: 0, to: 1, start: snapAt, end: snapAt + 0.7, ease: Easing.easeOutBack })(time)) * 60;

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

  return (
    <div style={{
      position: 'absolute',
      left: x, top: y,
      width,
      opacity: panelOpacity,
      transform: `translateX(${panelTranslate}px)`,
    }}>
      <div style={{
        background: `${CTE.bg1}F2`,
        border: `1px solid ${CTE.teal}55`,
        borderRadius: 8,
        boxShadow: `0 30px 80px ${CTE.bg0}, 0 0 80px ${CTE.teal}22`,
        backdropFilter: 'blur(8px)',
        overflow: 'hidden',
      }}>
        <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.text,
        }}>
          <span style={{
            width: 8, height: 8, borderRadius: 4,
            background: CTE.ok,
            boxShadow: `0 0 8px ${CTE.ok}`,
          }} />
          CLASSIFIED LEDGER
          <span style={{ flex: 1 }} />
          <span style={{ color: CTE.textMuted }}>9 of 14,228 shown</span>
        </div>

        <div style={{
          display: 'grid',
          gridTemplateColumns: '88px 64px 92px 92px 56px 1fr',
          gap: 10, padding: '10px 16px',
          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>

        <div>
          {rows.map((row, i) => {
            const rowStart = snapAt + 0.3 + i * 0.08;
            const rowOpacity = animate({ from: 0, to: 1, start: rowStart, end: rowStart + 0.4 })(time);
            const rowTx = (1 - rowOpacity) * 16;
            const highlight = animate({ from: 1, to: 0, start: rowStart, end: rowStart + 1.0 })(time);
            const tc = typeColor(row.type);

            return (
              <div key={i} style={{
                display: 'grid',
                gridTemplateColumns: '88px 64px 92px 92px 56px 1fr',
                gap: 10, padding: '11px 16px',
                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 * 50).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: tc, background: `${tc}1F`, border: `1px solid ${tc}55`,
                    borderRadius: 3, padding: '3px 8px',
                    fontSize: 10, letterSpacing: '0.14em',
                  }}>{row.type}</span>
                </span>
                <span style={{
                  color: row.confidence >= 95 ? CTE.ok : CTE.warn,
                  fontVariantNumeric: 'tabular-nums',
                }}>{row.confidence}%</span>
                <span style={{ color: CTE.textDim }}>{row.taxTag}</span>
              </div>
            );
          })}
        </div>
      </div>
    </div>
  );
}

Object.assign(window, { Reconciliation });
