// Hero — Quantization Neural Network animation
// Shows a large DNN with slow pulses → quantization event → smaller DNN with fast pulses
// Same output emerges from both sides

const HeroGlyph = ({ accent = 'gold', style }) => {
  const t = window.ATTO_TOKENS;
  const accentColor = accent === 'gold' ? t.gold : accent === 'blue' ? t.blue : t.ink;
  const glowColor = accent === 'gold' ? t.goldGlow : accent === 'blue' ? '#6e8fc0' : '#333';

  // Phase state: 'large' | 'compress' | 'small'
  const [phase, setPhase] = React.useState('large');
  const [cycle, setCycle] = React.useState(0);

  React.useEffect(() => {
    // Cycle: large (3.5s) → compress (1.2s) → small (3.5s) → reset
    const tick = () => {
      setPhase('large');
      setTimeout(() => setPhase('compress'), 3500);
      setTimeout(() => setPhase('small'), 4700);
      setTimeout(() => setCycle(c => c + 1), 8500);
    };
    tick();
    const id = setInterval(tick, 8500);
    return () => clearInterval(id);
  }, []);

  // Large network: 4 layers (6, 8, 8, 6)
  const largeLayers = [
    { x: 90,  nodes: [80, 135, 190, 245, 300, 355] },
    { x: 200, nodes: [60, 108, 156, 204, 252, 300, 348, 396] },
    { x: 310, nodes: [60, 108, 156, 204, 252, 300, 348, 396] },
    { x: 420, nodes: [80, 135, 190, 245, 300, 355] },
  ];
  // Small network: 4 layers (3, 4, 4, 3) — stays roughly centered
  const smallLayers = [
    { x: 130, nodes: [170, 227, 284] },
    { x: 220, nodes: [150, 207, 264, 321] },
    { x: 310, nodes: [150, 207, 264, 321] },
    { x: 400, nodes: [170, 227, 284] },
  ];

  // Connections helpers
  const makeEdges = (layers) => {
    const edges = [];
    for (let i = 0; i < layers.length - 1; i++) {
      for (const y1 of layers[i].nodes) {
        for (const y2 of layers[i + 1].nodes) {
          edges.push({ x1: layers[i].x, y1, x2: layers[i + 1].x, y2 });
        }
      }
    }
    return edges;
  };

  const largeEdges = React.useMemo(() => makeEdges(largeLayers), []);
  const smallEdges = React.useMemo(() => makeEdges(smallLayers), []);

  const isLarge = phase === 'large';
  const isSmall = phase === 'small';
  const isCompress = phase === 'compress';

  // Pulse speeds
  const largePulseDur = 3.2; // slow
  const smallPulseDur = 0.9; // fast

  return (
    <div style={{ position: 'relative', width: '100%', ...style }}>
      <svg viewBox="0 0 560 460" style={{ width: '100%', height: 'auto', display: 'block' }}>
        <defs>
          <radialGradient id="heroHalo" cx="0.5" cy="0.5" r="0.5">
            <stop offset="0%" stopColor={glowColor} stopOpacity="0.5" />
            <stop offset="60%" stopColor={accentColor} stopOpacity="0.12" />
            <stop offset="100%" stopColor={accentColor} stopOpacity="0" />
          </radialGradient>
          <linearGradient id="wireGradSlow" x1="0" x2="1">
            <stop offset="0%" stopColor={t.ink} stopOpacity="0.1" />
            <stop offset="50%" stopColor={accentColor} stopOpacity="0.7" />
            <stop offset="100%" stopColor={t.ink} stopOpacity="0.1" />
          </linearGradient>
        </defs>

        {/* Soft halo */}
        <ellipse cx="280" cy="230" rx="260" ry="200" fill="url(#heroHalo)" opacity={isSmall ? 1 : 0.6}
          style={{ transition: 'opacity 1.2s' }} />

        {/* Input/output labels */}
        <text x="40" y="40" fontFamily="var(--atto-mono)" fontSize="13"
          fill={t.fadedText} letterSpacing="0.1em">PROMPT →</text>
        <text x="520" y="40" fontFamily="var(--atto-mono)" fontSize="13"
          fill={t.fadedText} letterSpacing="0.1em" textAnchor="end">→ OUTPUT</text>

        {/* Param counter — morphs */}
        <text x="280" y="40" fontFamily="var(--atto-mono)" fontSize="14"
          fill={accentColor} fontWeight="600" textAnchor="middle" letterSpacing="0.05em">
          {isLarge ? '70B · FP16 · 3.2 tok/s' : isCompress ? 'QUANTIZING…' : '3.8B · INT4 · 112 tok/s'}
        </text>

        {/* ================ LARGE NETWORK ================ */}
        <g opacity={isLarge ? 1 : isCompress ? 0.35 : 0}
          style={{ transition: 'opacity 800ms' }}>
          {/* Edges */}
          {largeEdges.map((e, i) => (
            <line key={`le${i}`} x1={e.x1} y1={e.y1} x2={e.x2} y2={e.y2}
              stroke={t.ink} strokeWidth="0.4" opacity="0.18" />
          ))}
          {/* Nodes */}
          {largeLayers.map((layer, li) => layer.nodes.map((y, ni) => (
            <circle key={`ln${li}-${ni}`} cx={layer.x} cy={y} r="4.2"
              fill={t.ivory} stroke={t.ink} strokeWidth="1" />
          )))}
          {/* Pulse particles — SLOW */}
          {isLarge && largeLayers.slice(0, -1).map((layer, li) => (
            layer.nodes.map((y1, ni) => {
              // One moving pulse per source node, traveling to a random target in next layer
              const targets = largeLayers[li + 1].nodes;
              const y2 = targets[(ni + li * 2) % targets.length];
              return (
                <circle key={`lp${cycle}-${li}-${ni}`} r="2.2" fill={accentColor} opacity="0.9">
                  <animate attributeName="cx" from={layer.x} to={largeLayers[li + 1].x}
                    dur={`${largePulseDur}s`} begin={`${li * largePulseDur / 4}s`}
                    repeatCount="1" fill="freeze" />
                  <animate attributeName="cy" from={y1} to={y2}
                    dur={`${largePulseDur}s`} begin={`${li * largePulseDur / 4}s`}
                    repeatCount="1" fill="freeze" />
                  <animate attributeName="opacity" values="0;0.9;0.9;0"
                    dur={`${largePulseDur}s`} begin={`${li * largePulseDur / 4}s`}
                    repeatCount="1" fill="freeze" />
                </circle>
              );
            })
          ))}
        </g>

        {/* ================ COMPRESSION SHOCKWAVE ================ */}
        {isCompress && (
          <g>
            <circle cx="280" cy="230" r="40" fill="none" stroke={accentColor} strokeWidth="1.5">
              <animate attributeName="r" from="40" to="260" dur="1s" fill="freeze" />
              <animate attributeName="opacity" values="1;0" dur="1s" fill="freeze" />
              <animate attributeName="stroke-width" values="2;0.3" dur="1s" fill="freeze" />
            </circle>
            <circle cx="280" cy="230" r="20" fill={glowColor} opacity="0.4">
              <animate attributeName="r" values="20;80;20" dur="1s" fill="freeze" />
              <animate attributeName="opacity" values="0.5;0.1;0" dur="1s" fill="freeze" />
            </circle>
            <text x="280" y="234" fontFamily="var(--atto-mono)" fontSize="10"
              fill={t.ink} fontWeight="600" textAnchor="middle" letterSpacing="0.1em">
              INT4
              <animate attributeName="opacity" values="0;1;1;0" dur="1s" fill="freeze" />
            </text>
          </g>
        )}

        {/* ================ SMALL NETWORK ================ */}
        <g opacity={isSmall ? 1 : 0}
          style={{ transition: 'opacity 800ms' }}>
          {/* Edges — thicker & more confident */}
          {smallEdges.map((e, i) => (
            <line key={`se${i}`} x1={e.x1} y1={e.y1} x2={e.x2} y2={e.y2}
              stroke={t.ink} strokeWidth="0.8" opacity="0.3" />
          ))}
          {smallLayers.map((layer, li) => layer.nodes.map((y, ni) => (
            <g key={`sn${li}-${ni}`}>
              <circle cx={layer.x} cy={y} r="8"
                fill={t.ivory} stroke={accentColor} strokeWidth="1.5" />
              <circle cx={layer.x} cy={y} r="3" fill={accentColor}>
                <animate attributeName="opacity" values="0.5;1;0.5"
                  dur={`${0.6 + ni * 0.1}s`} repeatCount="indefinite" />
              </circle>
            </g>
          )))}
          {/* Pulse particles — FAST, multiple in flight */}
          {isSmall && [0, 1, 2].map(wave => (
            smallLayers.slice(0, -1).map((layer, li) => (
              layer.nodes.map((y1, ni) => {
                const targets = smallLayers[li + 1].nodes;
                const y2 = targets[(ni + wave) % targets.length];
                return (
                  <circle key={`sp${cycle}-${wave}-${li}-${ni}`} r="2.6"
                    fill={glowColor} opacity="0.95">
                    <animate attributeName="cx" from={layer.x} to={smallLayers[li + 1].x}
                      dur={`${smallPulseDur}s`}
                      begin={`${li * smallPulseDur / 3 + wave * smallPulseDur}s`}
                      repeatCount="indefinite" />
                    <animate attributeName="cy" from={y1} to={y2}
                      dur={`${smallPulseDur}s`}
                      begin={`${li * smallPulseDur / 3 + wave * smallPulseDur}s`}
                      repeatCount="indefinite" />
                    <animate attributeName="opacity" values="0;1;1;0"
                      dur={`${smallPulseDur}s`}
                      begin={`${li * smallPulseDur / 3 + wave * smallPulseDur}s`}
                      repeatCount="indefinite" />
                  </circle>
                );
              })
            ))
          ))}
        </g>

        {/* Input / Output tokens — visible always, showing same output */}
        <g>
          <circle cx="40" cy="230" r="6" fill={t.ink} />
          <circle cx="40" cy="230" r="14" fill="none" stroke={t.ink} strokeWidth="0.6" opacity="0.3">
            <animate attributeName="r" values="8;18;8" dur="2.2s" repeatCount="indefinite" />
            <animate attributeName="opacity" values="0.5;0;0.5" dur="2.2s" repeatCount="indefinite" />
          </circle>
          <circle cx="520" cy="230" r="6" fill={accentColor} />
          <circle cx="520" cy="230" r="14" fill="none" stroke={accentColor} strokeWidth="0.8">
            <animate attributeName="r" values="8;18;8" dur={isSmall ? '0.9s' : '2.2s'} repeatCount="indefinite" />
            <animate attributeName="opacity" values="0.7;0;0.7" dur={isSmall ? '0.9s' : '2.2s'} repeatCount="indefinite" />
          </circle>
          <text x="40" y="260" fontFamily="var(--atto-mono)" fontSize="9"
            fill={t.fadedText} textAnchor="middle" letterSpacing="0.08em">INPUT</text>
          <text x="520" y="260" fontFamily="var(--atto-mono)" fontSize="9"
            fill={t.fadedText} textAnchor="middle" letterSpacing="0.08em">
            {isSmall ? 'SAME OUTPUT · 35× FASTER' : 'OUTPUT'}
          </text>
        </g>

        {/* Phase progress rail */}
        <g transform="translate(40, 410)">
          <line x1="0" y1="0" x2="480" y2="0" stroke={t.rule} strokeWidth="1" />
          <line x1="0" y1="0" x2={isLarge ? 160 : isCompress ? 240 : 480} y2="0"
            stroke={accentColor} strokeWidth="2"
            style={{ transition: 'all 1s cubic-bezier(.6,.2,.2,1)' }} />
          <text x="0" y="-10" fontFamily="var(--atto-mono)" fontSize="9"
            fill={isLarge ? accentColor : t.fadedText} letterSpacing="0.08em"
            fontWeight={isLarge ? 600 : 400}>
            LARGE · SLOW
          </text>
          <text x="240" y="-10" fontFamily="var(--atto-mono)" fontSize="9"
            fill={isCompress ? accentColor : t.fadedText} textAnchor="middle"
            letterSpacing="0.08em" fontWeight={isCompress ? 600 : 400}>
            QUANTIZE
          </text>
          <text x="480" y="-10" fontFamily="var(--atto-mono)" fontSize="9"
            fill={isSmall ? accentColor : t.fadedText} textAnchor="end"
            letterSpacing="0.08em" fontWeight={isSmall ? 600 : 400}>
            SMALL · FAST
          </text>
        </g>
      </svg>
    </div>
  );
};

window.HeroGlyph = HeroGlyph;
