"use client";

import { useEffect, useRef } from "react";

type Particle = {
  x: number;
  y: number;
  vx: number;
  vy: number;
  baseAlpha: number;
};

const ACCENT = [250, 204, 13] as const; // --accent-500
const LINK_DISTANCE = 140;
const POINTER_RADIUS = 220;

/**
 * Particle constellation canvas. Subtle drift; pointer attraction within radius.
 * Particles near pointer tint to accent. Respects prefers-reduced-motion (no drift).
 * Mount as absolute child inside a feature slide.
 */
export function HeroCanvas() {
  const ref = useRef<HTMLCanvasElement>(null);

  useEffect(() => {
    const canvas = ref.current;
    if (!canvas) return;
    const ctx = canvas.getContext("2d");
    if (!ctx) return;

    const reduce =
      typeof window !== "undefined" &&
      window.matchMedia("(prefers-reduced-motion: reduce)").matches;

    let particles: Particle[] = [];
    let rafId = 0;
    const pointer = { x: -1000, y: -1000, active: false };

    const dpr = Math.max(1, Math.min(2, window.devicePixelRatio || 1));

    function resize() {
      if (!canvas || !ctx) return;
      const parent = canvas.parentElement;
      if (!parent) return;
      const { width, height } = parent.getBoundingClientRect();
      canvas.width = width * dpr;
      canvas.height = height * dpr;
      canvas.style.width = `${width}px`;
      canvas.style.height = `${height}px`;
      ctx.setTransform(dpr, 0, 0, dpr, 0, 0);

      const area = width * height;
      const target = Math.min(120, Math.max(50, Math.floor(area / 14000)));
      particles = Array.from({ length: target }, () => ({
        x: Math.random() * width,
        y: Math.random() * height,
        vx: (Math.random() - 0.5) * 0.18,
        vy: (Math.random() - 0.5) * 0.18,
        baseAlpha: 0.25 + Math.random() * 0.45,
      }));
    }

    function step() {
      if (!canvas || !ctx) return;
      const width = canvas.width / dpr;
      const height = canvas.height / dpr;
      ctx.clearRect(0, 0, width, height);

      for (let i = 0; i < particles.length; i++) {
        const p = particles[i];
        if (!reduce) {
          p.x += p.vx;
          p.y += p.vy;
          if (p.x < -10) p.x = width + 10;
          if (p.x > width + 10) p.x = -10;
          if (p.y < -10) p.y = height + 10;
          if (p.y > height + 10) p.y = -10;
        }

        let glow = 0;
        if (pointer.active) {
          const dx = p.x - pointer.x;
          const dy = p.y - pointer.y;
          const d2 = dx * dx + dy * dy;
          if (d2 < POINTER_RADIUS * POINTER_RADIUS) {
            const t = 1 - Math.sqrt(d2) / POINTER_RADIUS;
            glow = t;
            if (!reduce) {
              p.vx += (-dx / POINTER_RADIUS) * 0.0012;
              p.vy += (-dy / POINTER_RADIUS) * 0.0012;
            }
          }
        }

        p.vx *= 0.985;
        p.vy *= 0.985;

        const alpha = p.baseAlpha * 0.35 + glow * 0.85;
        if (glow > 0.02) {
          ctx.fillStyle = `rgba(${ACCENT[0]},${ACCENT[1]},${ACCENT[2]},${alpha})`;
        } else {
          ctx.fillStyle = `rgba(255,255,255,${p.baseAlpha * 0.35})`;
        }
        ctx.beginPath();
        ctx.arc(p.x, p.y, 1.2 + glow * 1.4, 0, Math.PI * 2);
        ctx.fill();
      }

      for (let i = 0; i < particles.length; i++) {
        const a = particles[i];
        for (let j = i + 1; j < particles.length; j++) {
          const b = particles[j];
          const dx = a.x - b.x;
          const dy = a.y - b.y;
          const d2 = dx * dx + dy * dy;
          if (d2 < LINK_DISTANCE * LINK_DISTANCE) {
            const d = Math.sqrt(d2);
            const t = 1 - d / LINK_DISTANCE;
            let pointerBoost = 0;
            if (pointer.active) {
              const mx = (a.x + b.x) / 2;
              const my = (a.y + b.y) / 2;
              const pdx = mx - pointer.x;
              const pdy = my - pointer.y;
              const pd2 = pdx * pdx + pdy * pdy;
              if (pd2 < POINTER_RADIUS * POINTER_RADIUS) {
                pointerBoost = (1 - Math.sqrt(pd2) / POINTER_RADIUS) * 0.6;
              }
            }
            const lineAlpha = t * (0.1 + pointerBoost * 0.45);
            if (pointerBoost > 0.02) {
              ctx.strokeStyle = `rgba(${ACCENT[0]},${ACCENT[1]},${ACCENT[2]},${lineAlpha})`;
            } else {
              ctx.strokeStyle = `rgba(255,255,255,${lineAlpha * 0.55})`;
            }
            ctx.lineWidth = 1;
            ctx.beginPath();
            ctx.moveTo(a.x, a.y);
            ctx.lineTo(b.x, b.y);
            ctx.stroke();
          }
        }
      }

      rafId = requestAnimationFrame(step);
    }

    function onPointerMove(e: PointerEvent) {
      if (!canvas) return;
      const rect = canvas.getBoundingClientRect();
      pointer.x = e.clientX - rect.left;
      pointer.y = e.clientY - rect.top;
      pointer.active = true;
    }
    function onPointerLeave() {
      pointer.active = false;
      pointer.x = -1000;
      pointer.y = -1000;
    }

    resize();
    window.addEventListener("resize", resize);
    window.addEventListener("pointermove", onPointerMove);
    window.addEventListener("pointerleave", onPointerLeave);
    rafId = requestAnimationFrame(step);

    return () => {
      cancelAnimationFrame(rafId);
      window.removeEventListener("resize", resize);
      window.removeEventListener("pointermove", onPointerMove);
      window.removeEventListener("pointerleave", onPointerLeave);
    };
  }, []);

  return (
    <canvas
      ref={ref}
      aria-hidden
      className="pointer-events-none absolute inset-0 z-0"
    />
  );
}
