import React, { useState, useEffect, useRef, Suspense, lazy } from "react";
import { metaData } from "../config";
import Play from "@mui/icons-material/PlayArrow";
import Pause from "@mui/icons-material/Pause";
import "@styles/player.css";

import { API_URL } from "@/config";
import { requireAuthHook } from "@/hooks/requireAuthHook";

const STATIONS = {
  main: { label: "Main" },
  rock: { label: "Rock" },
  rap: { label: "Rap" },
  electronic: { label: "Electronic" },
  pop: { label: "Pop" },
};


export default function Player({ user }) {
  const [activeStation, setActiveStation] = useState("main");
  const [isPlaying, setIsPlaying] = useState(false);
  const [trackTitle, setTrackTitle] = useState("");
  const [trackArtist, setTrackArtist] = useState("");
  const [trackGenre, setTrackGenre] = useState("");
  const [trackAlbum, setTrackAlbum] = useState("");
  const [coverArt, setCoverArt] = useState("/images/radio_art_default.jpg");
  const [lyrics, setLyrics] = useState([]);
  const [currentLyricIndex, setCurrentLyricIndex] = useState(0);
  const [elapsedTime, setElapsedTime] = useState(0);
  const [trackDuration, setTrackDuration] = useState(0);

  const audioElement = useRef(null);
  const hlsInstance = useRef(null);
  const currentTrackUuid = useRef(null);
  const baseTrackElapsed = useRef(0);
  const lastUpdateTimestamp = useRef(Date.now());
  const activeStationRef = useRef(activeStation);

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

  // Set page title based on current track and station
  const setPageTitle = (artist, song) => {
    document.title = `${metaData.title} - Radio - ${artist} - ${song} [${activeStation}]`;
  };

  // Initialize or switch HLS stream
  const initializeStream = (station) => {
    import('hls.js').then(({ default: Hls }) => {
      const audio = audioElement.current;
      if (!audio) return;
      const streamUrl = `https://stream.codey.lol/hls/${station}/${station}.m3u8`;

      // Clean up previous HLS
      if (hlsInstance.current) {
        hlsInstance.current.destroy();
        hlsInstance.current = null;
      }
      audio.pause();
      audio.removeAttribute("src");
      audio.load();

      // Handle audio load errors
      audio.onerror = () => {
        setIsPlaying(false);
      };

      if (audio.canPlayType("application/vnd.apple.mpegurl")) {
        audio.src = streamUrl;
        audio.load();
        audio.play().then(() => setIsPlaying(true)).catch(() => {
          setTrackTitle("Offline");
          setIsPlaying(false);
        });
        return;
      }

      if (!Hls.isSupported()) {
        console.error("HLS not supported");
        return;
      }

      const hls = new Hls({
        lowLatencyMode: true,
        abrEnabled: false,
        liveSyncDuration: 0.5,               // seconds behind live edge target
        liveMaxLatencyDuration: 3.0,        // max allowed latency before catchup
        liveCatchUpPlaybackRate: 1.02,
        maxBufferLength: 30,
        maxMaxBufferLength: 60,
        maxBufferHole: 0.5,
        manifestLoadingTimeOut: 4000,
        fragLoadingTimeOut: 10000,     // playback speed when catching up
      });

      hlsInstance.current = hls;
      hls.attachMedia(audio);
      hls.on(Hls.Events.MEDIA_ATTACHED, () => hls.loadSource(streamUrl));
      hls.on(Hls.Events.MANIFEST_PARSED, () => {
        audio.play().then(() => setIsPlaying(true)).catch(() => {
          setIsPlaying(false);
        });
      });
      hls.on(Hls.Events.ERROR, (event, data) => {
        console.warn("HLS error:", data);
        if (data.fatal) {
          hls.destroy();
          hlsInstance.current = null;
          setTrackTitle("Offline");
          setIsPlaying(false);
        }
      });
    });
  };

  // Update elapsed time smoothly
  useEffect(() => {
    const intervalId = setInterval(() => {
      const now = Date.now();
      const deltaSec = (now - lastUpdateTimestamp.current) / 1000;
      let liveElapsed = baseTrackElapsed.current + deltaSec;
      if (trackDuration && liveElapsed > trackDuration) liveElapsed = trackDuration;
      setElapsedTime(liveElapsed);
    }, 200);

    return () => clearInterval(intervalId);
  }, [isPlaying, trackDuration]);



  // Use both base elapsed and audio time for precise lyric syncing
  useEffect(() => {
    if (!isPlaying || !lyrics.length) return;

    const lyricsInterval = setInterval(() => {
      let newIndex = 0;
      for (let i = 0; i < lyrics.length; i++) {
        if (elapsedTime >= lyrics[i].timestamp) newIndex = i;
        else break;
      }
      setCurrentLyricIndex(newIndex);
    }, 200);

    return () => clearInterval(lyricsInterval);
  }, [isPlaying, lyrics, elapsedTime]);




  // Scroll active lyric into view
  useEffect(() => {
    const activeElement = document.querySelector('.lrc-line.active');
    if (activeElement) {
      activeElement.scrollIntoView({ behavior: 'smooth', block: 'center' });
    }
  }, [currentLyricIndex]);

  // Handle station changes: reset and start new stream
  useEffect(() => {
    setIsPlaying(false);
    setTrackTitle("");
    setTrackArtist("");
    setTrackGenre("");
    setTrackAlbum("");
    setCoverArt("/images/radio_art_default.jpg");

    setLyrics([]);
    setCurrentLyricIndex(0);
    setElapsedTime(0);
    setTrackDuration(0);

    currentTrackUuid.current = null;
    baseTrackElapsed.current = 0;
    lastUpdateTimestamp.current = Date.now();

    initializeStream(activeStation);
  }, [activeStation]);

  // Fetch metadata and lyrics periodically
  useEffect(() => {
    const fetchMetadataAndLyrics = async () => {
      // capture the station id at request time; ignore results if station changed
      const requestStation = activeStationRef.current;
      try {
        const response = await fetch(`${API_URL}/radio/np?station=${requestStation}`, { method: 'POST' });
        const trackData = await response.json();

        // If station changed while request was in-flight, ignore the response
        if (requestStation !== activeStationRef.current) return;

        if (trackData.artist === 'N/A') {
          setTrackTitle('Offline');
          setLyrics([]);
          return;
        }

        if (trackData.uuid !== currentTrackUuid.current) {
          currentTrackUuid.current = trackData.uuid;

          setTrackTitle(trackData.song);
          setTrackArtist(trackData.artist);
          setTrackGenre(trackData.genre || '');
          setTrackAlbum(trackData.album);
          setCoverArt(`${API_URL}/radio/album_art?station=${requestStation}&_=${Date.now()}`);

          baseTrackElapsed.current = trackData.elapsed;
          lastUpdateTimestamp.current = Date.now();
          setElapsedTime(trackData.elapsed);

          setTrackDuration(trackData.duration);

          setLyrics([]);
          setCurrentLyricIndex(0);
          setPageTitle(trackData.artist, trackData.song);

          // Fetch lyrics as before, but guard against station switches
          const lyricsResponse = await fetch(`${API_URL}/lyric/search`, {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({
              a: trackData.artist,
              s: trackData.song,
              excluded_sources: [],
              extra: false,
              lrc: true,
              src: 'WEB-RADIO',
            }),
          });
          const lyricsData = await lyricsResponse.json();
          if (requestStation !== activeStationRef.current) return;
          if (!lyricsData.err && Array.isArray(lyricsData.lrc)) {
            const parsedLyrics = lyricsData.lrc.map(({ timeTag, words }) => {
              const [mins, rest] = timeTag.split(':');
              const secs = parseFloat(rest);
              return { timestamp: Number(mins) * 60 + secs, line: words };
            });
            setLyrics(parsedLyrics);
            setCurrentLyricIndex(0);
          }
        } else {
          // Same track - do not update elapsed or elapsed base here
          setTrackDuration(trackData.duration);
        }
      } catch (error) {
        console.error('Error fetching metadata:', error);
        setTrackTitle('Offline');
        setLyrics([]);
      }
    };
    // ensure the ref points to the current activeStation for in-flight guards
    activeStationRef.current = activeStation;
    fetchMetadataAndLyrics();
    const metadataInterval = setInterval(fetchMetadataAndLyrics, 700);
    return () => clearInterval(metadataInterval);
  }, [activeStation]);

  const progress = (elapsedTime / trackDuration) * 100;
  const remaining = trackDuration - elapsedTime;

  const progressColorClass =
    progress >= 90
      ? "bg-red-500 dark:bg-red-400"
      : progress >= 75 || remaining <= 20
        ? "bg-yellow-400 dark:bg-yellow-300"
        : "bg-blue-500 dark:bg-blue-400";


  return (
    <>
      <div className="station-tabs flex gap-2 justify-center mb-4 flex-wrap z-10 relative">
        {Object.entries(STATIONS).map(([stationKey, { label }]) => (
          <button
            key={stationKey}
            onClick={() => setActiveStation(stationKey)}
            className={`px-3 py-1 rounded-full text-sm font-semibold transition-colors ${activeStation === stationKey
              ? 'bg-neutral-800 text-white dark:bg-white dark:text-black'
              : 'bg-neutral-200 text-black dark:bg-neutral-700 dark:text-white'
              }`}
            aria-pressed={activeStation === stationKey}
          >
            {label}
          </button>
        ))}
      </div>
      <div className="c-containter">
        {user && <span>Hello, {user.user}</span>}
        < div className="music-container mt-8">
          <section className="album-cover">
            <div className="music-player__album" title="Album">
              {trackAlbum}
            </div>
            <img src={coverArt} className="cover" alt="Cover Art" />
          </section>
          <section className="music-player">
            <h1 className="music-player__header">serious.FM</h1>
            <h1 className="music-player__title">{trackTitle}</h1>
            <h2 className="music-player__author">{trackArtist}</h2>
            {trackGenre && <h2 className="music-player__genre">{trackGenre}</h2>}

            <div className="music-time">
              <p className="music-time__current">{formatTime(elapsedTime)}</p>
              <p className="music-time__last">{formatTime(trackDuration - elapsedTime)}</p>
            </div>
            <div className="progress-bar-container w-full h-2 rounded bg-neutral-300 dark:bg-neutral-700 overflow-hidden">
              <div
                className={`h-full transition-all duration-200 ${progressColorClass}`}
                style={{ width: `${progress}%` }}
              ></div>
            </div>

            <div className={`lrc-text ${lyrics.length === 0 ? 'empty' : ''}`}>
              {lyrics.map((lyricObj, index) => (
                <p
                  key={index}
                  className={`lrc-line ${index === currentLyricIndex ? 'active' : ''}`}
                >
                  {lyricObj.line}
                </p>
              ))}
            </div>

            <div className="music-control">
              <div
                className="music-control__play"
                onClick={() => {
                  const audio = audioElement.current;
                  if (!audio) return;
                  if (isPlaying) {
                    audio.pause();
                    setIsPlaying(false);
                  } else {
                    audio.play().then(() => setIsPlaying(true));
                  }
                }}
                role="button"
                tabIndex={0}
                aria-pressed={isPlaying}
              >
                {isPlaying ? <Pause /> : <Play />}
              </div>
            </div>
          </section>
        </div>
        <audio ref={audioElement} preload="none" />
      </div >
    </>
  );
}
