/* Reactive overlay for the static cube-wall background.
   Detects cursor position and draws per-cell lift effects (brightness +
   drop shadow) that make cubes appear to pop out from the image. */

const { useEffect, useRef } = React;

function VoxelField() {
  const canvasRef = useRef(null);
  const mouse = useRef({ x: -9999, y: -9999, active: false, lastMove: 0 });

  useEffect(() => {
    const canvas = canvasRef.current;
    const ctx = canvas.getContext("2d");
    let raf;
    let W = 0, H = 0;
    const dpr = Math.min(window.devicePixelRatio || 1, 2);

    const CELL = 60;         // grid cell size — tuned to roughly match image cubes
    const RADIUS = 240;      // mouse influence radius
    const MAX_RAISE = 10;    // visual lift in px

    let cells = [];

    function resize() {
      const rect = canvas.getBoundingClientRect();
      W = rect.width; H = rect.height;
      canvas.width = W * dpr; canvas.height = H * dpr;
      ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
      buildCells();
    }

    function buildCells() {
      cells = [];
      const cols = Math.ceil(W / CELL) + 1;
      const rows = Math.ceil(H / CELL) + 1;
      for (let j = 0; j < rows; j++) {
        for (let i = 0; i < cols; i++) {
          // offset rows a bit so lifts don't look perfectly gridded
          const jitter = ((i * 7 + j * 13) * 9301) % 233280 / 233280;
          cells.push({
            x: i * CELL,
            y: j * CELL + (j % 2 === 1 ? CELL * 0.1 : 0),
            s: CELL + (jitter > 0.7 ? 8 : 0),
            noise: jitter,
            raise: 0, vel: 0,
          });
        }
      }
    }

    resize();
    window.addEventListener("resize", resize);

    const onMove = (e) => {
      const r = canvas.getBoundingClientRect();
      mouse.current.x = e.clientX - r.left;
      mouse.current.y = e.clientY - r.top;
      mouse.current.active = true;
      mouse.current.lastMove = performance.now();
    };
    const onLeave = () => { mouse.current.active = false; };
    window.addEventListener("mousemove", onMove);
    window.addEventListener("mouseleave", onLeave);

    function draw(t) {
      const mx = mouse.current.x, my = mouse.current.y;
      const active = mouse.current.active && (performance.now() - mouse.current.lastMove < 2500);
      const stiff = 0.15, damp = 0.80;

      for (let i = 0; i < cells.length; i++) {
        const c = cells[i];
        let target = 0;
        if (active) {
          const cx = c.x + c.s * 0.5;
          const cy = c.y + c.s * 0.5;
          const dx = cx - mx, dy = cy - my;
          const d = Math.sqrt(dx*dx + dy*dy);
          if (d < RADIUS) {
            const k = 1 - d / RADIUS;
            target = Math.pow(k, 1.5) * MAX_RAISE *
                     (0.7 + 0.3 * Math.sin(t * 0.005 - d * 0.03)) *
                     (0.6 + 0.8 * c.noise);
          }
        }
        const a = (target - c.raise) * stiff;
        c.vel = (c.vel + a) * damp;
        c.raise += c.vel;
        if (Math.abs(c.raise) < 0.02 && Math.abs(c.vel) < 0.02) {
          c.raise = 0; c.vel = 0;
        }
      }

      ctx.clearRect(0, 0, W, H);

      // Pass 1: shadows below raised cells (darken the gap they left)
      ctx.globalCompositeOperation = "source-over";
      for (let i = 0; i < cells.length; i++) {
        const c = cells[i];
        if (c.raise < 0.5) continue;
        const a = Math.min(0.65, c.raise * 0.07);
        ctx.fillStyle = `rgba(0,0,0,${a})`;
        // shadow sits below where the cube "was"
        ctx.fillRect(c.x + 2, c.y + c.raise * 0.3, c.s - 4, c.s);
      }

      // Pass 2: lighten raised cell (suggests top face catching light)
      ctx.globalCompositeOperation = "screen";
      for (let i = 0; i < cells.length; i++) {
        const c = cells[i];
        if (c.raise < 0.3) continue;
        const a = Math.min(0.35, c.raise * 0.04);
        const v = Math.floor(a * 255);
        ctx.fillStyle = `rgb(${v},${v},${v})`;
        // cube "top" shifts up as it raises
        ctx.fillRect(c.x, c.y - c.raise, c.s - 2, c.s - 2);
      }

      ctx.globalCompositeOperation = "source-over";
      raf = requestAnimationFrame(draw);
    }
    raf = requestAnimationFrame(draw);

    return () => {
      cancelAnimationFrame(raf);
      window.removeEventListener("resize", resize);
      window.removeEventListener("mousemove", onMove);
      window.removeEventListener("mouseleave", onLeave);
    };
  }, []);

  return (
    <canvas ref={canvasRef}
      style={{
        position: "absolute", inset: 0, width: "100%", height: "100%",
        display: "block", pointerEvents: "none",
      }}
    />
  );
}

window.VoxelField = VoxelField;
