// Floating particle background with mouse interaction.
// Canvas-based, GPU-friendly, low particle count for performance.

function Particles({ count = 60, color = '#5dd4c4', lineAlpha = 0.2, particleAlphaMin = 0.15, particleAlphaMax = 0.5 }) {
  const canvasRef = React.useRef(null);
  const animRef = React.useRef(0);
  const mouseRef = React.useRef({ x: -9999, y: -9999, active: false });
  const particlesRef = React.useRef([]);

  // Skip entirely on small screens (battery cost, invisible at that size)
  // and for users who prefer reduced motion.
  const [enabled, setEnabled] = React.useState(() =>
    !(window.matchMedia('(max-width: 820px)').matches ||
      window.matchMedia('(prefers-reduced-motion: reduce)').matches)
  );
  React.useEffect(() => {
    const mqSmall = window.matchMedia('(max-width: 820px)');
    const mqMotion = window.matchMedia('(prefers-reduced-motion: reduce)');
    const update = () => setEnabled(!(mqSmall.matches || mqMotion.matches));
    mqSmall.addEventListener('change', update);
    mqMotion.addEventListener('change', update);
    return () => {
      mqSmall.removeEventListener('change', update);
      mqMotion.removeEventListener('change', update);
    };
  }, []);

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

    // Size to viewport with DPR
    const resize = () => {
      const dpr = window.devicePixelRatio || 1;
      canvas.width = window.innerWidth * dpr;
      canvas.height = window.innerHeight * dpr;
      canvas.style.width = window.innerWidth + 'px';
      canvas.style.height = window.innerHeight + 'px';
      ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
    };
    resize();
    window.addEventListener('resize', resize);

    // Seed particles
    const W = window.innerWidth;
    const H = window.innerHeight;
    particlesRef.current = Array.from({ length: count }, () => ({
      x: Math.random() * W,
      y: Math.random() * H,
      vx: (Math.random() - 0.5) * 0.15,
      vy: (Math.random() - 0.5) * 0.15,
      r: 0.6 + Math.random() * 1.4,
      a: particleAlphaMin + Math.random() * (particleAlphaMax - particleAlphaMin),
    }));

    // Mouse tracking
    const onMove = (e) => {
      mouseRef.current.x = e.clientX;
      mouseRef.current.y = e.clientY;
      mouseRef.current.active = true;
    };
    const onLeave = () => {
      mouseRef.current.active = false;
    };
    window.addEventListener('mousemove', onMove);
    window.addEventListener('mouseleave', onLeave);

    const tick = () => {
      const w = window.innerWidth;
      const h = window.innerHeight;
      ctx.clearRect(0, 0, w, h);

      const m = mouseRef.current;
      const mouseRadius = 140;
      const repelStrength = 0.6;

      // Parse color rgba
      ctx.fillStyle = color;
      ctx.strokeStyle = color;

      const particles = particlesRef.current;
      for (let i = 0; i < particles.length; i++) {
        const p = particles[i];

        // Mouse repulsion
        if (m.active) {
          const dx = p.x - m.x;
          const dy = p.y - m.y;
          const dist = Math.sqrt(dx * dx + dy * dy);
          if (dist < mouseRadius && dist > 0) {
            const force = (1 - dist / mouseRadius) * repelStrength;
            p.vx += (dx / dist) * force;
            p.vy += (dy / dist) * force;
          }
        }

        // Damping toward gentle drift
        p.vx *= 0.96;
        p.vy *= 0.96;
        // Re-add tiny drift if too slow
        if (Math.abs(p.vx) < 0.05) p.vx += (Math.random() - 0.5) * 0.03;
        if (Math.abs(p.vy) < 0.05) p.vy += (Math.random() - 0.5) * 0.03;

        p.x += p.vx;
        p.y += p.vy;

        // Wrap around
        if (p.x < -10) p.x = w + 10;
        if (p.x > w + 10) p.x = -10;
        if (p.y < -10) p.y = h + 10;
        if (p.y > h + 10) p.y = -10;

        // Draw particle
        ctx.globalAlpha = p.a;
        ctx.beginPath();
        ctx.arc(p.x, p.y, p.r, 0, Math.PI * 2);
        ctx.fill();
      }

      // Draw connecting lines for nearby particles
      ctx.globalAlpha = 0.08;
      ctx.lineWidth = 0.5;
      const connectDist = 90;
      for (let i = 0; i < particles.length; i++) {
        for (let j = i + 1; j < particles.length; j++) {
          const a = particles[i], b = particles[j];
          const dx = a.x - b.x, dy = a.y - b.y;
          const d2 = dx * dx + dy * dy;
          if (d2 < connectDist * connectDist) {
            const alpha = (1 - Math.sqrt(d2) / connectDist) * lineAlpha;
            ctx.globalAlpha = alpha;
            ctx.beginPath();
            ctx.moveTo(a.x, a.y);
            ctx.lineTo(b.x, b.y);
            ctx.stroke();
          }
        }
      }

      animRef.current = requestAnimationFrame(tick);
    };
    animRef.current = requestAnimationFrame(tick);

    return () => {
      cancelAnimationFrame(animRef.current);
      window.removeEventListener('resize', resize);
      window.removeEventListener('mousemove', onMove);
      window.removeEventListener('mouseleave', onLeave);
    };
  }, [enabled, count, color, lineAlpha, particleAlphaMin, particleAlphaMax]);

  if (!enabled) return null;

  return (
    <canvas
      ref={canvasRef}
      className="particles-bg"
      style={{
        position: 'fixed',
        top: 0,
        left: 0,
        width: '100%',
        height: '100%',
        pointerEvents: 'none',
        zIndex: 1,
      }}
    />
  );
}

window.Particles = Particles;
