import React, { useState, useEffect, useRef, Suspense, lazy, useMemo, useCallback } 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 { Dialog } from "primereact/dialog";
import { AutoComplete } from "primereact/autocomplete";
import { DataTable } from "primereact/datatable";
import { Column } from "primereact/column";
import { toast } from "react-toastify";
import { ENVIRONMENT } from "../config";
import { API_URL } from "@/config";
import { authFetch } from "@/utils/authFetch";
import { requireAuthHook } from "@/hooks/requireAuthHook";
import { useHtmlThemeAttr } from "@/hooks/useHtmlThemeAttr";
import "@/components/TRip/RequestManagement.css";

// Custom styles for paginator
const paginatorStyles = `
  .queue-paginator .p-paginator-current {
    background: transparent !important;
    color: inherit !important;
    border: none !important;
  }
  
  .dark .queue-paginator .p-paginator-current {
    color: rgb(212 212 212) !important;
    background: transparent !important;
  }
  
  .queue-paginator .p-paginator-bottom {
    padding: 16px !important;
    border-top: 1px solid rgb(229 229 229) !important;
  }
  
  .dark .queue-paginator .p-paginator-bottom {
    border-top-color: rgb(82 82 82) !important;
  }
`;

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


export default function Player({ user }) {
  // Inject custom paginator styles
  useEffect(() => {
    const styleId = 'queue-paginator-styles';
    if (!document.getElementById(styleId)) {
      const style = document.createElement('style');
      style.id = styleId;
      style.textContent = paginatorStyles;
      document.head.appendChild(style);
    }
  }, []);

  const [isQueueVisible, setQueueVisible] = useState(false);
  // Mouse wheel scroll fix for queue modal
  useEffect(() => {
    if (!isQueueVisible) return;

    const setupScrollHandlers = () => {
      // Target multiple possible scroll containers
      const selectors = [
        '.p-dialog .p-dialog-content',
        '.p-dialog .p-datatable-wrapper',
        '.p-dialog .p-datatable-scrollable-body',
        '.p-dialog .p-datatable-tbody'
      ];

      const elements = selectors
        .map(selector => document.querySelector(selector))
        .filter(Boolean);

      // Also allow scrolling on the entire dialog
      const dialog = document.querySelector('.p-dialog');
      if (dialog) elements.push(dialog);

      elements.forEach(element => {
        element.style.overflowY = 'auto';
        element.style.overscrollBehavior = 'contain';

        const wheelHandler = (e) => {
          e.stopPropagation();
          // Allow normal scrolling within the modal
        };

        element.removeEventListener('wheel', wheelHandler);
        element.addEventListener('wheel', wheelHandler, { passive: true });
      });
    };

    // Use multiple timeouts to ensure elements are rendered
    setTimeout(setupScrollHandlers, 0);
    setTimeout(setupScrollHandlers, 100);
    setTimeout(setupScrollHandlers, 300);
  }, [isQueueVisible]);
  // Debugging output
  // Autocomplete for requests
  const fetchTypeahead = async (query) => {
    if (!query || query.length < 2) {
      setTypeaheadOptions([]);
      return;
    }
    try {
      const response = await authFetch(`${API_URL}/radio/typeahead`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ station: activeStation, query }),
      });
      const data = await response.json();
      // Accept bare array or { options: [...] }
      setTypeaheadOptions(Array.isArray(data) ? data : data.options || []);
    } catch (error) {
      console.error('Typeahead: error', error);
      setTypeaheadOptions([]);
    }
  };
  const theme = useHtmlThemeAttr();

  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);
  // Update currentLyricIndex as song progresses
  useEffect(() => {
    if (!lyrics || lyrics.length === 0) return;
    // Find the last lyric whose timestamp is <= elapsedTime
    let idx = 0;
    for (let i = 0; i < lyrics.length; i++) {
      if (lyrics[i].timestamp <= elapsedTime) {
        idx = i;
      } else {
        break;
      }
    }
    setCurrentLyricIndex(idx);
  }, [elapsedTime, lyrics]);
  const [trackDuration, setTrackDuration] = useState(0);
  const [queueData, setQueueData] = useState([]);
  const [queueTotalRecords, setQueueTotalRecords] = useState(0);
  const [queuePage, setQueuePage] = useState(0);
  const [queueRows, setQueueRows] = useState(20);

  // DJ controls state
  const [requestInput, setRequestInput] = useState("");
  const [typeaheadOptions, setTypeaheadOptions] = useState([]);
  const [requestInputArtist, setRequestInputArtist] = useState("");
  const [requestInputSong, setRequestInputSong] = useState("");
  const [requestInputUuid, setRequestInputUuid] = useState("");

  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 wsInstance = useRef(null);

  const formatTime = (seconds) => {
    if (!seconds || isNaN(seconds) || seconds < 0) return "00:00";
    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} [${activeStationRef.current}]`;
  };

  // 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 = (typeof baseTrackElapsed.current === 'number' && !isNaN(baseTrackElapsed.current) ? baseTrackElapsed.current : 0) + deltaSec;
      if (trackDuration && liveElapsed > trackDuration) liveElapsed = trackDuration;
      setElapsedTime(liveElapsed);
    }, 200);
    return () => clearInterval(intervalId);
  }, [isPlaying, trackDuration]);



  // Scroll active lyric into view
  useEffect(() => {
    setTimeout(() => {
      const activeElement = document.querySelector('.lrc-line.active');
      const lyricsContainer = document.querySelector('.lrc-text');
      if (activeElement && lyricsContainer) {
        lyricsContainer.style.maxHeight = '220px';
        lyricsContainer.style.overflowY = 'auto';
        activeElement.scrollIntoView({ behavior: 'smooth', block: 'center' });
      }
    }, 0);
  }, [currentLyricIndex, lyrics]);

  // 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);
    // If no track is loaded, update page title to just station
    document.title = `${metaData.title} - Radio [${activeStation}]`;
  }, [activeStation]);

  const parseLrcString = useCallback((lrcString) => {
    if (!lrcString || typeof lrcString !== 'string') return [];

    const lines = lrcString.split('\n').filter(line => line.trim());
    const parsedLyrics = [];

    for (const line of lines) {
      const match = line.match(/\[(\d{2}):(\d{2}\.\d{2})\]\s*(.+)/);
      if (match) {
        const [, mins, secs, text] = match;
        const timestamp = Number(mins) * 60 + parseFloat(secs);
        if (!isNaN(timestamp) && text.trim()) {
          parsedLyrics.push({ timestamp, line: text.trim() });
        }
      }
    }

    return parsedLyrics.sort((a, b) => a.timestamp - b.timestamp);
  }, []);

  const fetchLyrics = useCallback(async (trackData, requestStation) => {
    try {
      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();

      // Guard against station or track changes during lyrics fetch
      if (requestStation !== activeStationRef.current || trackData.uuid !== currentTrackUuid.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);
      }
    } catch (error) {
      console.error('Error fetching lyrics:', error);
    }
  }, []);

  const handleTrackData = useCallback((trackData) => {
    console.debug('handleTrackData called with:', trackData);
    const requestStation = activeStationRef.current;

    // Only set "No track playing" if we have clear indication of no track
    // and not just missing song field (to avoid flickering during transitions)
    if ((!trackData.song || trackData.song === 'N/A') && (!trackData.artist || trackData.artist === 'N/A')) {
      console.debug('Setting no track playing state');
      setTrackTitle('No track playing');
      setLyrics([]);
      return;
    }

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

      setTrackMetadata(trackData, requestStation);

      // Clear lyrics immediately when new track is detected
      setLyrics([]);
      setCurrentLyricIndex(0);

      // Refresh queue when track changes
      fetchQueue();

      // Fetch lyrics for the new track
      fetchLyrics(trackData, requestStation);
    } else {
      // Same track - update duration and elapsed time
      setTrackDuration(trackData.duration || 0);
      if (trackData.elapsed !== undefined && typeof trackData.elapsed === 'number' && !isNaN(trackData.elapsed)) {
        baseTrackElapsed.current = trackData.elapsed;
        lastUpdateTimestamp.current = Date.now();
        setElapsedTime(trackData.elapsed);
      }
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [fetchLyrics]);

  const initializeWebSocket = useCallback((station) => {
    // Clean up existing WebSocket
    if (wsInstance.current) {
      wsInstance.current.close();
      wsInstance.current = null;
    }

    const connectWebSocket = (retryCount = 0) => {
      const maxRetries = 5;
      const baseDelay = 1000; // 1 second
      const maxDelay = 30000; // 30 seconds

      const wsUrl = `${API_URL.replace(/^https?:/, 'wss:')}/radio/ws/${station}`;
      const ws = new WebSocket(wsUrl);

      ws.onopen = function () {
        console.log('Connected to radio WebSocket for station:', station);
        // Reset retry count on successful connection
      };

      ws.onmessage = function (event) {
        try {
          const data = JSON.parse(event.data);

          if (data.type === 'track_change') {
            // Handle track change
            handleTrackData(data.data);
          } else if (data.type === 'lrc') {
            // Handle LRC data
            const parsedLyrics = parseLrcString(data.data);
            setLyrics(parsedLyrics);
            setCurrentLyricIndex(0);
          } else {
            // Handle initial now playing data
            handleTrackData(data);
          }
        } catch (error) {
          console.error('Error parsing WebSocket message:', error);
        }
      };

      ws.onclose = function (event) {
        console.log('Radio WebSocket connection closed, code:', event.code, 'reason:', event.reason);

        // Don't retry if it was a clean close (code 1000)
        if (event.code === 1000) return;

        // Attempt reconnection with exponential backoff
        if (retryCount < maxRetries) {
          const delay = Math.min(baseDelay * Math.pow(2, retryCount), maxDelay);
          console.log(`Attempting WebSocket reconnection in ${delay}ms (attempt ${retryCount + 1}/${maxRetries})`);

          setTimeout(() => {
            connectWebSocket(retryCount + 1);
          }, delay);
        } else {
          console.error('Max WebSocket reconnection attempts reached');
          setTrackTitle('Connection lost');
          setLyrics([]);
        }
      };

      ws.onerror = function (error) {
        console.error('Radio WebSocket error:', error);
        // Don't set error state here - let onclose handle reconnection
      };

      wsInstance.current = ws;
    };

    connectWebSocket();
  }, [handleTrackData, parseLrcString]);

  const setTrackMetadata = useCallback((trackData, requestStation) => {
    setTrackTitle(trackData.song || 'Unknown Title');
    setTrackArtist(trackData.artist || 'Unknown Artist');
    setTrackGenre(trackData.genre || '');
    setTrackAlbum(trackData.album || 'Unknown Album');
    setCoverArt(`${API_URL}/radio/album_art?station=${requestStation}&_=${Date.now()}`);

    const elapsed = typeof trackData.elapsed === 'number' && !isNaN(trackData.elapsed) ? trackData.elapsed : 0;
    baseTrackElapsed.current = elapsed;
    lastUpdateTimestamp.current = Date.now();
    setElapsedTime(elapsed);

    setTrackDuration(trackData.duration || 0);
    setPageTitle(trackData.artist, trackData.song);
  }, []);

  useEffect(() => {
    // ensure the ref points to the current activeStation for in-flight guards
    activeStationRef.current = activeStation;

    // Initialize WebSocket connection for metadata
    initializeWebSocket(activeStation);

    return () => {
      // Clean up WebSocket on station change or component unmount
      if (wsInstance.current) {
        wsInstance.current.close();
        wsInstance.current = null;
      }
    };
  }, [activeStation, initializeWebSocket]);

  // Cleanup WebSocket on component unmount
  useEffect(() => {
    return () => {
      if (wsInstance.current) {
        wsInstance.current.close();
        wsInstance.current = null;
      }
    };
  }, []);

  const progress = trackDuration > 0 ? (elapsedTime / trackDuration) * 100 : 0;
  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";



  const handleSkip = async (uuid = null) => {
    try {
      const response = await authFetch(`${API_URL}/radio/skip`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          skipTo: uuid,
          station: activeStation,
        }),
      });
      const data = await response.json();
      if (data.success) {
        toast.success("OK!");
        fetchQueue();
      } else {
        toast.error("Skip failed.");
      }
    } catch (error) {
      console.error("Error skipping track:", error);
      toast.error("Skip failed.");
    }
  };

  const handleReshuffle = async () => {
    try {
      const response = await authFetch(`${API_URL}/radio/reshuffle`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          station: activeStation,
        }),
      });
      const data = await response.json();
      if (data.ok) {
        toast.success("OK!");
        fetchQueue();
      } else {
        toast.error("Reshuffle failed.");
      }
    } catch (error) {
      console.error("Error reshuffling queue:", error);
      toast.error("Reshuffle failed.");
    }
  };

  const handleQueueShift = async (uuid, next = false) => {
    try {
      const response = await authFetch(`${API_URL}/radio/queue_shift`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          uuid,
          next,
          station: activeStation,
        }),
      });
      const data = await response.json();
      if (!data.err) {
        toast.success("OK!");
        fetchQueue();
      } else {
        toast.error("Queue shift failed.");
      }
    } catch (error) {
      console.error("Error shifting queue:", error);
      toast.error("Queue shift failed.");
    }
  };

  const handlePlayNow = async (artistSong, next = false) => {
    const toastId = "playNowToast"; // Unique ID for this toast
    if (!toast.isActive(toastId)) {
      toast.info("Trying...", { toastId });
    }
    try {
      const response = await authFetch(`${API_URL}/radio/request`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          artistsong: artistSong,
          alsoSkip: !next,
          station: activeStation,
        }),
      });
      const data = await response.json();
      if (data.result) {
        setRequestInput(""); // Clear the input immediately
        toast.update(toastId, { render: "OK!", type: "success", autoClose: 2000 });
        fetchQueue();
      } else {
        toast.update(toastId, { render: "Play Now failed.", type: "error", autoClose: 3000 });
      }
    } catch (error) {
      console.error("Error playing song immediately:", error);
      toast.update(toastId, { render: "Play Now failed.", type: "error", autoClose: 3000 });
    }
  };

  const handleSongRequest = async (artistSong) => {
    const toastId = "songRequestToast"; // Unique ID for this toast
    if (!toast.isActive(toastId)) {
      toast.info("Trying...", { toastId });
    }
    try {
      const response = await authFetch(`${API_URL}/radio/request`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          artistsong: artistSong,
          alsoSkip: false, // Ensure alsoSkip is false for requests
          station: activeStation,
        }),
      });
      const data = await response.json();
      if (data.result) {
        setRequestInput(""); // Clear the input immediately
        toast.update(toastId, { render: "OK!", type: "success", autoClose: 2000 });
        fetchQueue();
      } else {
        toast.update(toastId, { render: "Song request failed.", type: "error", autoClose: 3000 });
      }
    } catch (error) {
      console.error("Error requesting song:", error);
      toast.update(toastId, { render: "Song request failed.", type: "error", autoClose: 3000 });
    }
  };

  const handleRemoveFromQueue = async (uuid) => {
    try {
      const response = await authFetch(`${API_URL}/radio/remove_from_queue`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          station: activeStation,
          uuid,
        }),
      });
      const data = await response.json();
      if (!data.err) {
        toast.success("OK!");
        fetchQueue();
      } else {
        toast.error("Remove from queue failed.");
      }
    } catch (error) {
      console.error("Error removing from queue:", error);
      toast.error("Remove from queue failed.");
    }
  };

  const [queueSearch, setQueueSearch] = useState("");
  const fetchQueue = async (page = queuePage, rows = queueRows, search = queueSearch) => {
    const start = page * rows;
    try {
      const response = await authFetch(`${API_URL}/radio/get_queue`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          station: activeStation,
          start,
          length: rows,
          search,
        }),
      });
      const data = await response.json();
      setQueueData(data.items || []);
      // Use recordsFiltered for search, otherwise recordsTotal
      setQueueTotalRecords(
        typeof search === 'string' && search.length > 0
          ? data.recordsFiltered ?? data.recordsTotal ?? 0
          : data.recordsTotal ?? 0
      );
    } catch (error) {
      console.error("Error fetching queue:", error);
    }
  };

  useEffect(() => {
    if (isQueueVisible) {
      fetchQueue(queuePage, queueRows, queueSearch);
    }
  }, [isQueueVisible, queuePage, queueRows, queueSearch]);

  // Always define queueFooter, fallback to Close button if user is not available
  const isDJ = (user && user.roles.includes('dj')) || ENVIRONMENT === "Dev";
  const queueFooter = isDJ
    ? (
      <div className="flex gap-2 justify-end">
        <button
          className="px-3 py-1 rounded bg-green-400 text-white hover:bg-green-500 text-xs font-bold"
          onClick={() => handleReshuffle()}
        >
          Reshuffle
        </button>
        <button
          className="px-3 py-1 rounded bg-gray-400 text-white hover:bg-gray-500 text-xs font-bold"
          onClick={() => setQueueVisible(false)}
        >
          Close
        </button>
      </div>
    )
    : (
      <div className="flex gap-2 justify-end">
        <button
          className="px-3 py-1 rounded bg-gray-400 text-white hover:bg-gray-500 text-xs font-bold"
          onClick={() => setQueueVisible(false)}
        >
          Close
        </button>
      </div>
    );
  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-container">
        {/* {user && <span className="text-lg font-semibold">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 rounded-lg shadow-md" alt="Cover Art" />
          </section>

          <section className="music-player">
            <h1 className="music-player__header text-2xl font-bold">serious.FM</h1>
            <h1 className="music-player__title text-xl font-semibold">{trackTitle}</h1>
            <h2 className="music-player__author text-lg font-medium">{trackArtist}</h2>
            {trackGenre && <h2 className="music-player__genre text-md italic">{trackGenre}</h2>}

            <div className="music-time flex justify-between items-center mt-4">
              <p className="music-time__current text-sm">{formatTime(elapsedTime)}</p>
              <p className="music-time__last text-sm">{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 mt-4 p-4 rounded-lg bg-neutral-100 dark:bg-neutral-800 ${lyrics.length === 0 ? "empty" : ""}`}>
              {lyrics.map((lyricObj, index) => (
                <p
                  key={index}
                  className={`lrc-line text-sm ${index === currentLyricIndex ? "active font-bold" : ""}`}
                >
                  {lyricObj.line}
                </p>
              ))}
            </div>

            {isDJ && (
              <div className="dj-controls mt-6 flex flex-wrap justify-center items-center gap-2" style={{ minWidth: '24rem', maxWidth: '100%', alignItems: 'flex-start' }}>
                <div className="flex flex-col items-center gap-2 w-full" style={{ minWidth: '24rem' }}>
                  <AutoComplete
                    value={requestInput}
                    suggestions={typeaheadOptions}
                    completeMethod={(e) => {
                      fetchTypeahead(e.query);
                    }}
                    onChange={e => {
                      setRequestInput(e.target.value);
                    }}
                    onShow={() => {
                      setTimeout(() => {
                        const panel = document.querySelector('.p-autocomplete-panel');
                        const items = panel?.querySelector('.p-autocomplete-items');
                        if (items) {
                          items.style.maxHeight = '200px';
                          items.style.overflowY = 'auto';
                          items.style.overscrollBehavior = 'contain';
                          const wheelHandler = (e) => {
                            const delta = e.deltaY;
                            const atTop = items.scrollTop === 0;
                            const atBottom = items.scrollTop + items.clientHeight >= items.scrollHeight;
                            if ((delta < 0 && atTop) || (delta > 0 && atBottom)) {
                              e.preventDefault();
                            } else {
                              e.stopPropagation();
                            }
                          };
                          items.removeEventListener('wheel', wheelHandler);
                          items.addEventListener('wheel', wheelHandler, { passive: false });
                        }
                      }, 0);
                    }}
                    placeholder="Request a song..."
                    inputStyle={{
                      width: '24rem',
                      minWidth: '24rem',
                      padding: '0.35rem 0.75rem',
                      borderRadius: '9999px',
                      border: '1px solid #d1d5db',
                      fontSize: '1rem',
                      fontWeight: 'bold',
                    }}
                    className="typeahead-input"
                    forceSelection={false}
                  />
                  <div className="flex flex-row flex-wrap justify-center gap-2 items-center" style={{ minWidth: '24rem' }}>
                    <button className="px-3 py-1 rounded-full bg-blue-400 text-white hover:bg-blue-500 text-xs font-bold"
                      onClick={() => handleSongRequest(requestInput)}>
                      Request
                    </button>
                    <button className="px-3 py-1 rounded-full bg-green-400 text-white hover:bg-green-500 text-xs font-bold"
                      onClick={() => handlePlayNow(requestInput)}>
                      Play Now
                    </button>
                    <button className="px-3 py-1 rounded-full bg-red-400 text-white hover:bg-red-500 text-xs font-bold" onClick={() => handleSkip()}>Skip</button>
                    <button
                      className="px-3 py-1 rounded-full bg-gray-400 text-white hover:bg-gray-500 text-xs font-bold"
                      onClick={() => setQueueVisible(true)}
                    >
                      Queue
                    </button>
                  </div>
                </div>
              </div>
            )}
            {/* Always show play/pause button */}
            <div className="music-control mt-4 flex justify-center">
              <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" />

        <Dialog
          header={`Queue - ${activeStation}`}
          visible={isQueueVisible}
          style={{ width: "80vw", maxWidth: "1200px", height: "auto", maxHeight: "90vh" }}
          footer={queueFooter}
          onHide={() => setQueueVisible(false)}
          className={theme === "dark" ? "dark-theme" : "light-theme"}
          dismissableMask={true}
        >
          <div style={{ maxHeight: "calc(90vh - 100px)", overflow: "visible" }}>
            <div className="mb-2 flex justify-end">
              <input
                type="text"
                value={queueSearch}
                onChange={e => setQueueSearch(e.target.value)}
                placeholder="Search..."
                className="px-2 py-1 rounded border border-neutral-300 dark:border-neutral-700 text-sm"
                style={{ minWidth: 180 }}
              />
            </div>
            <DataTable
              value={queueData}
              paginator
              alwaysShowPaginator={true}
              rows={queueRows}
              first={queuePage * queueRows}
              totalRecords={queueTotalRecords}
              onPage={(e) => {
                setQueuePage(e.page);
                fetchQueue(e.page, queueRows, queueSearch);
              }}
              paginatorTemplate="FirstPageLink PrevPageLink PageLinks NextPageLink LastPageLink CurrentPageReport"
              currentPageReportTemplate="Showing {first} to {last} of {totalRecords} entries"
              paginatorClassName="queue-paginator !bg-neutral-50 dark:!bg-neutral-800 !text-neutral-900 dark:!text-neutral-100 !border-neutral-200 dark:!border-neutral-700"
              className="p-datatable-gridlines rounded-lg shadow-md border-t border-neutral-300 dark:border-neutral-700"
              style={{ minHeight: 'auto', height: 'auto', tableLayout: 'fixed', width: '100%' }}
              lazy
            >
              <Column
                field="pos"
                header="Position"
                body={(rowData) => rowData.pos + 1}
                sortable
                headerClassName="bg-neutral-100 dark:bg-neutral-800 text-neutral-900 dark:text-neutral-100 font-bold font-sans"
                style={{ width: '50px', textAlign: 'center' }}
              ></Column>
              <Column
                field="artistsong"
                header="Track"
                sortable
                headerClassName="bg-neutral-100 dark:bg-neutral-800 text-neutral-900 dark:text-neutral-100 font-bold font-sans"
                style={{ width: '300px', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}
                body={(rowData) => <span title={rowData.artistsong} style={{ display: 'block', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis', maxWidth: '300px' }}>{rowData.artistsong}</span>}
              ></Column>
              <Column
                field="album"
                header="Album"
                sortable
                headerClassName="bg-neutral-100 dark:bg-neutral-800 text-neutral-900 dark:text-neutral-100 font-bold font-sans"
                style={{ width: '220px', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}
                body={(rowData) => <span title={rowData.album} style={{ display: 'block', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis', maxWidth: '220px' }}>{rowData.album}</span>}
              ></Column>
              <Column
                field="genre"
                header="Genre"
                sortable
                headerClassName="bg-neutral-100 dark:bg-neutral-800 text-neutral-900 dark:text-neutral-100 font-bold font-sans"
                style={{ width: '120px', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}
                body={(rowData) => <span title={rowData.genre} style={{ display: 'block', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis', maxWidth: '120px' }}>{rowData.genre}</span>}
              ></Column>
              {isDJ && (
                <Column
                  field="actions"
                  header="Actions"
                  body={(rowData) => (
                    <div className="flex gap-1 flex-nowrap" style={{ minWidth: '220px', justifyContent: 'center' }}>
                      <button
                        className="px-2 py-1 rounded bg-blue-400 text-neutral-900 hover:bg-blue-500 text-xs shadow-md cursor-pointer font-bold font-sans"
                        onClick={() => handleSkip(rowData.uuid)}
                        title="Skip To"
                      >
                        Skip To
                      </button>
                      <button
                        className="px-2 py-1 rounded bg-yellow-400 text-neutral-900 hover:bg-yellow-500 text-xs shadow-md cursor-pointer font-bold font-sans"
                        onClick={() => handleQueueShift(rowData.uuid, false)}
                        title="Play"
                      >
                        Play
                      </button>
                      <button
                        className="px-2 py-1 rounded bg-green-400 text-neutral-900 hover:bg-green-500 text-xs shadow-md cursor-pointer font-bold font-sans"
                        onClick={() => handleQueueShift(rowData.uuid, true)}
                        title="Play Next"
                      >
                        Play Next
                      </button>
                      <button
                        className="px-2 py-1 rounded bg-red-400 text-neutral-900 hover:bg-red-500 text-xs shadow-md cursor-pointer font-bold font-sans"
                        onClick={() => {
                          handleRemoveFromQueue(rowData.uuid);
                        }}
                        title="Remove"
                      >
                        Remove
                      </button>
                    </div>
                  )}
                  headerClassName="bg-neutral-100 dark:bg-neutral-800 text-neutral-900 dark:text-neutral-100 font-bold font-sans"
                  style={{ width: '220px', textAlign: 'center' }}
                ></Column>
              )}
            </DataTable>
          </div>
        </Dialog>
      </div>
    </>
  );
}
