const { useEffect, useRef, useState, useMemo } = React;

function mulberry32(a) {
  return function () {
    let t = (a += 0x6D2B79F5);
    t = Math.imul(t ^ (t >>> 15), t | 1);
    t ^= t + Math.imul(t ^ (t >>> 7), t | 61);
    return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
  };
}

// Animated spectrum
function Spectrum({ stable = true, intensity = 1 }) {
  const [t, setT] = useState(0);
  useEffect(() => {
    let raf, last = performance.now();
    const tick = (now) => { setT((p) => p + (now - last) * 0.001); last = now; raf = requestAnimationFrame(tick); };
    raf = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(raf);
  }, []);
  const W = 600, H = 150, N = 56;
  return (
    <svg viewBox={`0 0 ${W} ${H}`} preserveAspectRatio="none" style={{ width: "100%", height: "100%" }}>
      <defs>
        <linearGradient id="v2-spec" x1="0" x2="0" y1="0" y2="1">
          <stop offset="0%" stopColor="var(--energy)" stopOpacity="0.95" />
          <stop offset="100%" stopColor="var(--energy)" stopOpacity="0.08" />
        </linearGradient>
      </defs>
      {[0.25, 0.5, 0.75].map((p, i) => (
        <line key={i} x1="0" x2={W} y1={H*p} y2={H*p} stroke="var(--hair)" strokeDasharray="2 4" />
      ))}
      {Array.from({length: N}).map((_, i) => {
        const x = (i / N) * W;
        const phase = t * (stable ? 1.4 : 2.6) + i * 0.32;
        const env = Math.exp(-Math.pow((i - N/2) / (N/2.6), 2));
        const noise = stable ? 0.10 : 0.32;
        const h = (Math.sin(phase) * 0.4 + Math.sin(phase*2.3 + i*0.2) * 0.3 + 0.5) * env * intensity + (Math.random()-0.5) * noise;
        const bh = Math.max(2, Math.min(H-4, H * 0.85 * Math.max(0.05, h)));
        return <rect key={i} x={x+1.5} y={H-bh} width={W/N - 3} height={bh} fill="url(#v2-spec)" />;
      })}
    </svg>
  );
}

// Topology
function TopologyGraph({ nodes = 412, seed = 1 }) {
  const W = 600, H = 280;
  const NN = Math.min(28, Math.max(8, Math.round(nodes / 18)));
  const points = useMemo(() => {
    const rng = mulberry32(seed * 9301 + 1);
    return Array.from({ length: NN }).map((_, i) => {
      const r = (i % 5 === 0) ? 0.18 : 0.32 + rng() * 0.36;
      const a = rng() * Math.PI * 2;
      return {
        x: W*0.5 + Math.cos(a) * W * r * 0.7,
        y: H*0.5 + Math.sin(a) * H * r,
        size: i % 6 === 0 ? 5.5 : (i % 3 === 0 ? 3.6 : 2.4),
        kind: i % 7 === 0 ? "anchor" : "node",
      };
    });
  }, [seed, NN]);
  const edges = useMemo(() => {
    const rng = mulberry32(seed * 13);
    const e = [];
    for (let i = 0; i < points.length; i++) {
      const k = 1 + Math.floor(rng() * 3);
      for (let j = 0; j < k; j++) {
        const tg = (i + 1 + Math.floor(rng() * (points.length - 1))) % points.length;
        if (tg !== i) e.push([i, tg]);
      }
    }
    return e;
  }, [points, seed]);
  const [t, setT] = useState(0);
  useEffect(() => {
    let raf;
    const tick = () => { setT(performance.now() * 0.001); raf = requestAnimationFrame(tick); };
    raf = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(raf);
  }, []);
  return (
    <svg viewBox={`0 0 ${W} ${H}`} preserveAspectRatio="xMidYMid meet">
      <defs>
        <radialGradient id="v2-anchor"><stop offset="0%" stopColor="var(--energy)" stopOpacity="0.9" /><stop offset="100%" stopColor="var(--energy)" stopOpacity="0" /></radialGradient>
      </defs>
      {[60, 110, 150].map((r, i) => <circle key={i} cx={W/2} cy={H/2} r={r} fill="none" stroke="var(--hair)" strokeDasharray="2 4" />)}
      {edges.map(([a, b], i) => {
        const A = points[a], B = points[b];
        const phase = (t * 0.6 + i * 0.13) % 1;
        return (
          <g key={i}>
            <line x1={A.x} y1={A.y} x2={B.x} y2={B.y} stroke="var(--hair-strong)" strokeWidth="0.7" />
            <circle cx={A.x + (B.x-A.x)*phase} cy={A.y + (B.y-A.y)*phase} r="1.4" fill="var(--energy)" />
          </g>
        );
      })}
      {points.map((p, i) => {
        const a = p.kind === "anchor";
        return (
          <g key={i}>
            {a && <circle cx={p.x} cy={p.y} r={p.size*3} fill="url(#v2-anchor)" />}
            <rect x={p.x-p.size} y={p.y-p.size} width={p.size*2} height={p.size*2}
              transform={`rotate(45 ${p.x} ${p.y})`}
              fill={a ? "var(--energy)" : "transparent"}
              stroke={a ? "var(--energy)" : "var(--fg-2)"} strokeWidth="0.9" />
          </g>
        );
      })}
      <circle cx={W/2} cy={H/2} r="3.5" fill="var(--energy)" />
      <circle cx={W/2} cy={H/2} r="8" fill="none" stroke="var(--energy)" />
    </svg>
  );
}

// Synesthesia waves
function SynesStream() {
  const [t, setT] = useState(0);
  useEffect(() => {
    let raf;
    const tick = () => { setT(performance.now() * 0.001); raf = requestAnimationFrame(tick); };
    raf = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(raf);
  }, []);
  const W = 600, H = 140;
  const lines = [
    { y: H*0.25, amp: 12, freq: 1.6, c: "var(--energy)", op: 0.9 },
    { y: H*0.50, amp: 18, freq: 0.8, c: "var(--energy)", op: 0.55 },
    { y: H*0.75, amp: 8,  freq: 2.4, c: "var(--gold)",   op: 0.7 },
  ];
  return (
    <svg viewBox={`0 0 ${W} ${H}`} preserveAspectRatio="none">
      {lines.map((c, ci) => {
        const pts = [];
        for (let i = 0; i <= 100; i++) {
          const x = (i/100)*W;
          const y = c.y + Math.sin(t*c.freq + i*0.15)*c.amp + Math.sin(t*c.freq*1.7 + i*0.27)*c.amp*0.4;
          pts.push(`${i===0?"M":"L"}${x},${y}`);
        }
        return (
          <g key={ci}>
            <line x1="0" x2={W} y1={c.y} y2={c.y} stroke="var(--hair)" />
            <path d={pts.join(" ")} stroke={c.c} strokeWidth="1" fill="none" opacity={c.op} />
          </g>
        );
      })}
    </svg>
  );
}

// Knob
function Knob({ value, onChange, label, zh, disabled }) {
  const ang = 30 + (value / 100) * 240;
  const drag = (e) => {
    if (disabled) return;
    e.preventDefault();
    const sy = e.clientY, sv = value;
    const move = (ev) => onChange(Math.max(0, Math.min(100, Math.round(sv + (sy - ev.clientY) * 0.6))));
    const up = () => { window.removeEventListener("mousemove", move); window.removeEventListener("mouseup", up); };
    window.addEventListener("mousemove", move);
    window.addEventListener("mouseup", up);
  };
  return (
    <div className="knob">
      <div className="knob-dial" style={{ "--ang": `${ang}deg`, opacity: disabled ? 0.4 : 1 }} onMouseDown={drag} />
      <div className="knob-val mono">{value}</div>
      <div className="knob-label">{label}</div>
      <div className="knob-zh">{zh}</div>
    </div>
  );
}

// Fingerprint SVG
function FingerprintSVG({ seed = 1, color = "var(--gold)" }) {
  return (
    <svg viewBox="0 0 90 90">
      <defs>
        <radialGradient id={`fp-${seed}`}>
          <stop offset="0%" stopColor={color} stopOpacity="0.5" />
          <stop offset="100%" stopColor={color} stopOpacity="0" />
        </radialGradient>
      </defs>
      <circle cx="45" cy="45" r="40" fill={`url(#fp-${seed})`} />
      {Array.from({length:9}).map((_, i) => {
        const r = 6 + i * 4;
        const off = Math.sin((i+seed) * 1.3) * 4;
        return <circle key={i} cx={45 + off*0.3} cy={45} r={r} fill="none"
          stroke={color} strokeOpacity={0.35 + (i%3)*0.18}
          strokeWidth="0.8" strokeDasharray={`${10+i*1.5} ${4+(i%3)}`} />;
      })}
      <circle cx="45" cy="45" r="2" fill={color} />
      <line x1="45" y1="5" x2="45" y2="85" stroke={color} strokeOpacity="0.15" strokeDasharray="2 3" />
      <line x1="5" y1="45" x2="85" y2="45" stroke={color} strokeOpacity="0.15" strokeDasharray="2 3" />
    </svg>
  );
}

window.HG2Atoms = { Spectrum, TopologyGraph, SynesStream, Knob, FingerprintSVG };
