import { useEffect, useRef, useCallback } from 'react';
import { useResponsive, getResponsiveParticleDensity } from '../../hooks/use-responsive';

interface NeuralNetworkProps {
  density?: number;
  className?: string;
  showDataFlow?: boolean;
}

interface Neuron {
  x: number;
  y: number;
  vx: number;
  vy: number;
  size: number;
  opacity: number;
  pulsePhase: number;
  connections: number[];
  isActive: boolean;
  activationLevel: number;
}

interface DataPacket {
  fromIndex: number;
  toIndex: number;
  progress: number;
  x: number;
  y: number;
  opacity: number;
  size: number;
}

export default function NeuralNetwork({
  density = 25,
  className = "",
  showDataFlow = true
}: NeuralNetworkProps) {
  const responsive = useResponsive();
  const containerRef = useRef<HTMLDivElement>(null);
  const canvasRef = useRef<HTMLCanvasElement>(null);
  const animationRef = useRef<number | undefined>(undefined);
  const neuronsRef = useRef<Neuron[]>([]);
  const dataPacketsRef = useRef<DataPacket[]>([]);

  const createNeurons = useCallback((width: number, height: number) => {
    const neurons: Neuron[] = [];
    const responsiveDensity = getResponsiveParticleDensity(density, responsive);

    for (let i = 0; i < responsiveDensity; i++) {
      neurons.push({
        x: Math.random() * width,
        y: Math.random() * height,
        vx: (Math.random() - 0.5) * 0.3,
        vy: (Math.random() - 0.5) * 0.3,
        size: Math.random() * 4 + 2,
        opacity: Math.random() * 0.6 + 0.4,
        pulsePhase: Math.random() * Math.PI * 2,
        connections: [],
        isActive: false,
        activationLevel: 0
      });
    }

    // Crear conexiones entre neuronas cercanas
    neurons.forEach((neuron, i) => {
      neuron.connections = [];
      neurons.forEach((otherNeuron, j) => {
        if (i !== j) {
          const dx = neuron.x - otherNeuron.x;
          const dy = neuron.y - otherNeuron.y;
          const distance = Math.sqrt(dx * dx + dy * dy);

          // Conectar neuronas que estén relativamente cerca
          if (distance < 150 && neuron.connections.length < 3) {
            neuron.connections.push(j);
          }
        }
      });
    });

    return neurons;
  }, [density, responsive]);

  const createDataPacket = useCallback((fromIndex: number, toIndex: number) => {
    return {
      fromIndex,
      toIndex,
      progress: 0,
      x: neuronsRef.current[fromIndex].x,
      y: neuronsRef.current[fromIndex].y,
      opacity: 1,
      size: 2
    };
  }, []);

  const updateNeurons = useCallback((neurons: Neuron[], width: number, height: number) => {
    neurons.forEach((neuron, i) => {
      // Actualizar posición con movimiento suave
      neuron.x += neuron.vx;
      neuron.y += neuron.vy;

      // Rebote en bordes con amortiguación
      if (neuron.x < 0 || neuron.x > width) {
        neuron.vx *= -0.8;
        neuron.x = Math.max(0, Math.min(width, neuron.x));
      }
      if (neuron.y < 0 || neuron.y > height) {
        neuron.vy *= -0.8;
        neuron.y = Math.max(0, Math.min(height, neuron.y));
      }

      // Actualizar fase de pulso
      neuron.pulsePhase += 0.02;

      // Activación aleatoria de neuronas
      if (Math.random() < 0.005) {
        neuron.isActive = true;
        neuron.activationLevel = 1;

        // Crear paquetes de datos hacia neuronas conectadas
        if (showDataFlow && neuron.connections.length > 0) {
          const targetIndex = neuron.connections[Math.floor(Math.random() * neuron.connections.length)];
          dataPacketsRef.current.push(createDataPacket(i, targetIndex));
        }
      }

      // Decrementar activación
      if (neuron.isActive) {
        neuron.activationLevel -= 0.02;
        if (neuron.activationLevel <= 0) {
          neuron.isActive = false;
          neuron.activationLevel = 0;
        }
      }
    });
  }, [showDataFlow, createDataPacket]);

  const updateDataPackets = useCallback((dataPackets: DataPacket[], neurons: Neuron[]) => {
    return dataPackets.filter(packet => {
      const fromNeuron = neurons[packet.fromIndex];
      const toNeuron = neurons[packet.toIndex];

      if (!fromNeuron || !toNeuron) return false;

      // Actualizar progreso
      packet.progress += 0.02;

      // Interpolar posición
      packet.x = fromNeuron.x + (toNeuron.x - fromNeuron.x) * packet.progress;
      packet.y = fromNeuron.y + (toNeuron.y - fromNeuron.y) * packet.progress;

      // Actualizar opacidad
      packet.opacity = 1 - packet.progress;

      // Activar neurona destino cuando llegue el paquete
      if (packet.progress >= 0.9 && !toNeuron.isActive) {
        toNeuron.isActive = true;
        toNeuron.activationLevel = 0.8;
      }

      // Eliminar paquete cuando llegue al destino
      return packet.progress < 1;
    });
  }, []);

  const drawNeurons = useCallback((ctx: CanvasRenderingContext2D, neurons: Neuron[]) => {
    const isDark = document.documentElement.classList.contains('dark');

    neurons.forEach(neuron => {
      // Calcular tamaño con pulso
      const pulse = Math.sin(neuron.pulsePhase) * 0.3 + 1;
      const currentSize = neuron.size * pulse;

      // Color base con activación
      let opacity = neuron.opacity;
      let color = isDark ? '59, 130, 246' : '37, 99, 235'; // blue

      if (neuron.isActive) {
        opacity = Math.min(1, neuron.opacity + neuron.activationLevel * 0.6);
        color = isDark ? '34, 197, 94' : '16, 185, 129'; // emerald cuando está activa

        // Halo de activación
        ctx.beginPath();
        ctx.arc(neuron.x, neuron.y, currentSize * 3, 0, Math.PI * 2);
        ctx.fillStyle = `rgba(${color}, ${neuron.activationLevel * 0.1})`;
        ctx.fill();
      }

      // Núcleo de la neurona
      ctx.beginPath();
      ctx.arc(neuron.x, neuron.y, currentSize, 0, Math.PI * 2);
      ctx.fillStyle = `rgba(${color}, ${opacity})`;
      ctx.fill();

      // Borde brillante
      ctx.beginPath();
      ctx.arc(neuron.x, neuron.y, currentSize, 0, Math.PI * 2);
      ctx.strokeStyle = `rgba(${color}, ${opacity * 0.8})`;
      ctx.lineWidth = 1;
      ctx.stroke();
    });
  }, []);

  const drawConnections = useCallback((ctx: CanvasRenderingContext2D, neurons: Neuron[]) => {
    const isDark = document.documentElement.classList.contains('dark');

    neurons.forEach((neuron) => {
      neuron.connections.forEach(connectionIndex => {
        const targetNeuron = neurons[connectionIndex];
        if (!targetNeuron) return;

        const dx = targetNeuron.x - neuron.x;
        const dy = targetNeuron.y - neuron.y;
        const distance = Math.sqrt(dx * dx + dy * dy);

        // Solo dibujar conexiones relativamente cortas
        if (distance > 150) return;

        // Opacidad basada en distancia y activación
        let opacity = Math.max(0.1, 0.3 - distance / 500);
        if (neuron.isActive || targetNeuron.isActive) {
          opacity = Math.min(0.6, opacity + 0.3);
        }

        // Color de la conexión
        const connectionColor = isDark ? '148, 163, 184' : '100, 116, 139'; // slate

        ctx.beginPath();
        ctx.moveTo(neuron.x, neuron.y);
        ctx.lineTo(targetNeuron.x, targetNeuron.y);
        ctx.strokeStyle = `rgba(${connectionColor}, ${opacity})`;
        ctx.lineWidth = neuron.isActive || targetNeuron.isActive ? 2 : 1;
        ctx.stroke();
      });
    });
  }, []);

  const drawDataPackets = useCallback((ctx: CanvasRenderingContext2D, dataPackets: DataPacket[]) => {
    const isDark = document.documentElement.classList.contains('dark');

    dataPackets.forEach(packet => {
      // Partícula de datos con efecto brillante
      const glowSize = packet.size * 2;

      // Halo
      ctx.beginPath();
      ctx.arc(packet.x, packet.y, glowSize, 0, Math.PI * 2);
      const glowColor = isDark ? '34, 197, 94' : '16, 185, 129'; // emerald
      ctx.fillStyle = `rgba(${glowColor}, ${packet.opacity * 0.3})`;
      ctx.fill();

      // Núcleo
      ctx.beginPath();
      ctx.arc(packet.x, packet.y, packet.size, 0, Math.PI * 2);
      ctx.fillStyle = `rgba(${glowColor}, ${packet.opacity})`;
      ctx.fill();
    });
  }, []);

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

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

    // Clear canvas
    ctx.clearRect(0, 0, canvas.width, canvas.height);

    // Update neurons
    updateNeurons(neuronsRef.current, canvas.width, canvas.height);

    // Update data packets
    dataPacketsRef.current = updateDataPackets(dataPacketsRef.current, neuronsRef.current);

    // Draw connections first (background)
    drawConnections(ctx, neuronsRef.current);

    // Draw neurons
    drawNeurons(ctx, neuronsRef.current);

    // Draw data packets on top
    if (showDataFlow) {
      drawDataPackets(ctx, dataPacketsRef.current);
    }

    animationRef.current = requestAnimationFrame(animate);
  }, [updateNeurons, updateDataPackets, drawConnections, drawNeurons, drawDataPackets, showDataFlow]);

  useEffect(() => {
    const canvas = canvasRef.current;
    const container = containerRef.current;
    if (!canvas || !container) return;

    // Set canvas size
    const resizeCanvas = () => {
      canvas.width = container.offsetWidth;
      canvas.height = container.offsetHeight;

      // Recreate neurons with new dimensions
      neuronsRef.current = createNeurons(canvas.width, canvas.height);
    };

    resizeCanvas();
    window.addEventListener('resize', resizeCanvas);

    // Start animation
    animationRef.current = requestAnimationFrame(animate);

    return () => {
      window.removeEventListener('resize', resizeCanvas);
      if (animationRef.current) {
        cancelAnimationFrame(animationRef.current);
      }
    };
  }, [createNeurons, animate]);

  return (
    <div
      ref={containerRef}
      className={`absolute inset-0 overflow-hidden pointer-events-none ${className}`}
    >
      <canvas
        ref={canvasRef}
        className="w-full h-full"
        style={{ background: 'transparent' }}
      />
    </div>
  );
}
