import { useState, useRef, useCallback } from 'react';
import { createPortal } from 'react-dom';
import { usePlayer } from '@/features/player/hooks/usePlayer';
import { useKeyboardShortcuts } from '@/features/player/hooks/useKeyboardShortcuts';
import { useAudioAnalyser } from '@/features/player/hooks/useAudioAnalyser';
import { useMediaSession } from '@/features/player/hooks/useMediaSession';
import { useUIStore } from '@/stores/ui';
import { formatTime } from '@/features/player/services/playerService';
import { PlayerControls } from './PlayerControls';
import { PlayerQueue } from './PlayerQueue';
import { PlayerExpanded } from './PlayerExpanded';
import {
  PlayerBarGlass,
  PlayerBarTrackInfo,
  PlayerBarProgress,
  PlayerBarRight,
} from './player-bar';
import { PlaybackSpeedControl } from './PlaybackSpeedControl';
import { cn } from '@/lib/utils';

const IDLE_TRACK = {
  id: 'idle',
  title: 'System Online',
  artist: 'Select a track to play',
  cover: '',
  duration: 0,
  url: '',
};

export function GlobalPlayer() {
  const audioRef = useRef<HTMLAudioElement>(null);
  const [audioEl, setAudioEl] = useState<HTMLAudioElement | null>(null);
  const setAudioRef = useCallback((el: HTMLAudioElement | null) => {
    (audioRef as React.MutableRefObject<HTMLAudioElement | null>).current = el;
    setAudioEl(el);
  }, []);

  const { sidebarOpen } = useUIStore();
  const player = usePlayer(audioRef);
  useKeyboardShortcuts(player);
  useMediaSession({
    track: currentTrack ?? null,
    isPlaying: player.isPlaying,
    onPlay: () => !isIdle && player.resume(),
    onPause: player.pause,
    onPrevious: player.previous,
    onNext: player.next,
  });

  const [isHovered, setIsHovered] = useState(false);
  const [isExpanded, setIsExpanded] = useState(false);
  const [showQueue, setShowQueue] = useState(false);

  const waveformLevels = useAudioAnalyser(audioEl, player.isPlaying);
  const currentTrack = player.currentTrack;
  const displayTrack = currentTrack || IDLE_TRACK;
  const isIdle = !currentTrack;

  return (
    <>
      <audio ref={setAudioRef} />

      <PlayerExpanded
        isOpen={isExpanded}
        onClose={() => setIsExpanded(false)}
        currentTime={player.currentTime}
        duration={player.duration}
        onSeek={player.seek}
        player={player}
      />

      <PlayerQueue
        isOpen={showQueue}
        onClose={() => setShowQueue(false)}
        currentTrackId={currentTrack?.id}
        onPlay={(track) => player.play(track)}
      />

      {createPortal(
        <div
          data-testid="global-player"
          role="region"
          aria-label="Global player"
          className={cn(
            'fixed bottom-6 left-4 right-4 z-player transition-all duration-[var(--sumi-duration-slow)] ease-[var(--sumi-ease-out)]',
            'lg:right-4 w-player-bar',
            sidebarOpen ? 'lg:left-main-expanded lg:w-player-bar-expanded' : 'lg:left-main-collapsed lg:w-player-bar-collapsed',
            isExpanded && 'translate-y-full opacity-0 pointer-events-none',
          )}
          onMouseEnter={() => setIsHovered(true)}
          onMouseLeave={() => setIsHovered(false)}
        >
          <PlayerBarGlass isHovered={isHovered}>
            <div className="flex items-center justify-between gap-2 sm:gap-3 h-14 sm:h-16 px-3 sm:px-4 relative z-10 min-w-0 flex-nowrap">
              <PlayerBarTrackInfo
                title={displayTrack.title}
                artist={displayTrack.artist || 'Unknown Artist'}
                cover={displayTrack.cover}
                isIdle={isIdle}
                isPlaying={player.isPlaying}
                onExpand={() => !isIdle && setIsExpanded(true)}
              />

              <section
                className="flex flex-col items-center justify-center gap-0.5 flex-shrink-0"
                aria-label="Playback controls"
              >
                <PlayerControls
                  compact
                  isPlaying={player.isPlaying}
                  onPlayPause={() => {
                    if (player.isPlaying) player.pause();
                    else if (!isIdle) player.resume();
                  }}
                  onNext={player.next}
                  onPrevious={player.previous}
                  onShuffle={player.toggleShuffle}
                  onRepeat={() => {
                    const modes = ['off', 'track', 'playlist'] as const;
                    const current = player.repeat ?? 'off';
                    const next = modes[(modes.indexOf(current) + 1) % modes.length] ?? 'off';
                    player.setRepeat(next);
                  }}
                  shuffle={player.shuffle}
                  repeat={player.repeat}
                />
                <PlaybackSpeedControl
                  speed={player.playbackSpeed}
                  onSpeedChange={player.setPlaybackSpeed}
                  disabled={isIdle}
                />
                <div
                  className={cn(
                    'flex items-center gap-1.5 text-xs font-mono text-muted-foreground whitespace-nowrap',
                    isIdle ? 'opacity-50' : 'opacity-90',
                  )}
                >
                  <span>{formatTime(player.currentTime)}</span>
                  <span className="opacity-30">/</span>
                  <span>{formatTime(player.duration)}</span>
                </div>
              </section>

              <PlayerBarRight
                volume={player.volume}
                muted={player.muted}
                onVolumeChange={player.setVolume}
                onToggleMute={player.toggleMute}
                showQueue={showQueue}
                onToggleQueue={() => setShowQueue(!showQueue)}
                waveformLevels={waveformLevels}
                isPlaying={player.isPlaying}
              />
            </div>

            {!isIdle && (
              <PlayerBarProgress
                currentTime={player.currentTime}
                duration={player.duration}
                onSeek={(pct) => player.seek(pct * player.duration)}
              />
            )}
          </PlayerBarGlass>
        </div>,
        document.body,
      )}
    </>
  );
}
