import { useRef, useState, useEffect, useMemo } from "react";
import { Play, Pause, Volume2, VolumeX } from "lucide-react";
import { Button } from "@/components/ui/button";
import { Slider } from "@/components/ui/slider";
import { Card, CardContent } from "@/components/ui/card";
import { Badge } from "@/components/ui/badge";

interface ChunkMatch {
  score: number;
  title: string;
  artist: string;
  stemType?: string;
  matchedStartTime?: number;
  matchedEndTime?: number;
  matchType?: "exact" | "similar";
}

interface ChunkAttribution {
  chunkIndex: number;
  startTime: number;
  endTime: number;
  matches: ChunkMatch[];
}

interface AudioPlayerWithMatchesProps {
  src: string;
  title: string;
  stemType?: string;
  attributions: Array<{
    id: number;
    score: number;
    metadata: {
      chunkIndex?: number;
      startTime?: number;
      endTime?: number;
      matchedTitle?: string;
      matchedArtist?: string;
      matchedStemType?: string;
      matchedStartTime?: number;
      matchedEndTime?: number;
      matchType?: "exact" | "similar";
    } | null;
  }>;
}

export function AudioPlayerWithMatches({ 
  src, 
  title, 
  stemType,
  attributions 
}: AudioPlayerWithMatchesProps) {
  const audioRef = useRef<HTMLAudioElement>(null);
  const waveformRef = useRef<HTMLDivElement>(null);
  
  const [isPlaying, setIsPlaying] = useState(false);
  const [currentTime, setCurrentTime] = useState(0);
  const [duration, setDuration] = useState(0);
  const [isMuted, setIsMuted] = useState(false);
  const [hoverTime, setHoverTime] = useState<number | null>(null);
  const [hoverX, setHoverX] = useState<number>(0);

  // Group attributions by chunk
  const chunkAttributions = useMemo(() => {
    const chunks: Map<number, ChunkAttribution> = new Map();
    
    for (const attr of attributions) {
      const meta = attr.metadata;
      if (!meta || meta.chunkIndex === undefined) continue;
      
      const chunkIndex = meta.chunkIndex;
      const startTime = meta.startTime || 0;
      
      // For first 10 seconds, only show exact matches (skip style matches)
      const isFirstChunk = startTime < 1;
      if (isFirstChunk && meta.matchType !== "exact") {
        continue; // Skip style matches in first chunk
      }
      
      if (!chunks.has(chunkIndex)) {
        chunks.set(chunkIndex, {
          chunkIndex,
          startTime,
          endTime: meta.endTime || 0,
          matches: [],
        });
      }
      
      const chunk = chunks.get(chunkIndex)!;
      chunk.matches.push({
        score: attr.score,
        title: meta.matchedTitle || "Unknown",
        artist: meta.matchedArtist || "Unknown",
        stemType: meta.matchedStemType,
        matchedStartTime: meta.matchedStartTime,
        matchedEndTime: meta.matchedEndTime,
        matchType: meta.matchType,
      });
    }
    
    // Sort matches by score within each chunk
    for (const chunk of chunks.values()) {
      chunk.matches.sort((a, b) => b.score - a.score);
    }
    
    return Array.from(chunks.values()).sort((a, b) => a.startTime - b.startTime);
  }, [attributions]);

  // Get matches for current hover position
  const hoveredChunk = useMemo(() => {
    if (hoverTime === null) return null;
    return chunkAttributions.find(
      c => hoverTime >= c.startTime && hoverTime < c.endTime
    );
  }, [hoverTime, chunkAttributions]);

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

    const handleTimeUpdate = () => setCurrentTime(audio.currentTime);
    const handleDurationChange = () => setDuration(audio.duration);
    const handleEnded = () => setIsPlaying(false);

    audio.addEventListener("timeupdate", handleTimeUpdate);
    audio.addEventListener("durationchange", handleDurationChange);
    audio.addEventListener("ended", handleEnded);

    return () => {
      audio.removeEventListener("timeupdate", handleTimeUpdate);
      audio.removeEventListener("durationchange", handleDurationChange);
      audio.removeEventListener("ended", handleEnded);
    };
  }, []);

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

    if (isPlaying) {
      audio.pause();
    } else {
      audio.play();
    }
    setIsPlaying(!isPlaying);
  };

  const toggleMute = () => {
    const audio = audioRef.current;
    if (!audio) return;
    audio.muted = !isMuted;
    setIsMuted(!isMuted);
  };

  const handleSeek = (value: number[]) => {
    const audio = audioRef.current;
    if (!audio || !value[0]) return;
    audio.currentTime = value[0];
    setCurrentTime(value[0]);
  };

  const handleWaveformHover = (e: React.MouseEvent<HTMLDivElement>) => {
    const rect = e.currentTarget.getBoundingClientRect();
    const x = e.clientX - rect.left;
    const percentage = x / rect.width;
    const time = percentage * duration;
    setHoverTime(time);
    setHoverX(x);
  };

  const handleWaveformLeave = () => {
    setHoverTime(null);
  };

  const handleWaveformClick = (e: React.MouseEvent<HTMLDivElement>) => {
    const rect = e.currentTarget.getBoundingClientRect();
    const x = e.clientX - rect.left;
    const percentage = x / rect.width;
    const time = percentage * duration;
    handleSeek([time]);
  };

  const formatTime = (seconds: number) => {
    const mins = Math.floor(seconds / 60);
    const secs = Math.floor(seconds % 60);
    return `${mins}:${secs.toString().padStart(2, "0")}`;
  };

  // Get color based on match type: green for exact, orange for style
  const getChunkColor = (chunk: ChunkAttribution) => {
    const topMatch = chunk.matches[0];
    if (!topMatch) return "bg-gray-500/20";
    
    // Check if any match is exact
    const hasExact = chunk.matches.some(m => m.matchType === "exact");
    
    if (hasExact) {
      // Green shades for exact matches
      if (topMatch.score > 0.9) return "bg-green-500/70";
      if (topMatch.score > 0.8) return "bg-green-500/50";
      return "bg-green-500/40";
    } else {
      // Orange shades for style matches
      if (topMatch.score > 0.9) return "bg-orange-500/60";
      if (topMatch.score > 0.8) return "bg-orange-500/50";
      return "bg-orange-500/40";
    }
  };

  return (
    <Card className="relative">
      <CardContent className="p-4 overflow-visible">
        <div className="flex items-center gap-4 mb-3">
          <Button
            variant="outline"
            size="icon"
            onClick={togglePlay}
            className="shrink-0"
          >
            {isPlaying ? <Pause className="h-4 w-4" /> : <Play className="h-4 w-4" />}
          </Button>
          
          <div className="flex-1 min-w-0">
            <h4 className="font-medium truncate">{title}</h4>
            {stemType && (
              <Badge variant="secondary" className="text-xs">
                {stemType}
              </Badge>
            )}
          </div>
          
          <Button
            variant="ghost"
            size="icon"
            onClick={toggleMute}
            className="shrink-0"
          >
            {isMuted ? <VolumeX className="h-4 w-4" /> : <Volume2 className="h-4 w-4" />}
          </Button>
        </div>

        {/* Waveform */}
        <div className="relative">
          <div
            ref={waveformRef}
            className="relative h-16 bg-secondary/30 rounded-lg cursor-pointer overflow-hidden"
            onMouseMove={handleWaveformHover}
            onMouseLeave={handleWaveformLeave}
            onClick={handleWaveformClick}
          >
            {/* Chunk regions with match intensity coloring */}
            {duration > 0 && chunkAttributions.map((chunk) => {
              const left = (chunk.startTime / duration) * 100;
              const width = ((chunk.endTime - chunk.startTime) / duration) * 100;
              return (
                <div
                  key={chunk.chunkIndex}
                  className={`absolute top-0 h-full ${getChunkColor(chunk)} border-r border-background/20`}
                  style={{ left: `${left}%`, width: `${width}%` }}
                />
              );
            })}

            {/* Playhead */}
            {duration > 0 && (
              <div
                className="absolute top-0 h-full w-0.5 bg-primary z-10"
                style={{ left: `${(currentTime / duration) * 100}%` }}
              />
            )}

            {/* Hover indicator */}
            {hoverTime !== null && duration > 0 && (
              <div
                className="absolute top-0 h-full w-0.5 bg-foreground/50 z-10"
                style={{ left: `${(hoverTime / duration) * 100}%` }}
              />
            )}

            {/* Waveform placeholder bars */}
            <div className="absolute inset-0 flex items-center justify-around px-1">
              {Array.from({ length: 60 }).map((_, i) => (
                <div
                  key={i}
                  className="w-1 bg-foreground/20 rounded-full"
                  style={{ 
                    height: `${20 + Math.sin(i * 0.5) * 15 + Math.random() * 20}%`,
                  }}
                />
              ))}
            </div>
          </div>

        </div>

        {/* Time display */}
        <div className="flex justify-between text-xs text-muted-foreground mt-2">
          <span>{formatTime(currentTime)}</span>
          <span>{formatTime(duration)}</span>
        </div>

        {/* Matches panel - shown on hover */}
        <div className={`mt-3 rounded-lg border bg-muted/50 transition-all duration-200 overflow-hidden ${hoveredChunk ? 'max-h-40 p-3' : 'max-h-0 p-0 border-transparent'}`}>
          {hoveredChunk && (
            <>
              <div className="flex items-center justify-between mb-2">
                <span className="text-xs font-medium">
                  Matches for {formatTime(hoveredChunk.startTime)} - {formatTime(hoveredChunk.endTime)}
                </span>
                <Badge variant="outline" className="text-[10px]">
                  {hoveredChunk.matches.length} matches
                </Badge>
              </div>
              <div className="flex flex-wrap gap-2">
                {hoveredChunk.matches.slice(0, 5).map((match, i) => (
                  <div key={i} className="flex items-center gap-1.5 bg-background rounded-md px-2 py-1 border">
                    <Badge 
                      variant={match.score > 0.7 ? "destructive" : "secondary"}
                      className="text-[10px] px-1"
                    >
                      {(match.score * 100).toFixed(0)}%
                    </Badge>
                    <span className="text-xs truncate max-w-[120px]">{match.title}</span>
                  </div>
                ))}
                {hoveredChunk.matches.length === 0 && (
                  <span className="text-xs text-muted-foreground">No matching tracks found</span>
                )}
              </div>
            </>
          )}
        </div>

        {/* Hidden audio element */}
        <audio ref={audioRef} src={src} preload="metadata" />
      </CardContent>
    </Card>
  );
}

