/* global React */
const { useRef: useRefHC, useEffect: useEffectHC } = React;

function HeroCanvas() {
  const mountRef = useRefHC(null);

  useEffectHC(() => {
    const canvas = mountRef.current;
    if (!canvas) return;

    const ctx = canvas.getContext('2d');

    let w = canvas.offsetWidth || window.innerWidth;
    let h = canvas.offsetHeight || window.innerHeight;
    canvas.width  = w;
    canvas.height = h;

    // Build particle list once.
    // hx/hy: "home" position that always drifts at vx/vy — never touched by warp.
    // ox/oy: offset from home caused by cursor repulsion.
    // dvx/dvy: velocity of that offset; spring pulls it back to zero.
    const particles = [];
    for (let i = 0; i < 280; i++) {
      const isTeal = Math.random() > 0.38;
      const sx = Math.random() * w;
      const sy = Math.random() * h;
      particles.push({
        hx: sx, hy: sy,              // home (natural drift)
        ox: 0,  oy: 0,               // displacement from home
        dvx: 0, dvy: 0,              // velocity of displacement
        vx: (Math.random() - 0.5) * 0.14,
        vy: (Math.random() - 0.5) * 0.14,
        r:  0.7 + Math.random() * 1.4,
        a:  0.18 + Math.random() * 0.38,
        color: isTeal ? '0,212,170' : '240,168,66',
        twinkle: 0,
        twinkleRate: 0.004 + Math.random() * 0.008,
      });
    }

    const onResize = () => {
      w = canvas.offsetWidth;
      h = canvas.offsetHeight;
      canvas.width  = w;
      canvas.height = h;
    };
    window.addEventListener('resize', onResize);

    let cursorInArea = false;
    let mx = -9999, my = -9999;
    const parent = canvas.parentElement;

    const onEnter = () => { cursorInArea = true; };
    const onLeave = () => { cursorInArea = false; mx = -9999; my = -9999; };
    const onMove  = (e) => {
      const r = canvas.getBoundingClientRect();
      mx = e.clientX - r.left;
      my = e.clientY - r.top;
    };

    if (parent) {
      parent.addEventListener('mouseenter', onEnter,  { passive: true });
      parent.addEventListener('mouseleave', onLeave,  { passive: true });
      parent.addEventListener('mousemove',  onMove,   { passive: true });
    }

    // Glow radius matches CSS: 500px div, gradient fades to 0 at 70% = 350px
    const GLOW_RADIUS  = 350;
    const GLOW_ALPHA   = 0.10;  // opacity at glow center in the CSS
    const WARP_ACCEL   = 4.8;   // push force at full glow strength
    const SPRING_K     = 0.045; // how strongly home pulls the particle back
    const DAMPING      = 0.86;  // velocity damping per frame — controls oscillation

    // Cap at 30fps — more than enough for slow-drifting particles
    let raf, last = 0;
    const tick = (now) => {
      raf = requestAnimationFrame(tick);
      if (now - last < 33) return;
      last = now;

      ctx.clearRect(0, 0, w, h);

      for (const p of particles) {
        // Advance home position at natural drift speed
        p.hx += p.vx;
        p.hy += p.vy;
        if (p.hx < -2)    p.hx = w + 2;
        if (p.hx > w + 2) p.hx = -2;
        if (p.hy < -2)    p.hy = h + 2;
        if (p.hy > h + 2) p.hy = -2;

        // Spring: pull displacement back toward zero (home)
        p.dvx += -p.ox * SPRING_K;
        p.dvy += -p.oy * SPRING_K;

        // Cursor repulsion — only when cursor is present
        if (cursorInArea) {
          const rx = (p.hx + p.ox) - mx;
          const ry = (p.hy + p.oy) - my;
          const dist = Math.sqrt(rx * rx + ry * ry);
          if (dist > 0 && dist < GLOW_RADIUS) {
            const glowStrength = GLOW_ALPHA * (1 - dist / GLOW_RADIUS);
            const accel = glowStrength * WARP_ACCEL;
            p.dvx += (rx / dist) * accel;
            p.dvy += (ry / dist) * accel;
          }
        }

        // Dampen and apply displacement velocity
        p.dvx *= DAMPING;
        p.dvy *= DAMPING;
        p.ox  += p.dvx;
        p.oy  += p.dvy;

        // Twinkle — only fires when cursor is in area; always decays
        if (cursorInArea && Math.random() < p.twinkleRate) p.twinkle = 1;
        p.twinkle *= 0.82;

        const px     = p.hx + p.ox;
        const py     = p.hy + p.oy;
        const alpha  = p.a  + p.twinkle * 0.38;
        const radius = p.r  + p.twinkle * 0.85;

        ctx.beginPath();
        ctx.arc(px, py, radius, 0, Math.PI * 2);
        ctx.fillStyle = `rgba(${p.color},${alpha})`;
        ctx.fill();
      }
    };
    requestAnimationFrame(tick);

    return () => {
      cancelAnimationFrame(raf);
      window.removeEventListener('resize', onResize);
      if (parent) {
        parent.removeEventListener('mouseenter', onEnter);
        parent.removeEventListener('mouseleave', onLeave);
        parent.removeEventListener('mousemove',  onMove);
      }
    };
  }, []);

  return (
    <canvas
      ref={mountRef}
      style={{
        position: 'absolute',
        inset: 0,
        width: '100%',
        height: '100%',
        pointerEvents: 'none',
        zIndex: 0,
      }}
    />
  );
}

window.HeroCanvas = HeroCanvas;
