'use client';

import { useEffect, useRef, useState, useCallback } from 'react';
import { motion, useMotionValue } from 'framer-motion';

interface Particle {
  x: number;
  y: number;
  vx: number;
  vy: number;
  size: number;
  opacity: number;
}

interface ParticleGalaxyProps {
  particleCount?: number;
  connectionDistance?: number;
  mouseRadius?: number;
  particleColor?: string;
  lineColor?: string;
  className?: string;
}

export function ParticleGalaxy({
  particleCount = 100,
  connectionDistance = 150,
  mouseRadius = 150,
  particleColor = '196, 30, 58',
  lineColor = '196, 30, 58',
  className = ''
}: ParticleGalaxyProps) {
  const canvasRef = useRef<HTMLCanvasElement>(null);
  const particlesRef = useRef<Particle[]>([]);
  const animationRef = useRef<number | undefined>(undefined);
  const [isVisible, setIsVisible] = useState(false);

  const mouseX = useMotionValue(0);
  const mouseY = useMotionValue(0);
  const mouseInCanvas = useMotionValue(false);

  const createParticle = useCallback((width: number, height: number): Particle => {
    return {
      x: Math.random() * width,
      y: Math.random() * height,
      vx: (Math.random() - 0.5) * 0.8,
      vy: (Math.random() - 0.5) * 0.8,
      size: Math.random() * 2 + 1,
      opacity: Math.random() * 0.5 + 0.2
    };
  }, []);

  const initParticles = useCallback((width: number, height: number) => {
    particlesRef.current = Array.from({ length: particleCount }, () => 
      createParticle(width, height)
    );
  }, [particleCount, createParticle]);

  const drawParticles = useCallback((ctx: CanvasRenderingContext2D, width: number, height: number) => {
    const mx = mouseX.get();
    const my = mouseY.get();
    const inCanvas = mouseInCanvas.get();

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

    const particles = particlesRef.current;

    particles.forEach((particle, i) => {
      let { x, y, vx, vy, size, opacity } = particle;

      if (inCanvas) {
        const dx = x - mx;
        const dy = y - my;
        const distance = Math.sqrt(dx * dx + dy * dy);

        if (distance < mouseRadius) {
          const force = (mouseRadius - distance) / mouseRadius;
          const angle = Math.atan2(dy, dx);
          vx += Math.cos(angle) * force * 0.5;
          vy += Math.sin(angle) * force * 0.5;
        }
      }

      x += vx;
      y += vy;

      if (x < 0 || x > width) {vx *= -1;}
      if (y < 0 || y > height) {vy *= -1;}

      x = Math.max(0, Math.min(width, x));
      y = Math.max(0, Math.min(height, y));

      vx *= 0.99;
      vy *= 0.99;

      const speed = Math.sqrt(vx * vx + vy * vy);
      if (speed < 0.1) {
        vx += (Math.random() - 0.5) * 0.1;
        vy += (Math.random() - 0.5) * 0.1;
      }

      particlesRef.current[i] = { x, y, vx, vy, size, opacity };

      ctx.beginPath();
      ctx.arc(x, y, size, 0, Math.PI * 2);
      ctx.fillStyle = `rgba(${particleColor}, ${opacity})`;
      ctx.fill();
    });

    for (let i = 0; i < particles.length; i++) {
      for (let j = i + 1; j < particles.length; j++) {
        const p1 = particles[i];
        const p2 = particles[j];
        if (!p1 || !p2) {continue;}
        
        const dx = p1.x - p2.x;
        const dy = p1.y - p2.y;
        const distance = Math.sqrt(dx * dx + dy * dy);

        if (distance < connectionDistance) {
          const opacity = (1 - distance / connectionDistance) * 0.3;
          ctx.beginPath();
          ctx.moveTo(p1.x, p1.y);
          ctx.lineTo(p2.x, p2.y);
          ctx.strokeStyle = `rgba(${lineColor}, ${opacity})`;
          ctx.lineWidth = 0.5;
          ctx.stroke();
        }
      }
    }
  }, [mouseX, mouseY, mouseInCanvas, mouseRadius, particleColor, lineColor, connectionDistance]);

  const animate = useCallback(() => {
    const canvas = canvasRef.current;
    if (!canvas) {return;}

    const ctx = canvas.getContext('2d');
    if (!ctx) {return;}

    drawParticles(ctx, canvas.width, canvas.height);
    animationRef.current = requestAnimationFrame(animate);
  }, [drawParticles]);

  const handleResize = useCallback(() => {
    const canvas = canvasRef.current;
    if (!canvas) {return;}

    const container = canvas.parentElement;
    if (!container) {return;}

    canvas.width = container.clientWidth;
    canvas.height = container.clientHeight;

    initParticles(canvas.width, canvas.height);
  }, [initParticles]);

  useEffect(() => {
    const canvas = canvasRef.current;
    if (!canvas) {return;}

    const container = canvas.parentElement;
    if (!container) {return;}

    canvas.width = container.clientWidth;
    canvas.height = container.clientHeight;

    initParticles(canvas.width, canvas.height);

    const observer = new IntersectionObserver(
      (entries) => {
        entries.forEach((entry) => {
          setIsVisible(entry.isIntersecting);
        });
      },
      { threshold: 0.1 }
    );

    observer.observe(canvas);

    if (isVisible) {
      animate();
    }

    const handleResizeWithDebounce = () => {
      setTimeout(handleResize, 250);
    };

    window.addEventListener('resize', handleResizeWithDebounce);

    return () => {
      observer.disconnect();
      window.removeEventListener('resize', handleResizeWithDebounce);
      if (animationRef.current) {
        cancelAnimationFrame(animationRef.current);
      }
    };
  }, [isVisible, animate, initParticles, handleResize]);

  useEffect(() => {
    if (isVisible) {
      animate();
    } else if (animationRef.current) {
      cancelAnimationFrame(animationRef.current);
    }
  }, [isVisible, animate]);

  return (
    <motion.div
      className={`absolute inset-0 pointer-events-none ${className}`}
      initial={{ opacity: 0 }}
      animate={{ opacity: isVisible ? 1 : 0 }}
      transition={{ duration: 0.5 }}
    >
      <canvas
        ref={canvasRef}
        className="w-full h-full"
        onMouseMove={(e) => {
          mouseX.set(e.clientX);
          mouseY.set(e.clientY);
          mouseInCanvas.set(true);
        }}
        onMouseLeave={() => {
          mouseInCanvas.set(false);
        }}
      />
    </motion.div>
  );
}

export default ParticleGalaxy;