// Full-viewport interactive dot grid.
// Dots are arranged on a regular grid; dots within `radius` of the cursor
// brighten and grow, with smooth easing back to rest.
const DotGrid = ({
  spacing = 36,
  baseRadius = 1.1,
  hoverRadius = 3.2,
  baseColor = [150, 165, 160, 0.55],
  hoverColor = [74, 222, 128, 1],
  influence = 180,
  fade = 0.10,
}) => {
  const ref = React.useRef(null);

  React.useEffect(() => {
    const canvas = ref.current;
    if (!canvas) return;
    const ctx = canvas.getContext("2d");
    let dpr = Math.min(window.devicePixelRatio || 1, 2);
    let w = 0, h = 0;
    let dots = [];
    let mouse = { x: -9999, y: -9999, active: false };
    let raf = 0;

    const buildDots = () => {
      const cols = Math.ceil(w / spacing) + 2;
      const rows = Math.ceil(h / spacing) + 2;
      const offsetX = (w - (cols - 1) * spacing) / 2;
      const offsetY = (h - (rows - 1) * spacing) / 2;
      dots = [];
      for (let r = 0; r < rows; r++) {
        for (let c = 0; c < cols; c++) {
          // tiny jitter so it doesn't feel mechanical
          const jx = (Math.sin(r * 12.9898 + c * 78.233) * 43758.5453) % 1;
          const jy = (Math.cos(r * 4.123 + c * 91.7) * 12345.67) % 1;
          dots.push({
            x: offsetX + c * spacing + jx * 1.5,
            y: offsetY + r * spacing + jy * 1.5,
            t: 0, // current activation 0..1
          });
        }
      }
    };

    const resize = () => {
      w = canvas.clientWidth;
      h = canvas.clientHeight;
      canvas.width = Math.floor(w * dpr);
      canvas.height = Math.floor(h * dpr);
      ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
      buildDots();
    };

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

    const draw = () => {
      ctx.clearRect(0, 0, w, h);
      const infl2 = influence * influence;
      for (let i = 0; i < dots.length; i++) {
        const d = dots[i];
        let target = 0;
        if (mouse.active) {
          const dx = d.x - mouse.x;
          const dy = d.y - mouse.y;
          const dist2 = dx * dx + dy * dy;
          if (dist2 < infl2) {
            const t = 1 - Math.sqrt(dist2) / influence;
            target = t * t; // ease-in
          }
        }
        // smooth ease toward target
        d.t += (target - d.t) * fade;
        const t = d.t;

        if (t < 0.01) {
          ctx.fillStyle = `rgba(${baseColor[0]},${baseColor[1]},${baseColor[2]},${baseColor[3]})`;
          ctx.beginPath();
          ctx.arc(d.x, d.y, baseRadius, 0, Math.PI * 2);
          ctx.fill();
        } else {
          // lerp color + radius
          const r = baseRadius + (hoverRadius - baseRadius) * t;
          const cr = baseColor[0] + (hoverColor[0] - baseColor[0]) * t;
          const cg = baseColor[1] + (hoverColor[1] - baseColor[1]) * t;
          const cb = baseColor[2] + (hoverColor[2] - baseColor[2]) * t;
          const ca = baseColor[3] + (hoverColor[3] - baseColor[3]) * t;
          // outer glow
          if (t > 0.25) {
            const glow = ctx.createRadialGradient(d.x, d.y, 0, d.x, d.y, r * 5);
            glow.addColorStop(0, `rgba(${cr|0},${cg|0},${cb|0},${0.12 * t})`);
            glow.addColorStop(1, `rgba(${cr|0},${cg|0},${cb|0},0)`);
            ctx.fillStyle = glow;
            ctx.beginPath();
            ctx.arc(d.x, d.y, r * 5, 0, Math.PI * 2);
            ctx.fill();
          }
          ctx.fillStyle = `rgba(${cr|0},${cg|0},${cb|0},${ca})`;
          ctx.beginPath();
          ctx.arc(d.x, d.y, r, 0, Math.PI * 2);
          ctx.fill();
        }
      }
      raf = requestAnimationFrame(draw);
    };

    resize();
    window.addEventListener("resize", resize);
    window.addEventListener("mousemove", onMove);
    window.addEventListener("mouseleave", onLeave);
    // touch
    const onTouch = (e) => {
      if (e.touches[0]) {
        const rect = canvas.getBoundingClientRect();
        mouse.x = e.touches[0].clientX - rect.left;
        mouse.y = e.touches[0].clientY - rect.top;
        mouse.active = true;
      }
    };
    window.addEventListener("touchmove", onTouch, { passive: true });
    window.addEventListener("touchend", onLeave);
    raf = requestAnimationFrame(draw);
    return () => {
      cancelAnimationFrame(raf);
      window.removeEventListener("resize", resize);
      window.removeEventListener("mousemove", onMove);
      window.removeEventListener("mouseleave", onLeave);
      window.removeEventListener("touchmove", onTouch);
      window.removeEventListener("touchend", onLeave);
    };
  }, [spacing, baseRadius, hoverRadius, influence, fade]);

  return (
    <canvas
      ref={ref}
      style={{
        position: "fixed",
        inset: 0,
        width: "100vw",
        height: "100vh",
        pointerEvents: "none",
        zIndex: 0,
        filter: "blur(0.4px)",
        opacity: 0.85,
      }}
    />
  );
};
window.DotGrid = DotGrid;
