
"use client";

import { useEffect, useRef, useState } from "react";
import { Button } from "@/components/ui/button";
import { Play, Pause, Volume2, VolumeX, AlertTriangle, Volume1 } from "lucide-react";
import { Slider } from "@/components/ui/slider";
import { cn } from "@/lib/utils";

type AudioPlayerProps = {
  src: string;
  autoPlay?: boolean;
};

export function AudioPlayer({ src, autoPlay = false }: AudioPlayerProps) {
  const audioRef = useRef<HTMLAudioElement | null>(null);
  const canvasRef = useRef<HTMLCanvasElement>(null);
  const [isPlaying, setIsPlaying] = useState(false);
  const [playbackError, setPlaybackError] = useState<string | null>(null);
  const [elapsedTime, setElapsedTime] = useState("00:00");
  const [volume, setVolume] = useState(1);
  const [isMuted, setIsMuted] = useState(false);

  const audioContextRef = useRef<AudioContext | null>(null);
  const analyserRef = useRef<AnalyserNode | null>(null);
  const sourceRef = useRef<MediaElementAudioSourceNode | null>(null);
  const animationFrameIdRef = useRef<number | null>(null);

  const draw = () => {
    if (!analyserRef.current || !canvasRef.current) {
        animationFrameIdRef.current = requestAnimationFrame(draw);
        return;
    };

    const bufferLength = analyserRef.current.frequencyBinCount;
    const dataArray = new Uint8Array(bufferLength);
    analyserRef.current.getByteFrequencyData(dataArray);
    
    const canvas = canvasRef.current;
    const canvasCtx = canvas.getContext('2d');
    if (!canvasCtx) return;
    
    const WIDTH = canvas.width;
    const HEIGHT = canvas.height;

    canvasCtx.clearRect(0, 0, WIDTH, HEIGHT);
    
    let barWidth = (WIDTH / bufferLength) * 2.5;
    let barHeight;
    let x = 0;

    for (let i = 0; i < bufferLength; i++) {
      barHeight = dataArray[i] / 2;
      const accentHsl = getComputedStyle(document.documentElement).getPropertyValue('--accent').trim();
      const [h, s, l] = accentHsl.split(' ').map(parseFloat);
      canvasCtx.fillStyle = `hsla(${h}, ${s}%, ${l}%, ${barHeight / 100})`;
      canvasCtx.fillRect(x, HEIGHT - barHeight, barWidth, barHeight);
      x += barWidth + 1;
    }
    animationFrameIdRef.current = requestAnimationFrame(draw);
  };

  const setupAudioVisualizer = () => {
    const audio = audioRef.current;
    if (!audio || audioContextRef.current) return;
    
    try {
        const context = new (window.AudioContext || (window as any).webkitAudioContext)();
        audioContextRef.current = context;
        analyserRef.current = context.createAnalyser();
        analyserRef.current.fftSize = 256;
        
        sourceRef.current = context.createMediaElementSource(audio);
        sourceRef.current.connect(analyserRef.current);
        analyserRef.current.connect(context.destination);

        draw();
    } catch (e) {
        console.error("Failed to initialize AudioContext:", e);
        if (audioContextRef.current) audioContextRef.current.close().catch(console.error);
        audioContextRef.current = null;
    }
  };
  
  const togglePlayPause = () => {
    const audio = audioRef.current;
    if (!audio) return;
  
    if (audio.paused) {
      if (!audioContextRef.current) {
        setupAudioVisualizer();
      }
      if (audioContextRef.current && audioContextRef.current.state === 'suspended') {
        audioContextRef.current.resume();
      }
      const playPromise = audio.play();
      if (playPromise !== undefined) {
        playPromise.catch(error => {
          if (error.name !== 'AbortError') {
            console.error("Playback failed:", error);
            setPlaybackError("Playback failed or was interrupted.");
          }
        });
      }
    } else {
      audio.pause();
    }
  };


  useEffect(() => {
    const audio = audioRef.current;
    if (!audio) return;

    setPlaybackError(null);
    audio.src = src;
    audio.muted = isMuted;

    const handlePlay = () => { setIsPlaying(true); setPlaybackError(null); };
    const handlePause = () => setIsPlaying(false);
    const handleError = (e: Event) => {
      console.error("Audio playback error:", e);
      if (audio.error) {
          let message = "This audio stream is currently unavailable.";
          switch (audio.error.code) {
              case audio.error.MEDIA_ERR_NETWORK: message = "A network error caused the audio to fail."; break;
              case audio.error.MEDIA_ERR_DECODE: message = "The audio could not be decoded or is not supported."; break;
              case audio.error.MEDIA_ERR_SRC_NOT_SUPPORTED: message = "The audio format is not supported."; break;
              default: message = "An unknown error occurred during playback."; break;
          }
          setPlaybackError(message);
      }
      setIsPlaying(false);
    };
    const handleTimeUpdate = () => {
        if (isFinite(audio.currentTime)) {
            const minutes = Math.floor(audio.currentTime / 60);
            const seconds = Math.floor(audio.currentTime % 60);
            setElapsedTime(`${minutes.toString().padStart(2, "0")}:${seconds.toString().padStart(2, "0")}`);
        }
    };
    
    const handleVolumeChange = () => {
      setVolume(audio.volume);
      setIsMuted(audio.muted);
    };

    audio.addEventListener('play', handlePlay);
    audio.addEventListener('pause', handlePause);
    audio.addEventListener('error', handleError);
    audio.addEventListener('timeupdate', handleTimeUpdate);
    audio.addEventListener('volumechange', handleVolumeChange);

    if (autoPlay) {
        audio.muted = false; // Explicitly unmute for autoplay
        togglePlayPause();
    }
    
    return () => {
      if (animationFrameIdRef.current) cancelAnimationFrame(animationFrameIdRef.current);
      audio.removeEventListener('play', handlePlay);
      audio.removeEventListener('pause', handlePause);
      audio.removeEventListener('error', handleError);
      audio.removeEventListener('timeupdate', handleTimeUpdate);
      audio.removeEventListener('volumechange', handleVolumeChange);
      audio.pause();
      audio.removeAttribute('src');
      audio.load();
    };
  // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [src, isMuted]);


  const handleVolumeChange = (value: number[]) => {
    const newVolume = value[0];
    if (audioRef.current) {
      audioRef.current.volume = newVolume;
      if (newVolume > 0 && audioRef.current.muted) {
        audioRef.current.muted = false;
      }
    }
  };
  
  const toggleMute = () => {
    const audio = audioRef.current;
    if (!audio) return;
    audio.muted = !audio.muted;
  };
  
  const VolumeIcon = isMuted || volume === 0 ? VolumeX : volume < 0.5 ? Volume1 : Volume2;


  return (
    <div className="relative w-full aspect-video bg-muted rounded-lg overflow-hidden shadow-2xl flex flex-col items-center justify-center p-6">
      <audio ref={audioRef} key={src} playsInline crossOrigin="anonymous" />
      
      <canvas ref={canvasRef} className="absolute inset-0 w-full h-full opacity-50 z-20" />

      {playbackError && (
        <div className="z-30 flex flex-col items-center justify-center text-white bg-black/50 p-4 rounded-lg text-center">
          <AlertTriangle className="w-12 h-12 mb-2 text-yellow-400" />
          <p className="font-semibold text-lg">Playback Error</p>
          <p className="text-sm">{playbackError}</p>
        </div>
      )}

      {!playbackError && (
        <div className="z-30 flex flex-col items-center gap-4 w-full max-w-md">
            <div className="flex items-center gap-4">
                <Button onClick={togglePlayPause} size="icon" className="w-16 h-16 rounded-full">
                    {isPlaying ? <Pause className="w-8 h-8" /> : <Play className="w-8 h-8" />}
                </Button>
                <span className="text-2xl font-mono tracking-wider text-white/80">{elapsedTime}</span>
            </div>
            <div className="flex items-center gap-3 w-full">
                <Button onClick={toggleMute} variant="ghost" size="icon" className="rounded-full text-white/80 hover:text-white">
                    <VolumeIcon className="w-6 h-6" />
                </Button>
                <Slider
                    value={[isMuted ? 0 : volume]}
                    onValueChange={handleVolumeChange}
                    max={1}
                    step={0.05}
                    className={cn("w-full")}
                    aria-label="Volume slider"
                />
            </div>
        </div>
      )}
    </div>
  );
}

    