'use client';

import { useEffect, useRef } from 'react';

/**
 * Lightweight 2D hex-grid particle network.
 * - Nodes drift slowly, repelled by the cursor.
 * - Edges drawn between nearby nodes form a connection mesh.
 * - Pauses when the tab is hidden or the section scrolls offscreen.
 */
export function ParticleCanvas() {
  const ref = useRef<HTMLCanvasElement>(null);

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

    const DPR = Math.min(window.devicePixelRatio || 1, 2);
    let width = 0;
    let height = 0;
    let raf = 0;
    let running = true;
    const mouse = { x: -9999, y: -9999, active: false };

    type Node = { x: number; y: number; vx: number; vy: number; r: number; hue: number };
    let nodes: Node[] = [];

    const COLORS = [
      { r: 56, g: 189, b: 248 }, // electric
      { r: 129, g: 140, b: 248 }, // violet
      { r: 232, g: 121, b: 249 }, // magenta
      { r: 34, g: 211, b: 238 }, // cyan
    ];

    const seed = () => {
      const area = width * height;
      const density = window.matchMedia('(max-width: 640px)').matches ? 14000 : 9000;
      const count = Math.min(140, Math.max(40, Math.floor(area / density)));
      nodes = Array.from({ length: count }, () => ({
        x: Math.random() * width,
        y: Math.random() * height,
        vx: (Math.random() - 0.5) * 0.18,
        vy: (Math.random() - 0.5) * 0.18,
        r: 0.8 + Math.random() * 1.6,
        hue: Math.floor(Math.random() * COLORS.length),
      }));
    };

    const resize = () => {
      const rect = canvas.getBoundingClientRect();
      width = rect.width;
      height = rect.height;
      canvas.width = Math.floor(width * DPR);
      canvas.height = Math.floor(height * DPR);
      ctx.setTransform(DPR, 0, 0, DPR, 0, 0);
      seed();
    };

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

    const onVisibility = () => {
      running = !document.hidden;
      if (running && !raf) raf = requestAnimationFrame(tick);
    };

    const tick = () => {
      raf = 0;
      if (!running) return;

      ctx.clearRect(0, 0, width, height);

      // Drift + cursor repel
      for (const n of nodes) {
        n.x += n.vx;
        n.y += n.vy;

        // Wrap around edges
        if (n.x < -10) n.x = width + 10;
        else if (n.x > width + 10) n.x = -10;
        if (n.y < -10) n.y = height + 10;
        else if (n.y > height + 10) n.y = -10;

        if (mouse.active) {
          const dx = n.x - mouse.x;
          const dy = n.y - mouse.y;
          const d2 = dx * dx + dy * dy;
          const R = 140;
          if (d2 < R * R && d2 > 0.01) {
            const d = Math.sqrt(d2);
            const force = (R - d) / R;
            n.x += (dx / d) * force * 2.4;
            n.y += (dy / d) * force * 2.4;
          }
        }
      }

      // Edges
      const LINK_DIST = 130;
      for (let i = 0; i < nodes.length; i++) {
        const a = nodes[i];
        for (let j = i + 1; j < nodes.length; j++) {
          const b = nodes[j];
          const dx = a.x - b.x;
          const dy = a.y - b.y;
          const d2 = dx * dx + dy * dy;
          if (d2 < LINK_DIST * LINK_DIST) {
            const d = Math.sqrt(d2);
            const alpha = (1 - d / LINK_DIST) * 0.35;
            const ca = COLORS[a.hue];
            const cb = COLORS[b.hue];
            const grad = ctx.createLinearGradient(a.x, a.y, b.x, b.y);
            grad.addColorStop(0, `rgba(${ca.r},${ca.g},${ca.b},${alpha})`);
            grad.addColorStop(1, `rgba(${cb.r},${cb.g},${cb.b},${alpha})`);
            ctx.strokeStyle = grad;
            ctx.lineWidth = 0.7;
            ctx.beginPath();
            ctx.moveTo(a.x, a.y);
            ctx.lineTo(b.x, b.y);
            ctx.stroke();
          }
        }
      }

      // Nodes
      for (const n of nodes) {
        const c = COLORS[n.hue];
        ctx.beginPath();
        ctx.fillStyle = `rgba(${c.r},${c.g},${c.b},0.85)`;
        ctx.shadowBlur = 8;
        ctx.shadowColor = `rgba(${c.r},${c.g},${c.b},0.55)`;
        ctx.arc(n.x, n.y, n.r, 0, Math.PI * 2);
        ctx.fill();
      }
      ctx.shadowBlur = 0;

      raf = requestAnimationFrame(tick);
    };

    resize();
    raf = requestAnimationFrame(tick);
    window.addEventListener('resize', resize);
    window.addEventListener('mousemove', onMove);
    window.addEventListener('mouseleave', onLeave);
    document.addEventListener('visibilitychange', onVisibility);

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

  return (
    <canvas
      ref={ref}
      aria-hidden
      className="absolute inset-0 h-full w-full"
      style={{ background: 'transparent' }}
    />
  );
}
