/* NEXABOT — animated node network canvas (automation / data-center motif) */

function NodeNetwork({ intensity = 1 }) {
  const ref = React.useRef(null);

  React.useEffect(() => {
    const canvas = ref.current;
    if (!canvas) return;
    const ctx = canvas.getContext("2d");
    let raf, W, H, DPR;
    let nodes = [];
    let mouse = { x: -9999, y: -9999 };
    const reduce = window.matchMedia("(prefers-reduced-motion: reduce)").matches;

    const css = getComputedStyle(document.documentElement);
    function colors() {
      return {
        a: css.getPropertyValue("--accent").trim() || "#3b82f6",
        b: css.getPropertyValue("--accent-2").trim() || "#06b6d4",
      };
    }

    function resize() {
      DPR = Math.min(window.devicePixelRatio || 1, 2);
      W = canvas.clientWidth; H = canvas.clientHeight;
      canvas.width = W * DPR; canvas.height = H * DPR;
      ctx.setTransform(DPR, 0, 0, DPR, 0, 0);
      const density = Math.max(26, Math.min(70, Math.floor((W * H) / 22000)));
      const count = Math.round(density * intensity);
      nodes = Array.from({ length: count }, () => ({
        x: Math.random() * W,
        y: Math.random() * H,
        vx: (Math.random() - 0.5) * 0.28 * (reduce ? 0 : 1),
        vy: (Math.random() - 0.5) * 0.28 * (reduce ? 0 : 1),
        r: Math.random() * 1.6 + 0.8,
        pulse: Math.random() * Math.PI * 2,
      }));
    }

    function step() {
      const { a, b } = colors();
      ctx.clearRect(0, 0, W, H);
      const linkDist = 150;

      for (const n of nodes) {
        n.x += n.vx; n.y += n.vy;
        if (n.x < 0 || n.x > W) n.vx *= -1;
        if (n.y < 0 || n.y > H) n.vy *= -1;
        // gentle pull toward mouse
        const dx = mouse.x - n.x, dy = mouse.y - n.y;
        const md = Math.hypot(dx, dy);
        if (md < 180) { n.x += (dx / md) * 0.4; n.y += (dy / md) * 0.4; }
        n.pulse += 0.02;
      }

      // links
      for (let i = 0; i < nodes.length; i++) {
        for (let j = i + 1; j < nodes.length; j++) {
          const a1 = nodes[i], b1 = nodes[j];
          const d = Math.hypot(a1.x - b1.x, a1.y - b1.y);
          if (d < linkDist) {
            const o = (1 - d / linkDist) * 0.5;
            ctx.strokeStyle = `rgba(96, 165, 250, ${o})`;
            ctx.lineWidth = 0.7;
            ctx.beginPath();
            ctx.moveTo(a1.x, a1.y); ctx.lineTo(b1.x, b1.y); ctx.stroke();
          }
        }
      }
      // nodes
      for (const n of nodes) {
        const glow = (Math.sin(n.pulse) + 1) / 2;
        ctx.beginPath();
        ctx.arc(n.x, n.y, n.r + glow * 0.6, 0, Math.PI * 2);
        ctx.fillStyle = glow > 0.6 ? b : a;
        ctx.shadowBlur = 8 + glow * 8;
        ctx.shadowColor = a;
        ctx.fill();
        ctx.shadowBlur = 0;
      }
      raf = requestAnimationFrame(step);
    }

    resize();
    if (reduce) { step(); cancelAnimationFrame(raf); }
    else step();

    const onMove = (e) => {
      const rect = canvas.getBoundingClientRect();
      mouse.x = e.clientX - rect.left; mouse.y = e.clientY - rect.top;
    };
    const onLeave = () => { mouse.x = -9999; mouse.y = -9999; };
    window.addEventListener("resize", resize);
    canvas.addEventListener("pointermove", onMove);
    canvas.addEventListener("pointerleave", onLeave);

    return () => {
      cancelAnimationFrame(raf);
      window.removeEventListener("resize", resize);
      canvas.removeEventListener("pointermove", onMove);
      canvas.removeEventListener("pointerleave", onLeave);
    };
  }, [intensity]);

  return <canvas ref={ref} className="node-canvas" />;
}

window.NodeNetwork = NodeNetwork;
