import React, { useEffect, useRef, useState } from "react";
import finalGenres from "../src/app/finalGenresV4-5.json";
import { fetchAudioUrl, getClipTitlesAndIDsByGenre } from "../utils/audioUtils";
import { capitalizeGenre } from "../utils/utils";

/**
 * Filter out clips with the same title
 */
const filterByUniqueTitle = (clips: Array<[string | null, string]>) => {
  const uniqueTitles = new Set<string>();
  return clips.filter(([title]) => {
    if (!title) return false;
    if (uniqueTitles.has(title)) return false;
    uniqueTitles.add(title);
    return true;
  });
};

export interface MusicPlayerModalProps {
  audioUrl?: string;
  genre: string;
  genreColor: string;
  isMobile: boolean;
  onDiceRoll?: () => void;
  onGenreChange: (genre: string, audioUrl: string, color: string) => void;
  onPlayPauseClick: () => void;
}

export const usePlayer = ({
  audioUrl,
  genre,
  genreColor,
  isMobile,
  onDiceRoll,
  onGenreChange,
  onPlayPauseClick,
}: MusicPlayerModalProps) => {
  const audioRef = useRef<HTMLAudioElement>(null);
  const [isPlaying, setIsPlaying] = useState(false);
  const [progress, setProgress] = useState(0);

  const [diceRolled, setDiceRolled] = useState(false);
  const [currentGenre, setCurrentGenre] = useState(genre);

  const [currentAudioUrl, setCurrentAudioUrl] = useState(audioUrl);
  const [currentSongIndex, setCurrentSongIndex] = useState(0);
  const [currentSongTitle, setCurrentSongTitle] = useState("");

  const [miniPlaylist, setMiniPlaylist] = useState<
    Array<[string | null, string]>
  >([]);

  const progressBarRef = useRef<HTMLDivElement>(null);

  useEffect(() => {
    const playAudio = async () => {
      if (audioRef.current) {
        if (currentAudioUrl && audioRef.current.src !== currentAudioUrl) {
          audioRef.current.src = currentAudioUrl;
          audioRef.current.load();
        }
        try {
          await audioRef.current.play();
          setIsPlaying(true);
        } catch (error) {
          console.error("Playback error:", error);
          setIsPlaying(false);
        }
      }
    };

    if (miniPlaylist.length > 0) {
      playAudio();
    }
  }, [currentAudioUrl, miniPlaylist.length]);

  const handlePlayPause = () => {
    setIsPlaying(!isPlaying);
    onPlayPauseClick();
  };

  useEffect(() => {
    if (audioUrl) {
      setIsPlaying(true);
    }
  }, [audioUrl]);

  useEffect(() => {
    if (audioUrl) {
      setCurrentAudioUrl(audioUrl);
      setIsPlaying(true);
    }
  }, [audioUrl]);

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

    const updateProgress = () => {
      if (audio) {
        const { currentTime, duration } = audio;
        setProgress((currentTime / duration) * 100);
      }
    };

    if (audio) {
      audio.addEventListener("timeupdate", updateProgress);
    }

    return () => {
      if (audio) {
        audio.removeEventListener("timeupdate", updateProgress);
      }
    };
  }, [audioUrl]);

  const [volumeOn, setVolumeOn] = useState(true);

  const handleVolumeToggle = () => {
    setVolumeOn(!volumeOn);

    if (audioRef.current) {
      audioRef.current.muted = !audioRef.current.muted;
    }
  };

  useEffect(() => {
    const playAudio = async () => {
      if (audioRef.current) {
        if (currentAudioUrl && audioRef.current.src !== currentAudioUrl) {
          audioRef.current.src = currentAudioUrl;
          audioRef.current.load();
        }
        try {
          if (isPlaying) {
            await audioRef.current.play();
          } else {
            audioRef.current.pause();
          }
        } catch (error) {
          console.error("Playback error:", error);
          setIsPlaying(false);
        }
      }
    };

    playAudio();
  }, [isPlaying, currentAudioUrl]);

  const handleDiceRoll = async (origin: string) => {
    const minVisibleRadius = 1000;
    const maxVisibleRadius = 1200;

    const visibleGenres = finalGenres.filter(
      (genre) =>
        genre.radius <= maxVisibleRadius && minVisibleRadius < genre.radius
    );

    if (visibleGenres.length > 0) {
      const randomIndex = Math.floor(Math.random() * visibleGenres.length);
      const randomGenre = visibleGenres[randomIndex];

      const clipsByGenre = getClipTitlesAndIDsByGenre();
      const selectedGenreClips = clipsByGenre[randomGenre.genre.toLowerCase()];

      if (selectedGenreClips && selectedGenreClips.length > 0) {
        const [_, firstClipId] = selectedGenreClips[0];
        const newAudioUrl = await fetchAudioUrl(firstClipId);

        const matchingGenreEntry = finalGenres.find(
          (entry) =>
            entry.genre.toLowerCase() === randomGenre.genre.toLowerCase()
        );
        const genreColor = matchingGenreEntry
          ? matchingGenreEntry.color
          : "#FFFFFF";

        if (newAudioUrl) {
          setCurrentAudioUrl(newAudioUrl);
          setCurrentGenre(randomGenre.genre);
          const capitalizedRandomGenre = capitalizeGenre(randomGenre.genre);
          onGenreChange(capitalizedRandomGenre, newAudioUrl, genreColor);
          setIsPlaying(true);
        } else {
          console.error("Failed to fetch audio URL for the selected clip");
        }
      } else {
        console.error("No clips found for the selected genre");
      }

      setDiceRolled(true);
      onDiceRoll?.();
    } else {
      console.error("No visible genres found based on radius criteria");
    }
  };

  useEffect(() => {
    setCurrentGenre(genre);
    const clipsByGenre = getClipTitlesAndIDsByGenre();
    const selectedGenreClips = clipsByGenre[genre.toLowerCase()] || [];
    setMiniPlaylist(filterByUniqueTitle(selectedGenreClips));
    setCurrentSongIndex(0);
    if (selectedGenreClips.length > 0) {
      const [firstSongTitle, firstClipId] = selectedGenreClips[0];
      setCurrentSongTitle(firstSongTitle || "");
      const fetchedAudioUrl = fetchAudioUrl(firstClipId);
      setCurrentAudioUrl(fetchedAudioUrl);
    }
  }, [genre]);

  const handleNextSong = () => {
    const nextIndex = (currentSongIndex + 1) % miniPlaylist.length;
    if (nextIndex === 0) {
      handleDiceRoll("nextSong");
    } else {
      setCurrentSongIndex(nextIndex);
      const [nextSongTitle, nextClipId] = miniPlaylist[nextIndex];
      setCurrentSongTitle(nextSongTitle || "");
      const fetchedAudioUrl = fetchAudioUrl(nextClipId);
      setCurrentAudioUrl(fetchedAudioUrl);
    }
  };

  const handleOnEndedNextSong = (
    currentGenre: string,
    currentSongTitle: string
  ) => {
    const nextIndex = (currentSongIndex + 1) % miniPlaylist.length;
    if (nextIndex === 0) {
      handleDiceRoll("songEnded");
    } else {
      handleNextSong();
    }
  };

  const handlePrevSong = () => {
    let prevIndex = currentSongIndex - 1;
    if (prevIndex < 0) {
      prevIndex = miniPlaylist.length - 1;
    }
    setCurrentSongIndex(prevIndex);
    const [prevSongTitle, prevClipId] = miniPlaylist[prevIndex];
    setCurrentSongTitle(prevSongTitle || "");
    const fetchedAudioUrl = fetchAudioUrl(prevClipId);
    setCurrentAudioUrl(fetchedAudioUrl);
  };

  const handleProgressBarClick = (event: React.MouseEvent<HTMLDivElement>) => {
    const progressBar = progressBarRef.current;
    if (!progressBar) return;

    const clickX = event.clientX - progressBar.getBoundingClientRect().left;
    const width = progressBar.clientWidth;
    const clickPositionRatio = clickX / width;
    const audioDuration = audioRef.current ? audioRef.current.duration : 0;
    if (audioRef.current) {
      audioRef.current.currentTime = clickPositionRatio * audioDuration;
    }
  };

  const changeSong = async (index: number) => {
    setCurrentSongIndex(index);
    const [songTitle, clipId] = miniPlaylist[index];
    setCurrentSongTitle(songTitle || "");
    const newAudioUrl = await fetchAudioUrl(clipId);
    setCurrentAudioUrl(newAudioUrl);
    if (!isPlaying) {
      setIsPlaying(true);
    }
  };

  const [hoverPosition, setHoverPosition] = useState(0);
  const [showHoverDot, setShowHoverDot] = useState(false);

  useEffect(() => {
    const beforeContent = genreColor ? "none" : "''";
    document.documentElement.style.setProperty(
      "--before-content",
      beforeContent
    );
  }, [genreColor]);

  const titleStyle = {
    fontSize: "22px",
    fontWeight: "normal",
    fontFamily: "Input Sans",
    marginBottom: "20px",
    color: "#FFFFFF",
    whiteSpace: "nowrap",
    overflow: "hidden",
    textOverflow: "ellipsis",
  };

  return {
    audioRef,
    changeSong,
    currentAudioUrl,
    currentGenre,
    currentSongIndex,
    diceRolled,
    handleDiceRoll,
    handleNextSong,
    handleOnEndedNextSong,
    handlePlayPause,
    handlePrevSong,
    handleProgressBarClick,
    handleVolumeToggle,
    hoverPosition,
    isPlaying,
    miniPlaylist,
    progress,
    progressBarRef,
    setHoverPosition,
    setProgress,
    showHoverDot,
    setShowHoverDot,
    volumeOn,
    titleStyle,
    currentSongTitle,
  };
};
