/* ============================================================================
   AMBIENT BACKGROUND — gradient mesh + sparse drifting grid/particles.
   Evokes compute, not a screensaver. Caps particle count, simplifies on phones,
   honors prefers-reduced-motion (static gradient, no rAF loop).
   ============================================================================ */
const { useRef, useEffect } = React;

function AmbientBackground({ accent }) {
  const canvasRef = useRef(null);
  const accentRef = useRef(accent);
  const pointerRef = useRef({ x: 0.5, y: 0.4, tx: 0.5, ty: 0.4 });

  useEffect(() => { accentRef.current = accent; }, [accent]);

  useEffect(() => {
    const canvas = canvasRef.current;
    if (!canvas) return;
    const ctx = canvas.getContext("2d");
    const reduce = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
    const mobile = window.matchMedia("(max-width: 640px)").matches;

    let w = 0, h = 0, dpr = Math.min(window.devicePixelRatio || 1, 2);
    function resize() {
      w = canvas.clientWidth; h = canvas.clientHeight;
      canvas.width = w * dpr; canvas.height = h * dpr;
      ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
    }
    resize();
    window.addEventListener("resize", resize);

    // sparse node field
    const COUNT = mobile ? 26 : 54;
    const nodes = Array.from({ length: COUNT }, () => ({
      x: Math.random(), y: Math.random(),
      vx: (Math.random() - 0.5) * 0.00018,
      vy: (Math.random() - 0.5) * 0.00018,
      r: Math.random() * 1.4 + 0.6,
    }));

    function hexToRgb(hex) {
      const m = hex.replace("#", "");
      return [parseInt(m.slice(0, 2), 16), parseInt(m.slice(2, 4), 16), parseInt(m.slice(4, 6), 16)];
    }

    function drawMesh() {
      const [r, g, b] = hexToRgb(accentRef.current || "#4A76F6");
      const p = pointerRef.current;
      // base
      ctx.fillStyle = "#0A0B0F";
      ctx.fillRect(0, 0, w, h);
      // accent glow following pointer faintly
      const gx = p.x * w, gy = p.y * h;
      const grad = ctx.createRadialGradient(gx, gy, 0, gx, gy, Math.max(w, h) * 0.7);
      grad.addColorStop(0, `rgba(${r},${g},${b},0.14)`);
      grad.addColorStop(0.4, `rgba(${r},${g},${b},0.05)`);
      grad.addColorStop(1, "rgba(10,11,15,0)");
      ctx.fillStyle = grad;
      ctx.fillRect(0, 0, w, h);
      // a cooler second pool for depth
      const grad2 = ctx.createRadialGradient(w * 0.85, h * 0.1, 0, w * 0.85, h * 0.1, Math.max(w, h) * 0.6);
      grad2.addColorStop(0, "rgba(74,118,246,0.10)");
      grad2.addColorStop(1, "rgba(10,11,15,0)");
      ctx.fillStyle = grad2;
      ctx.fillRect(0, 0, w, h);
    }

    function drawNodes() {
      const [r, g, b] = hexToRgb(accentRef.current || "#4A76F6");
      const px = pointerRef.current.x * w, py = pointerRef.current.y * h;
      // links
      for (let i = 0; i < nodes.length; i++) {
        const a = nodes[i];
        const ax = a.x * w, ay = a.y * h;
        for (let j = i + 1; j < nodes.length; j++) {
          const c = nodes[j];
          const cx = c.x * w, cy = c.y * h;
          const dx = ax - cx, dy = ay - cy;
          const d = Math.hypot(dx, dy);
          const max = mobile ? 110 : 150;
          if (d < max) {
            const o = (1 - d / max) * 0.18;
            ctx.strokeStyle = `rgba(${r},${g},${b},${o})`;
            ctx.lineWidth = 1;
            ctx.beginPath(); ctx.moveTo(ax, ay); ctx.lineTo(cx, cy); ctx.stroke();
          }
        }
      }
      // dots
      for (const n of nodes) {
        const nx = n.x * w, ny = n.y * h;
        const dp = Math.hypot(nx - px, ny - py);
        const near = dp < 140 ? (1 - dp / 140) : 0;
        ctx.beginPath();
        ctx.arc(nx, ny, n.r + near * 1.2, 0, Math.PI * 2);
        ctx.fillStyle = `rgba(${r},${g},${b},${0.3 + near * 0.5})`;
        ctx.fill();
      }
    }

    let raf;
    function frame() {
      const p = pointerRef.current;
      p.x += (p.tx - p.x) * 0.04;
      p.y += (p.ty - p.y) * 0.04;
      for (const n of nodes) {
        n.x += n.vx; n.y += n.vy;
        if (n.x < 0 || n.x > 1) n.vx *= -1;
        if (n.y < 0 || n.y > 1) n.vy *= -1;
      }
      drawMesh();
      drawNodes();
      raf = requestAnimationFrame(frame);
    }

    if (reduce) {
      drawMesh();
      drawNodes();
    } else {
      raf = requestAnimationFrame(frame);
    }

    function onMove(e) {
      const t = e.touches ? e.touches[0] : e;
      pointerRef.current.tx = t.clientX / window.innerWidth;
      pointerRef.current.ty = t.clientY / window.innerHeight;
    }
    if (!reduce) {
      window.addEventListener("pointermove", onMove, { passive: true });
      window.addEventListener("touchmove", onMove, { passive: true });
    }

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

  return React.createElement("canvas", { ref: canvasRef, className: "ambient-canvas" });
}

window.AmbientBackground = AmbientBackground;
