// primitives.jsx — shared visual building blocks for all three directions.
// Depends on palette.jsx and animations.jsx already loaded.

// ── Background: subtle dot grid + vignette ──────────────────────────────────
function GridBackground({ color = CTE.bgGrid, spacing = 40, opacity = 1 }) {
  return (
    <div style={{
      position: 'absolute', inset: 0,
      background: `
        radial-gradient(ellipse at center, transparent 0%, ${CTE.bg0} 95%),
        radial-gradient(circle at 1px 1px, ${color} 1px, transparent 1px)
      `,
      backgroundSize: `100% 100%, ${spacing}px ${spacing}px`,
      opacity,
      pointerEvents: 'none',
    }} />
  );
}

// ── Soft glowing orb behind the logo, breathes with the timeline ───────────
function CenterGlow({ x, y, time, intensity = 1, size = 520 }) {
  const pulse = 0.7 + 0.3 * Math.sin(time * 1.5);
  return (
    <div style={{
      position: 'absolute',
      left: x - size / 2, top: y - size / 2,
      width: size, height: size,
      background: `radial-gradient(circle, ${CTE.teal}33 0%, ${CTE.cyan}22 30%, transparent 65%)`,
      filter: 'blur(20px)',
      opacity: intensity * pulse * 0.9,
      pointerEvents: 'none',
      mixBlendMode: 'screen',
    }} />
  );
}

// ── The CTE logo, rendered as inline SVG so we can animate its parts ───────
// It's the same molecular structure as the brand mark: a central hub with
// 7 satellite nodes connected by gradient lines.
//
// Props let scenes drive per-node activation, hub pulse, full glow, etc.
//
// We render at a "natural" 200×200 viewBox and the caller sets size+pos.
function LogoEngine({
  x, y, size = 280,
  // 0..1 per node — controls glow / scale / activation
  nodeActivation = [1, 1, 1, 1, 1, 1, 1],
  hubPulse = 1,
  rotate = 0,
  // 0..1 — controls the master "energizing" glow
  intensity = 1,
}) {
  // Logo geometry — read off the actual logo image, normalized to 200×200.
  // Hub at (100, 105) with radius ~30. Then 7 satellites at varying r/theta.
  // Colors approximate the gradient stops from the brand mark.
  const HUB = { cx: 100, cy: 105, r: 30 };
  // 7 satellites — matches the real CTE mark exactly. Read clockwise from top.
  const NODES = [
    // Top — large mint
    { cx: 100, cy: 22,  r: 18, color: CTE.teal,  angle: -90 },
    // Upper-right — medium cyan
    { cx: 168, cy: 70,  r: 15, color: CTE.cyan,  angle: -40 },
    // Far right — small cyan, long line
    { cx: 198, cy: 122, r: 7,  color: CTE.cyan,  angle: 5 },
    // Lower-right — large azure-blue (the "anchor" node)
    { cx: 152, cy: 185, r: 19, color: CTE.azure, angle: 50 },
    // Lower-mid small — short line down from hub
    { cx: 96,  cy: 158, r: 6,  color: CTE.teal,  angle: 95 },
    // Lower-left — medium teal, long line
    { cx: 22,  cy: 145, r: 13, color: CTE.teal,  angle: 155 },
    // Upper-left — small teal, close to hub
    { cx: 50,  cy: 65,  r: 9,  color: CTE.teal,  angle: -150 },
  ];

  return (
    <div style={{
      position: 'absolute',
      left: x - size / 2, top: y - size / 2,
      width: size, height: size,
      transform: `rotate(${rotate}deg)`,
      transformOrigin: 'center',
      willChange: 'transform',
    }}>
      <svg viewBox="0 0 200 200" width={size} height={size} style={{ overflow: 'visible' }}>
        <defs>
          <linearGradient id="cte-grad" x1="0" y1="0" x2="1" y2="1">
            <stop offset="0%"  stopColor={CTE.teal} />
            <stop offset="50%" stopColor={CTE.cyan} />
            <stop offset="100%" stopColor={CTE.azure} />
          </linearGradient>
          {/* Line-specific gradient anchored in user space so it resolves
              correctly on perfectly-vertical lines (200×200 viewBox extent). */}
          <linearGradient id="cte-grad-line" gradientUnits="userSpaceOnUse" x1="0" y1="0" x2="200" y2="200">
            <stop offset="0%"  stopColor={CTE.teal} />
            <stop offset="50%" stopColor={CTE.cyan} />
            <stop offset="100%" stopColor={CTE.azure} />
          </linearGradient>
          <radialGradient id="cte-hub-grad" cx="0.5" cy="0.45" r="0.6">
            <stop offset="0%"  stopColor={CTE.ice} stopOpacity="0.95" />
            <stop offset="40%" stopColor={CTE.teal} />
            <stop offset="100%" stopColor={CTE.azure} />
          </radialGradient>
          <filter id="cte-glow" x="-50%" y="-50%" width="200%" height="200%">
            <feGaussianBlur stdDeviation="4" result="blur"/>
            <feMerge>
              <feMergeNode in="blur"/>
              <feMergeNode in="SourceGraphic"/>
            </feMerge>
          </filter>
        </defs>

        {/* Connecting lines — drawn first so they sit under the nodes.
            Use gradientUnits=userSpaceOnUse so the gradient resolves consistently
            even on perfectly-vertical lines (which would otherwise have zero
            x-extent and render as a single-color sample). */}
        {NODES.map((n, i) => {
          const act = nodeActivation[i] ?? 1;
          return (
            <line
              key={`l${i}`}
              x1={HUB.cx} y1={HUB.cy}
              x2={n.cx} y2={n.cy}
              stroke="url(#cte-grad-line)"
              strokeWidth={4 + act * 1.0}
              strokeLinecap="round"
              opacity={0.95}
            />
          );
        })}

        {/* Satellite nodes */}
        {NODES.map((n, i) => {
          const act = nodeActivation[i] ?? 1;
          const r = n.r * (0.9 + 0.18 * act);
          return (
            <g key={`n${i}`} filter={act > 0.6 ? 'url(#cte-glow)' : undefined}>
              <circle
                cx={n.cx} cy={n.cy} r={r}
                fill={n.color}
                opacity={0.95}
              />
              {/* inner highlight */}
              <circle
                cx={n.cx - r * 0.25} cy={n.cy - r * 0.3} r={r * 0.4}
                fill={CTE.ice}
                opacity={0.18 * act}
              />
            </g>
          );
        })}

        {/* Hub */}
        <g filter="url(#cte-glow)">
          <circle
            cx={HUB.cx} cy={HUB.cy}
            r={HUB.r * (0.95 + 0.08 * hubPulse)}
            fill="url(#cte-hub-grad)"
            opacity={0.9 + 0.1 * hubPulse}
          />
          <circle
            cx={HUB.cx - 6} cy={HUB.cy - 8} r={HUB.r * 0.4}
            fill={CTE.ice}
            opacity={0.25 * hubPulse}
          />
        </g>
      </svg>
    </div>
  );
}

// ── A small "monitor chip" — the boxed labels from the existing CTE site ───
function ClassifierChip({ x, y, label, active = 0, status = 'idle', width = 200 }) {
  const borderCol = active > 0.5 ? CTE.teal : 'rgba(143, 240, 220, 0.25)';
  const bg = active > 0.5
    ? `linear-gradient(180deg, ${CTE.bg3} 0%, ${CTE.bg2} 100%)`
    : CTE.bg2;
  const dot = status === 'ok' ? CTE.ok : status === 'warn' ? CTE.warn : status === 'err' ? CTE.err : CTE.textMuted;

  return (
    <div style={{
      position: 'absolute',
      left: x - width / 2, top: y - 24,
      width, height: 48,
      background: bg,
      border: `1.5px solid ${borderCol}`,
      borderRadius: 6,
      padding: '0 14px',
      display: 'flex', alignItems: 'center', gap: 10,
      fontFamily: FONTS.mono,
      fontSize: 11,
      letterSpacing: '0.12em',
      color: active > 0.5 ? CTE.text : CTE.textDim,
      boxShadow: active > 0.5
        ? `0 0 24px ${CTE.teal}33, inset 0 0 0 1px ${CTE.teal}22`
        : 'none',
      transition: 'box-shadow 200ms, border-color 200ms',
    }}>
      <span style={{
        width: 6, height: 6, borderRadius: 3,
        background: dot,
        boxShadow: status !== 'idle' ? `0 0 8px ${dot}` : 'none',
      }} />
      <span style={{ flex: 1 }}>{label}</span>
    </div>
  );
}

// ── A raw transaction row (chaotic, unlabeled) ─────────────────────────────
// Looks like a hex hash + protocol address + raw method id.
function RawTxRow({
  x, y, width = 380,
  hash, fromAddr, methodId,
  opacity = 1,
}) {
  return (
    <div style={{
      position: 'absolute',
      left: x, top: y,
      width,
      opacity,
      fontFamily: FONTS.mono,
      fontSize: 12,
      color: CTE.textDim,
      letterSpacing: '0.02em',
      whiteSpace: 'nowrap',
      overflow: 'hidden',
      textOverflow: 'ellipsis',
    }}>
      <span style={{ color: CTE.textMuted }}>tx</span>{' '}
      <span style={{ color: CTE.text }}>{hash}</span>{' '}
      <span style={{ color: CTE.textMuted }}>→</span>{' '}
      <span>{fromAddr}</span>{' '}
      <span style={{ color: CTE.warn }}>{methodId}</span>
    </div>
  );
}

// ── A clean, classified ledger row — the "after" state ─────────────────────
function ClassifiedRow({
  x, y, width = 520,
  date, asset, amount, type, confidence, taxTag,
  opacity = 1,
  highlight = 0,
}) {
  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,
  }[type] || CTE.teal;

  return (
    <div style={{
      position: 'absolute',
      left: x, top: y,
      width,
      height: 36,
      opacity,
      display: 'grid',
      gridTemplateColumns: '78px 96px 110px 92px 64px 1fr',
      alignItems: 'center',
      gap: 10,
      padding: '0 14px',
      fontFamily: FONTS.mono,
      fontSize: 12,
      color: CTE.text,
      background: highlight > 0
        ? `linear-gradient(90deg, ${CTE.teal}${Math.round(highlight * 30).toString(16).padStart(2,'0')} 0%, transparent 100%)`
        : 'transparent',
      borderBottom: `1px solid ${CTE.bg3}`,
      letterSpacing: '0.02em',
    }}>
      <span style={{ color: CTE.textDim }}>{date}</span>
      <span style={{ color: CTE.text, fontWeight: 600 }}>{asset}</span>
      <span style={{ color: CTE.text, fontVariantNumeric: 'tabular-nums' }}>{amount}</span>
      <span style={{
        color: typeColor,
        background: `${typeColor}1A`,
        border: `1px solid ${typeColor}40`,
        borderRadius: 3,
        padding: '2px 6px',
        fontSize: 10,
        letterSpacing: '0.1em',
        textAlign: 'center',
      }}>{type}</span>
      <span style={{
        color: confidence >= 95 ? CTE.ok : confidence >= 80 ? CTE.warn : CTE.err,
        fontVariantNumeric: 'tabular-nums',
      }}>{confidence}%</span>
      <span style={{ color: CTE.textDim }}>{taxTag}</span>
    </div>
  );
}

// ── A header for a ledger panel ────────────────────────────────────────────
function LedgerHeader({ x, y, width = 520, label = 'CLASSIFIED LEDGER' }) {
  return (
    <div style={{
      position: 'absolute',
      left: x, top: y,
      width,
      height: 32,
      display: 'grid',
      gridTemplateColumns: '78px 96px 110px 92px 64px 1fr',
      alignItems: 'center',
      gap: 10,
      padding: '0 14px',
      fontFamily: FONTS.mono,
      fontSize: 9.5,
      color: CTE.textMuted,
      letterSpacing: '0.18em',
      borderBottom: `1px solid ${CTE.teal}40`,
      background: CTE.bg2,
    }}>
      <span>DATE</span>
      <span>ASSET</span>
      <span>AMOUNT</span>
      <span>TYPE</span>
      <span>CONF.</span>
      <span>{label}</span>
    </div>
  );
}

// ── Floating tx hash particle — used in chaos shots ────────────────────────
function TxParticle({ x, y, hash, opacity = 1, scale = 1, color = CTE.textDim }) {
  return (
    <div style={{
      position: 'absolute',
      left: x, top: y,
      transform: `scale(${scale}) translate(-50%, -50%)`,
      opacity,
      fontFamily: FONTS.mono,
      fontSize: 11,
      color,
      whiteSpace: 'nowrap',
      letterSpacing: '0.04em',
      pointerEvents: 'none',
      textShadow: `0 0 8px ${CTE.bg0}`,
    }}>
      {hash}
    </div>
  );
}

// ── Pulsing energy dot traveling along a path ──────────────────────────────
// Used to show transactions flowing into the hub or out to the ledger.
function EnergyPulse({ x, y, color = CTE.teal, size = 6, glow = 1 }) {
  return (
    <div style={{
      position: 'absolute',
      left: x - size / 2, top: y - size / 2,
      width: size, height: size,
      borderRadius: size / 2,
      background: color,
      boxShadow: `0 0 ${12 * glow}px ${color}, 0 0 ${24 * glow}px ${color}80`,
      pointerEvents: 'none',
    }} />
  );
}

// ── Generate deterministic-looking hex strings ─────────────────────────────
function makeHash(seed, len = 10) {
  // Simple LCG so seeds give stable strings across renders.
  let s = (seed * 9301 + 49297) % 233280;
  const chars = '0123456789abcdef';
  let out = '0x';
  for (let i = 0; i < len; i++) {
    s = (s * 9301 + 49297) % 233280;
    out += chars[s % 16];
  }
  return out;
}

const ASSETS = ['ETH', 'WBTC', 'USDC', 'ARB', 'OP', 'LINK', 'UNI', 'AAVE', 'stETH', 'MATIC', 'DAI'];
const TYPES = ['SWAP', 'BRIDGE', 'STAKE', 'AIRDROP', 'FEE', 'INCOME', 'REWARD'];
const TAX_TAGS = ['Sched D', 'Form 8949', 'Ord. income', 'Self-empl.', 'Cap. gain (LT)', 'Cap. gain (ST)', 'Cost basis'];

function pickFromSeed(arr, seed) {
  return arr[Math.abs(seed * 2654435761 % arr.length)];
}

Object.assign(window, {
  GridBackground, CenterGlow, LogoEngine,
  ClassifierChip, RawTxRow, ClassifiedRow, LedgerHeader,
  TxParticle, EnergyPulse,
  makeHash, ASSETS, TYPES, TAX_TAGS, pickFromSeed,
});
