/* Canvas-based hero particle field. A subtle drifting field of dots
   with a soft gradient orb that breathes. R3F was too heavy to load
   reliably as a CDN module inside an artifact, so this is the fallback —
   it still feels alive and depth-y, never fights the text. */

const ParticleField = ({ className = '', reduced = false }) => {
  const canvasRef = React.useRef(null);
  const rafRef = React.useRef(0);

  React.useEffect(() => {
    if (reduced) return;
    const canvas = canvasRef.current;
    if (!canvas) return;
    const ctx = canvas.getContext('2d');
    let dpr = Math.min(window.devicePixelRatio || 1, 2);
    let w = 0, h = 0;
    const points = [];

    const 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);
    };
    resize();

    const N = Math.min(110, Math.max(60, Math.floor((w * h) / 16000)));
    for (let i = 0; i < N; i++) {
      points.push({
        x: Math.random() * w,
        y: Math.random() * h,
        z: 0.3 + Math.random() * 0.7, // depth → size + opacity
        vx: (Math.random() - 0.5) * 0.18,
        vy: (Math.random() - 0.5) * 0.18,
        hue: Math.random() < 0.5 ? 'sky' : 'fuchsia',
      });
    }

    const onResize = () => {
      resize();
      points.forEach(p => { p.x = Math.min(p.x, w); p.y = Math.min(p.y, h); });
    };
    window.addEventListener('resize', onResize);

    let t = 0;
    const draw = () => {
      t += 0.005;
      ctx.clearRect(0, 0, w, h);

      // breathing gradient orb
      const cx = w * (0.5 + Math.sin(t * 0.6) * 0.08);
      const cy = h * (0.45 + Math.cos(t * 0.5) * 0.05);
      const r = Math.max(w, h) * 0.55;
      const g1 = ctx.createRadialGradient(cx, cy, 0, cx, cy, r);
      g1.addColorStop(0, 'rgba(56,189,248,0.18)');
      g1.addColorStop(0.5, 'rgba(139,92,246,0.10)');
      g1.addColorStop(1, 'rgba(6,8,20,0)');
      ctx.fillStyle = g1;
      ctx.fillRect(0, 0, w, h);

      const cx2 = w * (0.5 + Math.cos(t * 0.4 + 1) * 0.18);
      const cy2 = h * (0.6 + Math.sin(t * 0.45 + 2) * 0.08);
      const g2 = ctx.createRadialGradient(cx2, cy2, 0, cx2, cy2, r * 0.6);
      g2.addColorStop(0, 'rgba(217,70,239,0.16)');
      g2.addColorStop(1, 'rgba(6,8,20,0)');
      ctx.fillStyle = g2;
      ctx.fillRect(0, 0, w, h);

      // particle dots
      for (let i = 0; i < points.length; i++) {
        const p = points[i];
        p.x += p.vx;
        p.y += p.vy;
        if (p.x < -20) p.x = w + 20;
        if (p.x > w + 20) p.x = -20;
        if (p.y < -20) p.y = h + 20;
        if (p.y > h + 20) p.y = -20;

        const size = 0.6 + p.z * 1.6;
        const alpha = 0.18 + p.z * 0.55;
        ctx.beginPath();
        ctx.fillStyle = p.hue === 'sky'
          ? `rgba(180, 220, 255, ${alpha})`
          : `rgba(241, 188, 255, ${alpha})`;
        ctx.arc(p.x, p.y, size, 0, Math.PI * 2);
        ctx.fill();
      }

      // soft connecting filaments (only nearest neighbours, cheap)
      ctx.strokeStyle = 'rgba(180, 200, 240, 0.05)';
      ctx.lineWidth = 0.6;
      for (let i = 0; i < points.length; i++) {
        for (let j = i + 1; j < points.length; j++) {
          const a = points[i], b = points[j];
          const dx = a.x - b.x, dy = a.y - b.y;
          const d2 = dx * dx + dy * dy;
          if (d2 < 110 * 110) {
            ctx.globalAlpha = 1 - d2 / (110 * 110);
            ctx.beginPath();
            ctx.moveTo(a.x, a.y);
            ctx.lineTo(b.x, b.y);
            ctx.stroke();
          }
        }
      }
      ctx.globalAlpha = 1;

      rafRef.current = requestAnimationFrame(draw);
    };
    draw();

    return () => {
      cancelAnimationFrame(rafRef.current);
      window.removeEventListener('resize', onResize);
    };
  }, [reduced]);

  return (
    <canvas
      ref={canvasRef}
      aria-hidden="true"
      className={'absolute inset-0 w-full h-full ' + className}
    />
  );
};

window.ParticleField = ParticleField;
