import React, { useRef, useEffect, useState } from 'react';
import { Box, IconButton, Tooltip } from '@mui/material';
import { Audiotrack } from '@mui/icons-material';

/**
 * AudioVisualizer Component
 * Provides 10 different audio visualizations for radio playback
 */
const AudioVisualizer = ({ audioElement, isPlaying, visualizerType = 0 }) => {
  const canvasRef = useRef(null);
  const animationRef = useRef(null);
  const audioContextRef = useRef(null);
  const analyserRef = useRef(null);
  const dataArrayRef = useRef(null);
  const sourceRef = useRef(null);
  const connectedElementRef = useRef(null);

  useEffect(() => {
    console.log('[AudioVisualizer] Props:', { audioElement, isPlaying, visualizerType });
    
    if (!audioElement || !isPlaying) {
      console.log('[AudioVisualizer] Not rendering - no audio element or not playing');
      if (animationRef.current) {
        cancelAnimationFrame(animationRef.current);
      }
      // Clear canvas
      const canvas = canvasRef.current;
      if (canvas) {
        const ctx = canvas.getContext('2d');
        ctx.clearRect(0, 0, canvas.width, canvas.height);
      }
      return;
    }

    const canvas = canvasRef.current;
    if (!canvas) {
      console.log('[AudioVisualizer] No canvas element');
      return;
    }

    const ctx = canvas.getContext('2d');
    
    // Set canvas size
    const updateCanvasSize = () => {
      const rect = canvas.getBoundingClientRect();
      canvas.width = rect.width;
      canvas.height = rect.height;
    };
    updateCanvasSize();

    // Initialize Web Audio API (only once per audio element)
    if (!audioContextRef.current) {
      try {
        const AudioContext = window.AudioContext || window.webkitAudioContext;
        audioContextRef.current = new AudioContext();
        analyserRef.current = audioContextRef.current.createAnalyser();
        analyserRef.current.fftSize = 128; // Smaller for better performance
        analyserRef.current.smoothingTimeConstant = 0.8;
        
        const bufferLength = analyserRef.current.frequencyBinCount;
        dataArrayRef.current = new Uint8Array(bufferLength);
      } catch (error) {
        console.error('[AudioVisualizer] Error initializing audio context:', error);
        return;
      }
    }

    // Create media source only once per audio element
    // Check if this is the same element we already connected
    const needsNewSource = !sourceRef.current || connectedElementRef.current !== audioElement;
    
    if (needsNewSource && audioContextRef.current) {
      // Clean up old source if switching elements
      if (sourceRef.current && connectedElementRef.current !== audioElement) {
        try {
          sourceRef.current.disconnect();
          sourceRef.current = null;
          connectedElementRef.current = null;
        } catch (e) {
          // Ignore disconnect errors
        }
      }
      
      try {
        console.log('[AudioVisualizer] Creating media element source');
        sourceRef.current = audioContextRef.current.createMediaElementSource(audioElement);
        sourceRef.current.connect(analyserRef.current);
        analyserRef.current.connect(audioContextRef.current.destination);
        connectedElementRef.current = audioElement;
        console.log('[AudioVisualizer] Audio context initialized successfully');
      } catch (error) {
        // If element is already connected, it means we already set it up
        console.log('[AudioVisualizer] Element already connected, reusing existing connection');
        // Don't return, continue with existing setup if available
        if (!analyserRef.current || !audioContextRef.current) {
          return;
        }
      }
    }

    // Resume audio context if suspended
    if (audioContextRef.current.state === 'suspended') {
      audioContextRef.current.resume();
    }

    const analyser = analyserRef.current;
    const dataArray = dataArrayRef.current;
    const bufferLength = analyser.frequencyBinCount;

    // Visualization functions
    const visualizers = [
      // 0: Classic Bars
      () => {
        analyser.getByteFrequencyData(dataArray);
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        
        const barWidth = (canvas.width / bufferLength) * 2.5;
        let barHeight;
        let x = 0;

        for (let i = 0; i < bufferLength; i++) {
          barHeight = (dataArray[i] / 255) * canvas.height * 0.8;
          
          const hue = (i / bufferLength) * 360;
          ctx.fillStyle = `hsl(${hue}, 70%, 50%)`;
          ctx.fillRect(x, canvas.height - barHeight, barWidth, barHeight);
          
          x += barWidth + 1;
        }
      },

      // 1: Circular Spectrum
      () => {
        analyser.getByteFrequencyData(dataArray);
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        
        const centerX = canvas.width / 2;
        const centerY = canvas.height / 2;
        const radius = Math.min(centerX, centerY) * 0.6;

        for (let i = 0; i < bufferLength; i++) {
          const angle = (i / bufferLength) * Math.PI * 2;
          const barHeight = (dataArray[i] / 255) * radius * 0.8;
          
          const x1 = centerX + Math.cos(angle) * radius;
          const y1 = centerY + Math.sin(angle) * radius;
          const x2 = centerX + Math.cos(angle) * (radius + barHeight);
          const y2 = centerY + Math.sin(angle) * (radius + barHeight);
          
          const hue = (i / bufferLength) * 360;
          ctx.strokeStyle = `hsl(${hue}, 70%, 50%)`;
          ctx.lineWidth = 3;
          ctx.beginPath();
          ctx.moveTo(x1, y1);
          ctx.lineTo(x2, y2);
          ctx.stroke();
        }
      },

      // 2: Waveform
      () => {
        analyser.getByteTimeDomainData(dataArray);
        ctx.fillStyle = 'rgba(0, 0, 0, 0.1)';
        ctx.fillRect(0, 0, canvas.width, canvas.height);
        
        ctx.lineWidth = 2;
        ctx.strokeStyle = '#a855f7';
        ctx.beginPath();

        const sliceWidth = canvas.width / bufferLength;
        let x = 0;

        for (let i = 0; i < bufferLength; i++) {
          const v = dataArray[i] / 128.0;
          const y = (v * canvas.height) / 2;

          if (i === 0) {
            ctx.moveTo(x, y);
          } else {
            ctx.lineTo(x, y);
          }

          x += sliceWidth;
        }

        ctx.lineTo(canvas.width, canvas.height / 2);
        ctx.stroke();
      },

      // 3: Symmetric Bars
      () => {
        analyser.getByteFrequencyData(dataArray);
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        
        const barWidth = (canvas.width / bufferLength) * 2.5;
        let x = 0;

        for (let i = 0; i < bufferLength; i++) {
          const barHeight = (dataArray[i] / 255) * canvas.height * 0.4;
          
          const hue = (i / bufferLength) * 360;
          ctx.fillStyle = `hsl(${hue}, 70%, 50%)`;
          
          // Top bars
          ctx.fillRect(x, canvas.height / 2 - barHeight, barWidth, barHeight);
          // Bottom bars (mirrored)
          ctx.fillRect(x, canvas.height / 2, barWidth, barHeight);
          
          x += barWidth + 1;
        }
      },

      // 4: Particles
      () => {
        analyser.getByteFrequencyData(dataArray);
        ctx.fillStyle = 'rgba(0, 0, 0, 0.05)';
        ctx.fillRect(0, 0, canvas.width, canvas.height);
        
        for (let i = 0; i < bufferLength; i += 2) {
          const value = dataArray[i];
          if (value > 100) {
            const x = (i / bufferLength) * canvas.width;
            const y = Math.random() * canvas.height;
            const size = (value / 255) * 5;
            
            const hue = (i / bufferLength) * 360;
            ctx.fillStyle = `hsla(${hue}, 70%, 50%, 0.8)`;
            ctx.beginPath();
            ctx.arc(x, y, size, 0, Math.PI * 2);
            ctx.fill();
          }
        }
      },

      // 5: Frequency Rings
      () => {
        analyser.getByteFrequencyData(dataArray);
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        
        const centerX = canvas.width / 2;
        const centerY = canvas.height / 2;
        const maxRadius = Math.min(centerX, centerY) * 0.9;

        for (let i = 0; i < bufferLength; i += 4) {
          const value = dataArray[i];
          const radius = (value / 255) * maxRadius;
          
          const hue = (i / bufferLength) * 360;
          ctx.strokeStyle = `hsla(${hue}, 70%, 50%, 0.5)`;
          ctx.lineWidth = 2;
          ctx.beginPath();
          ctx.arc(centerX, centerY, radius, 0, Math.PI * 2);
          ctx.stroke();
        }
      },

      // 6: Line Spectrum
      () => {
        analyser.getByteFrequencyData(dataArray);
        ctx.fillStyle = 'rgba(0, 0, 0, 0.2)';
        ctx.fillRect(0, 0, canvas.width, canvas.height);
        
        ctx.lineWidth = 2;
        ctx.beginPath();

        for (let i = 0; i < bufferLength; i++) {
          const x = (i / bufferLength) * canvas.width;
          const y = canvas.height - (dataArray[i] / 255) * canvas.height;
          
          if (i === 0) {
            ctx.moveTo(x, y);
          } else {
            ctx.lineTo(x, y);
          }
        }

        const gradient = ctx.createLinearGradient(0, 0, canvas.width, 0);
        gradient.addColorStop(0, '#a855f7');
        gradient.addColorStop(0.5, '#3b82f6');
        gradient.addColorStop(1, '#10b981');
        ctx.strokeStyle = gradient;
        ctx.stroke();
      },

      // 7: Radial Bars
      () => {
        analyser.getByteFrequencyData(dataArray);
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        
        const centerX = canvas.width / 2;
        const centerY = canvas.height / 2;
        const baseRadius = Math.min(centerX, centerY) * 0.3;

        for (let i = 0; i < bufferLength; i++) {
          const angle = (i / bufferLength) * Math.PI * 2;
          const barHeight = (dataArray[i] / 255) * baseRadius;
          
          const innerX = centerX + Math.cos(angle) * baseRadius;
          const innerY = centerY + Math.sin(angle) * baseRadius;
          const outerX = centerX + Math.cos(angle) * (baseRadius + barHeight);
          const outerY = centerY + Math.sin(angle) * (baseRadius + barHeight);
          
          const gradient = ctx.createLinearGradient(innerX, innerY, outerX, outerY);
          gradient.addColorStop(0, '#a855f7');
          gradient.addColorStop(1, '#3b82f6');
          ctx.strokeStyle = gradient;
          ctx.lineWidth = 5;
          ctx.beginPath();
          ctx.moveTo(innerX, innerY);
          ctx.lineTo(outerX, outerY);
          ctx.stroke();
        }
      },

      // 8: Block Grid
      () => {
        analyser.getByteFrequencyData(dataArray);
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        
        const cols = 16;
        const rows = 8;
        const blockWidth = canvas.width / cols;
        const blockHeight = canvas.height / rows;

        for (let i = 0; i < cols; i++) {
          const dataIndex = Math.floor((i / cols) * bufferLength);
          const value = dataArray[dataIndex];
          const activedRows = Math.floor((value / 255) * rows);
          
          for (let j = 0; j < activedRows; j++) {
            const hue = (i / cols) * 360;
            const brightness = 50 + (j / rows) * 30;
            ctx.fillStyle = `hsl(${hue}, 70%, ${brightness}%)`;
            ctx.fillRect(
              i * blockWidth + 1,
              canvas.height - (j + 1) * blockHeight + 1,
              blockWidth - 2,
              blockHeight - 2
            );
          }
        }
      },

      // 9: Spiral
      () => {
        analyser.getByteFrequencyData(dataArray);
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        
        const centerX = canvas.width / 2;
        const centerY = canvas.height / 2;
        let radius = 10;

        ctx.beginPath();
        ctx.lineWidth = 2;

        for (let i = 0; i < bufferLength; i++) {
          const angle = (i / bufferLength) * Math.PI * 8;
          const value = dataArray[i];
          radius += (value / 255) * 2;
          
          const x = centerX + Math.cos(angle) * radius;
          const y = centerY + Math.sin(angle) * radius;
          
          if (i === 0) {
            ctx.moveTo(x, y);
          } else {
            ctx.lineTo(x, y);
          }
        }

        const gradient = ctx.createRadialGradient(centerX, centerY, 0, centerX, centerY, radius);
        gradient.addColorStop(0, '#a855f7');
        gradient.addColorStop(0.5, '#3b82f6');
        gradient.addColorStop(1, '#10b981');
        ctx.strokeStyle = gradient;
        ctx.stroke();
      }
    ];

    // Animation loop
    const draw = () => {
      visualizers[visualizerType]();
      animationRef.current = requestAnimationFrame(draw);
    };

    draw();

    // Cleanup
    return () => {
      if (animationRef.current) {
        cancelAnimationFrame(animationRef.current);
      }
    };
  }, [audioElement, isPlaying, visualizerType]);

  // Cleanup audio context on unmount
  useEffect(() => {
    return () => {
      if (audioContextRef.current) {
        audioContextRef.current.close();
      }
    };
  }, []);

  if (!isPlaying) {
    return (
      <Box
        sx={{
          width: '100%',
          height: '100%',
          display: 'flex',
          alignItems: 'center',
          justifyContent: 'center',
          background: 'linear-gradient(135deg, rgba(168, 85, 247, 0.05) 0%, rgba(59, 130, 246, 0.05) 100%)'
        }}
      >
        <Audiotrack sx={{ fontSize: 80, color: 'text.disabled', opacity: 0.3 }} />
      </Box>
    );
  }

  return (
    <canvas
      ref={canvasRef}
      style={{
        width: '100%',
        height: '100%',
        display: 'block'
      }}
    />
  );
};

export default AudioVisualizer;
