/* Network background — custom particle field with connecting edges.
   Faithful to Vanta.NET's mood, but on-brand: monochrome with selective
   accent flares; respects reduced motion; gentle depth + drift. */

function NetworkBackground({ density = 'balanced' }) {
  const canvasRef = React.useRef(null);
  const [visible, setVisible] = React.useState(false);

  React.useEffect(() => {
    const t = setTimeout(() => setVisible(true), 600); // patient reveal AFTER hero copy
    return () => clearTimeout(t);
  }, []);

  React.useEffect(() => {
    const canvas = canvasRef.current;
    if (!canvas) return;
    const ctx = canvas.getContext('2d');
    const dpr = Math.min(window.devicePixelRatio || 1, 2);
    let w = 0, h = 0, raf = 0;
    let mouse = { x: -1000, y: -1000, active: false };
    const reduced = window.matchMedia('(prefers-reduced-motion: reduce)').matches;

    const counts = { sparse: 50, balanced: 90, dense: 150 };
    const N = counts[density] || counts.balanced;

    // Theme-aware palette — re-read at every frame so live toggling works.
    function palette() {
      const dark = document.body.classList.contains('dark');
      return dark
        ? {
            hazeFrom: 'rgba(31,33,37,0)',
            hazeTo:   'rgba(0,0,0,0.45)',
            node:     (z) => `rgba(243,246,247,${0.35 + z * 0.35})`,
            edge:     (t) => `rgba(243,246,247,${t * 0.18})`,
            accent:   'rgba(245,11,11,0.85)',
            accentEdge: (t) => `rgba(245,11,11,${t * 0.45})`,
          }
        : {
            hazeFrom: 'rgba(243,246,247,0)',
            hazeTo:   'rgba(28,28,28,0.06)',
            node:     (z) => `rgba(28,28,28,${0.18 + z * 0.18})`,
            edge:     (t) => `rgba(28,28,28,${t * 0.10})`,
            accent:   'rgba(232,81,58,0.55)',
            accentEdge: (t) => `rgba(232,81,58,${t * 0.28})`,
          };
    }

    function resize() {
      w = canvas.clientWidth;
      h = canvas.clientHeight;
      canvas.width = w * dpr;
      canvas.height = h * dpr;
      ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
    }

    // Build node field
    let nodes = [];
    function build() {
      nodes = Array.from({ length: N }, () => ({
        x: Math.random() * w,
        y: Math.random() * h,
        z: 0.4 + Math.random() * 0.6,             // depth 0.4..1
        vx: (Math.random() - 0.5) * 0.18,
        vy: (Math.random() - 0.5) * 0.18,
        accent: Math.random() < 0.06              // ~6% glow red
      }));
    }

    function step(animate) {
      const pal = palette();
      ctx.clearRect(0, 0, w, h);

      const grd = ctx.createRadialGradient(w / 2, h / 2, 0, w / 2, h / 2, Math.max(w, h) * 0.7);
      grd.addColorStop(0, pal.hazeFrom);
      grd.addColorStop(1, pal.hazeTo);
      ctx.fillStyle = grd;
      ctx.fillRect(0, 0, w, h);

      for (const p of nodes) {
        if (animate) {
          p.x += p.vx; p.y += p.vy;
          if (p.x < -10) p.x = w + 10;
          if (p.x > w + 10) p.x = -10;
          if (p.y < -10) p.y = h + 10;
          if (p.y > h + 10) p.y = -10;

          if (mouse.active) {
            const dx = mouse.x - p.x, dy = mouse.y - p.y;
            const d2 = dx * dx + dy * dy;
            if (d2 < 18000) {
              const k = (1 - d2 / 18000) * 0.025;
              p.x += dx * k; p.y += dy * k;
            }
          }
        }

        const r = 1.0 + p.z * 0.8;
        ctx.fillStyle = p.accent ? pal.accent : pal.node(p.z);
        ctx.beginPath(); ctx.arc(p.x, p.y, r, 0, Math.PI * 2); ctx.fill();
      }

      const MAX_D = 130;
      for (let i = 0; i < nodes.length; i++) {
        const a = nodes[i];
        for (let j = i + 1; j < nodes.length; j++) {
          const b = nodes[j];
          const dx = a.x - b.x, dy = a.y - b.y;
          const d = Math.sqrt(dx * dx + dy * dy);
          if (d < MAX_D) {
            const t = 1 - d / MAX_D;
            const accent = a.accent || b.accent;
            ctx.strokeStyle = accent ? pal.accentEdge(t) : pal.edge(t);
            ctx.lineWidth = accent ? 0.8 : 0.5;
            ctx.beginPath();
            ctx.moveTo(a.x, a.y); ctx.lineTo(b.x, b.y);
            ctx.stroke();
          }
        }
      }

      if (animate) raf = requestAnimationFrame(() => step(true));
    }

    function onMove(e) {
      const rect = canvas.getBoundingClientRect();
      mouse.x = e.clientX - rect.left;
      mouse.y = e.clientY - rect.top;
      mouse.active = true;
    }
    function onLeave() { mouse.active = false; }

    resize(); build();
    step(!reduced);

    // Re-paint a static frame whenever the theme changes so the palette swaps
    // even if motion is reduced.
    const themeObs = new MutationObserver(() => { if (reduced) step(false); });
    themeObs.observe(document.body, { attributes: true, attributeFilter: ['class'] });

    function onResize() { resize(); build(); if (reduced) step(false); }
    window.addEventListener('resize', onResize);
    window.addEventListener('mousemove', onMove);
    window.addEventListener('mouseleave', onLeave);

    return () => {
      cancelAnimationFrame(raf);
      themeObs.disconnect();
      window.removeEventListener('resize', onResize);
      window.removeEventListener('mousemove', onMove);
      window.removeEventListener('mouseleave', onLeave);
    };
  }, [density]);

  return (
    <div className={`netbg ${visible ? 'in' : ''}`} aria-hidden="true">
      <canvas ref={canvasRef} />
    </div>
  );
}

window.NetworkBackground = NetworkBackground;
