import { Badge } from '@/components/ui/badge'
import { Button } from '@/components/ui/button'
import { Card, CardContent } from '@/components/ui/card'
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu'
import { Progress } from '@/components/ui/progress'
import { Slider } from '@/components/ui/slider'
import { filesService } from '@/lib/api/services/files'
import {
  type MessageResponse,
  type PlayerMode,
  type PlayerState,
  playerService,
} from '@/lib/api/services/player'
import { soundsService } from '@/lib/api/services/sounds'
import { PLAYER_EVENTS, playerEvents } from '@/lib/events'
import { cn } from '@/lib/utils'
import {
  ArrowRight,
  ArrowRightToLine,
  Download,
  ExternalLink,
  List,
  Maximize2,
  Minimize2,
  MoreVertical,
  Music,
  Pause,
  Play,
  Repeat,
  Repeat1,
  Shuffle,
  SkipBack,
  SkipForward,
  Square,
  Volume2,
  VolumeX,
} from 'lucide-react'
import { useCallback, useEffect, useState } from 'react'
import { toast } from 'sonner'
import { Playlist } from './Playlist'
import { NumberFlowDuration } from '../ui/number-flow-duration'

export type PlayerDisplayMode = 'normal' | 'minimized' | 'maximized' | 'sidebar'

interface PlayerProps {
  className?: string
  onPlayerModeChange?: (mode: PlayerDisplayMode) => void
}

export function Player({ className, onPlayerModeChange }: PlayerProps) {
  const [state, setState] = useState<PlayerState>({
    status: 'stopped',
    mode: 'continuous',
    volume: 80,
    previous_volume: 80,
    position: 0,
  })
  const [displayMode, setDisplayMode] = useState<PlayerDisplayMode>(() => {
    // Initialize from localStorage or default to 'normal'
    if (typeof window !== 'undefined') {
      const saved = localStorage.getItem(
        'playerDisplayMode',
      ) as PlayerDisplayMode
      return saved &&
        ['normal', 'minimized', 'maximized', 'sidebar'].includes(saved)
        ? saved
        : 'normal'
    }
    return 'normal'
  })

  // Notify parent when display mode changes and save to localStorage
  useEffect(() => {
    onPlayerModeChange?.(displayMode)
    // Save to localStorage
    if (typeof window !== 'undefined') {
      localStorage.setItem('playerDisplayMode', displayMode)
    }
  }, [displayMode, onPlayerModeChange])
  const [showPlaylist, setShowPlaylist] = useState(false)
  const [isLoading, setIsLoading] = useState(false)

  // Load initial state
  useEffect(() => {
    const loadState = async () => {
      try {
        const initialState = await playerService.getState()
        setState(initialState)
      } catch (error) {
        console.error('Failed to load player state:', error)
      }
    }
    loadState()
  }, [])

  // Listen for player state updates
  useEffect(() => {
    const handlePlayerState = (...args: unknown[]) => {
      const newState = args[0] as PlayerState
      setState(newState)
    }

    playerEvents.on(PLAYER_EVENTS.PLAYER_STATE, handlePlayerState)

    return () => {
      playerEvents.off(PLAYER_EVENTS.PLAYER_STATE, handlePlayerState)
    }
  }, [])

  // Handle body scroll when in fullscreen
  useEffect(() => {
    if (displayMode === 'maximized') {
      // Disable body scroll
      document.body.style.overflow = 'hidden'
    } else {
      // Re-enable body scroll
      document.body.style.overflow = 'unset'
    }

    // Cleanup when component unmounts
    return () => {
      document.body.style.overflow = 'unset'
    }
  }, [displayMode])

  const executeAction = useCallback(
    async (
      action: () => Promise<void | MessageResponse>,
      actionName: string,
    ) => {
      setIsLoading(true)
      try {
        await action()
      } catch (error) {
        console.error(`Failed to ${actionName}:`, error)
        toast.error(`Failed to ${actionName}`)
      } finally {
        setIsLoading(false)
      }
    },
    [],
  )

  const handlePlayPause = useCallback(() => {
    if (state.status === 'playing') {
      executeAction(playerService.pause, 'pause')
    } else {
      executeAction(playerService.play, 'play')
    }
  }, [state.status, executeAction])

  const handleStop = useCallback(() => {
    executeAction(playerService.stop, 'stop')
  }, [executeAction])

  const handlePrevious = useCallback(() => {
    executeAction(playerService.previous, 'go to previous track')
  }, [executeAction])

  const handleNext = useCallback(() => {
    executeAction(playerService.next, 'go to next track')
  }, [executeAction])

  const handleSeek = useCallback(
    (position: number[]) => {
      const newPosition = position[0]
      executeAction(() => playerService.seek(newPosition), 'seek')
    },
    [executeAction],
  )

  const handleVolumeChange = useCallback(
    (volume: number[]) => {
      const newVolume = volume[0]
      executeAction(() => playerService.setVolume(newVolume), 'change volume')
    },
    [executeAction],
  )

  const handleMute = useCallback(() => {
    if (state.volume === 0) {
      // Unmute
      executeAction(playerService.unmute, 'unmute')
    } else {
      // Mute
      executeAction(playerService.mute, 'mute')
    }
  }, [state.volume, executeAction])

  const handleModeChange = useCallback(() => {
    const modes: PlayerMode[] = [
      'continuous',
      'loop',
      'loop_one',
      'random',
      'single',
    ]
    const currentIndex = modes.indexOf(state.mode)
    const nextMode = modes[(currentIndex + 1) % modes.length]
    executeAction(() => playerService.setMode(nextMode), 'change mode')
  }, [state.mode, executeAction])

  const handleDownloadSound = useCallback(async () => {
    if (!state.current_sound) return

    try {
      await filesService.downloadSound(state.current_sound.id)
      toast.success('Download started')
    } catch (error) {
      console.error('Failed to download sound:', error)
      toast.error('Failed to download sound')
    }
  }, [state.current_sound])

  const handleStopAllSounds = useCallback(async () => {
    try {
      await soundsService.stopSounds()
      toast.success('All sounds stopped')
    } catch (error) {
      console.error('Failed to stop all sounds:', error)
      toast.error('Failed to stop all sounds')
    }
  }, [])

  const getModeIcon = () => {
    switch (state.mode) {
      case 'continuous':
        return <ArrowRight className="h-4 w-4" />
      case 'loop':
        return <Repeat className="h-4 w-4" />
      case 'loop_one':
        return <Repeat1 className="h-4 w-4" />
      case 'random':
        return <Shuffle className="h-4 w-4" />
      default:
        return <ArrowRightToLine className="h-4 w-4" />
    }
  }

  const expandFromSidebar = useCallback(() => {
    setDisplayMode('normal')
  }, [])

  const getPlayerPosition = () => {
    switch (displayMode) {
      case 'minimized':
        return 'fixed bottom-4 right-4 z-50'
      case 'maximized':
        return 'fixed inset-0 z-50 bg-background'
      case 'sidebar':
        return 'hidden' // Hidden when in sidebar mode
      default:
        return 'fixed bottom-4 right-4 z-50'
    }
  }

  const renderMinimizedPlayer = () => (
    <Card className="w-48 bg-background/90 backdrop-blur-sm pt-0 pb-0">
      <CardContent className="p-2">
        <div className="flex items-center gap-1">
          <Button
            size="sm"
            variant="ghost"
            onClick={handlePrevious}
            disabled={isLoading}
            className="h-8 w-8 p-0"
          >
            <SkipBack className="h-4 w-4" />
          </Button>
          <Button
            size="sm"
            variant="ghost"
            onClick={handlePlayPause}
            disabled={isLoading}
            className="h-8 w-8 p-0"
          >
            {state.status === 'playing' ? (
              <Pause className="h-4 w-4" />
            ) : (
              <Play className="h-4 w-4" />
            )}
          </Button>
          <Button
            size="sm"
            variant="ghost"
            onClick={handleStop}
            disabled={isLoading}
            className="h-8 w-8 p-0"
          >
            <Square className="h-4 w-4" />
          </Button>
          <Button
            size="sm"
            variant="ghost"
            onClick={handleNext}
            disabled={isLoading}
            className="h-8 w-8 p-0"
          >
            <SkipForward className="h-4 w-4" />
          </Button>
          <Button
            size="sm"
            variant="ghost"
            onClick={() => setDisplayMode('normal')}
            className="h-8 w-8 p-0 ml-auto"
          >
            <Maximize2 className="h-4 w-4" />
          </Button>
        </div>
      </CardContent>
    </Card>
  )

  const renderNormalPlayer = () => (
    <Card className="w-80 bg-background/90 backdrop-blur-sm pt-3 pb-3">
      <CardContent className="pt-0 pb-0 pl-3 pr-3">
        {/* Window Controls */}
        <div className="flex items-center justify-end gap-1 pb-2">
          <Button
            size="sm"
            variant="ghost"
            onClick={() => setDisplayMode('sidebar')}
            className="h-6 w-6 p-0 hover:bg-muted"
            title="Minimize to Sidebar"
          >
            <Minimize2 className="h-3 w-3" />
          </Button>
          <Button
            size="sm"
            variant="ghost"
            onClick={() => setDisplayMode('maximized')}
            className="h-6 w-6 p-0 hover:bg-muted"
            title="Fullscreen"
          >
            <Maximize2 className="h-3 w-3" />
          </Button>
        </div>

        {/* Album Art / Thumbnail */}
        <div className="mb-4">
          {state.current_sound?.thumbnail ? (
            <div className="w-full aspect-auto bg-muted rounded-lg flex items-center justify-center overflow-hidden">
              <img
                src={filesService.getThumbnailUrl(state.current_sound.id)}
                alt={state.current_sound.name}
                className="w-full h-full object-cover"
                onError={e => {
                  // Hide image and show music icon if thumbnail fails to load
                  const target = e.target as HTMLImageElement
                  target.style.display = 'none'
                  const musicIcon = target.nextElementSibling as HTMLElement
                  if (musicIcon) musicIcon.style.display = 'block'
                }}
              />
              <Music
                className={cn(
                  'h-8 w-8 text-muted-foreground',
                  state.current_sound?.thumbnail ? 'hidden' : 'block',
                )}
              />
            </div>
          ) : null}
        </div>

        {/* Track Info */}
        <div className="mb-4 text-center">
          <div className="flex items-center justify-center gap-2">
            <h3 className="font-medium text-sm truncate">
              {state.current_sound?.name || 'No track selected'}
            </h3>
            {state.current_sound &&
              (state.current_sound.extract_url || state.current_sound.id) && (
                <DropdownMenu>
                  <DropdownMenuTrigger asChild>
                    <Button variant="ghost" size="sm" className="h-4 w-4 p-0">
                      <MoreVertical className="h-3 w-3" />
                    </Button>
                  </DropdownMenuTrigger>
                  <DropdownMenuContent align="start">
                    {state.current_sound.extract_url && (
                      <DropdownMenuItem asChild>
                        <a
                          href={state.current_sound.extract_url}
                          target="_blank"
                          rel="noopener noreferrer"
                          className="flex items-center gap-2"
                        >
                          <ExternalLink className="h-4 w-4" />
                          Source
                        </a>
                      </DropdownMenuItem>
                    )}
                    <DropdownMenuItem
                      onClick={handleDownloadSound}
                      className="flex items-center gap-2"
                    >
                      <Download className="h-4 w-4" />
                      File
                    </DropdownMenuItem>
                  </DropdownMenuContent>
                </DropdownMenu>
              )}
          </div>
        </div>

        {/* Progress Bar */}
        <div className="mb-4">
          <Progress
            value={(state.position / (state.duration || 1)) * 100}
            className="w-full h-2 cursor-pointer"
            onClick={e => {
              const rect = e.currentTarget.getBoundingClientRect()
              const clickX = e.clientX - rect.left
              const percentage = clickX / rect.width
              const newPosition = Math.round(percentage * (state.duration || 0))
              handleSeek([newPosition])
            }}
          />
          <div className="flex justify-between text-xs text-muted-foreground mt-1">
            <NumberFlowDuration duration={state.position} />
            <NumberFlowDuration duration={state.duration || 0} />
          </div>
        </div>

        {/* Main Controls */}
        <div className="flex items-center justify-center gap-2 mb-4">
          <Button
            size="sm"
            variant="ghost"
            onClick={handleModeChange}
            className="h-8 w-8 p-0"
            title={`Mode: ${state.mode.replace('_', ' ')}`}
          >
            {getModeIcon()}
          </Button>
          <Button
            size="sm"
            variant="ghost"
            onClick={handlePrevious}
            disabled={isLoading}
          >
            <SkipBack className="h-4 w-4" />
          </Button>
          <Button
            size="sm"
            onClick={handlePlayPause}
            disabled={isLoading}
            className="h-10 w-10 rounded-full"
          >
            {state.status === 'playing' ? (
              <Pause className="h-5 w-5" />
            ) : (
              <Play className="h-5 w-5" />
            )}
          </Button>
          <Button
            size="sm"
            variant="ghost"
            onClick={handleStop}
            disabled={isLoading}
          >
            <Square className="h-4 w-4" />
          </Button>
          <Button
            size="sm"
            variant="ghost"
            onClick={handleNext}
            disabled={isLoading}
          >
            <SkipForward className="h-4 w-4" />
          </Button>
          <Button
            size="sm"
            variant="ghost"
            onClick={() => setShowPlaylist(!showPlaylist)}
            className="h-8 w-8 p-0"
            title="Toggle Playlist"
          >
            <List className="h-4 w-4" />
          </Button>
        </div>

        {/* Secondary Controls */}
        <div className="flex items-center justify-between">
          <Badge variant="secondary" className="text-xs">
            {state.mode.replace('_', ' ')}
          </Badge>

          <div className="flex items-center gap-2">
            <Button
              size="sm"
              variant="ghost"
              onClick={handleMute}
              className="h-8 w-8 p-0"
            >
              {state.volume === 0 ? (
                <VolumeX className="h-4 w-4" />
              ) : (
                <Volume2 className="h-4 w-4" />
              )}
            </Button>
            <div className="w-16">
              <Slider
                value={[state.volume]}
                max={100}
                step={1}
                onValueChange={handleVolumeChange}
                className="w-full"
              />
            </div>
          </div>
        </div>

        {/* Playlist */}
        {showPlaylist && state.playlist && (
          <div className="mt-4 pt-4 border-t">
            <Playlist
              playlist={state.playlist}
              currentIndex={state.index}
              onTrackSelect={index =>
                executeAction(
                  () => playerService.playAtIndex(index),
                  'play track',
                )
              }
            />
          </div>
        )}
      </CardContent>
    </Card>
  )

  const renderMaximizedPlayer = () => (
    <div className="h-full flex flex-col bg-background/95 backdrop-blur-md">
      {/* Header */}
      <div className="p-4 border-b flex items-center justify-between">
        <h2 className="text-lg font-semibold">Now Playing</h2>
        <div className="flex items-center gap-2">
          <Button
            size="sm"
            variant="ghost"
            onClick={handleStopAllSounds}
            className="text-red-600 hover:text-red-700 hover:bg-red-50 dark:text-red-400 dark:hover:text-red-300 dark:hover:bg-red-950/50"
          >
            <Square className="h-4 w-4 mr-2 fill-current" />
            Stop All Sounds
          </Button>
          <Button
            size="sm"
            variant="ghost"
            onClick={() => setDisplayMode('normal')}
          >
            <Minimize2 className="h-4 w-4 mr-2" />
            Exit Fullscreen
          </Button>
        </div>
      </div>

      <div className="flex-1 flex">
        {/* Main Player Area */}
        <div className="flex-1 flex flex-col items-center justify-center p-8">
          {/* Large Album Art */}
          <div className="max-w-300 max-h-200 aspect-auto bg-muted rounded-lg flex items-center justify-center overflow-hidden mb-8">
            {state.current_sound?.thumbnail ? (
              <img
                src={filesService.getThumbnailUrl(state.current_sound.id)}
                alt={state.current_sound.name}
                className="w-full h-full object-cover"
                onError={e => {
                  // Hide image and show music icon if thumbnail fails to load
                  const target = e.target as HTMLImageElement
                  target.style.display = 'none'
                  const musicIcon = target.nextElementSibling as HTMLElement
                  if (musicIcon) musicIcon.style.display = 'block'
                }}
              />
            ) : null}
            <Music
              className={cn(
                'h-32 w-32 text-muted-foreground',
                state.current_sound?.thumbnail ? 'hidden' : 'block',
              )}
            />
          </div>

          {/* Track Info */}
          <div className="text-center mb-8">
            <div className="flex items-center justify-center gap-3 mb-2">
              <h1 className="text-2xl font-bold">
                {state.current_sound?.name || 'No track selected'}
              </h1>
              {state.current_sound &&
                (state.current_sound.extract_url || state.current_sound.id) && (
                  <DropdownMenu>
                    <DropdownMenuTrigger asChild>
                      <Button variant="ghost" size="sm" className="h-6 w-6 p-0">
                        <MoreVertical className="h-4 w-4" />
                      </Button>
                    </DropdownMenuTrigger>
                    <DropdownMenuContent align="start">
                      {state.current_sound.extract_url && (
                        <DropdownMenuItem asChild>
                          <a
                            href={state.current_sound.extract_url}
                            target="_blank"
                            rel="noopener noreferrer"
                            className="flex items-center gap-2"
                          >
                            <ExternalLink className="h-4 w-4" />
                            Source
                          </a>
                        </DropdownMenuItem>
                      )}
                      <DropdownMenuItem
                        onClick={handleDownloadSound}
                        className="flex items-center gap-2"
                      >
                        <Download className="h-4 w-4" />
                        File
                      </DropdownMenuItem>
                    </DropdownMenuContent>
                  </DropdownMenu>
                )}
            </div>
          </div>

          {/* Progress Bar */}
          <div className="w-full max-w-md mb-8">
            <Progress
              value={(state.position / (state.duration || 1)) * 100}
              className="w-full h-3 cursor-pointer"
              onClick={e => {
                const rect = e.currentTarget.getBoundingClientRect()
                const clickX = e.clientX - rect.left
                const percentage = clickX / rect.width
                const newPosition = Math.round(
                  percentage * (state.duration || 0),
                )
                handleSeek([newPosition])
              }}
            />
            <div className="flex justify-between text-sm text-muted-foreground mt-2">
              <NumberFlowDuration duration={state.position} />
              <NumberFlowDuration duration={state.duration || 0} />
            </div>
          </div>

          {/* Large Controls */}
          <div className="flex items-center gap-4 mb-8">
            <Button
              size="lg"
              variant="ghost"
              onClick={handlePrevious}
              disabled={isLoading}
            >
              <SkipBack className="h-6 w-6" />
            </Button>
            <Button
              size="lg"
              onClick={handlePlayPause}
              disabled={isLoading}
              className="h-16 w-16 rounded-full"
            >
              {state.status === 'playing' ? (
                <Pause className="h-8 w-8" />
              ) : (
                <Play className="h-8 w-8" />
              )}
            </Button>
            <Button
              size="lg"
              variant="ghost"
              onClick={handleStop}
              disabled={isLoading}
            >
              <Square className="h-6 w-6" />
            </Button>
            <Button
              size="lg"
              variant="ghost"
              onClick={handleNext}
              disabled={isLoading}
            >
              <SkipForward className="h-6 w-6" />
            </Button>
          </div>

          {/* Secondary Controls */}
          <div className="flex items-center gap-6">
            <div className="flex items-center gap-2">
              <Button size="sm" variant="ghost" onClick={handleModeChange}>
                {getModeIcon()}
              </Button>
              <Badge variant="secondary">{state.mode.replace('_', ' ')}</Badge>
            </div>

            <div className="flex items-center gap-2">
              <Button size="sm" variant="ghost" onClick={handleMute}>
                {state.volume === 0 ? (
                  <VolumeX className="h-4 w-4" />
                ) : (
                  <Volume2 className="h-4 w-4" />
                )}
              </Button>
              <div className="w-24">
                <Slider
                  value={[state.volume]}
                  max={100}
                  step={1}
                  onValueChange={handleVolumeChange}
                  className="w-full"
                />
              </div>
              <span className="text-sm text-muted-foreground w-8">
                {Math.round(state.volume)}%
              </span>
            </div>
          </div>
        </div>

        {/* Playlist Sidebar */}
        {state.playlist && (
          <div className="w-96 border-l bg-muted/10 backdrop-blur-sm">
            <div className="p-4 border-b">
              <h3 className="font-semibold">Playlist</h3>
              <p className="text-sm text-muted-foreground">
                {state.playlist.sounds.length} tracks
              </p>
            </div>
            <div className="p-4">
              <Playlist
                playlist={state.playlist}
                currentIndex={state.index}
                onTrackSelect={index =>
                  executeAction(
                    () => playerService.playAtIndex(index),
                    'play track',
                  )
                }
                variant="maximized"
              />
            </div>
          </div>
        )}
      </div>
    </div>
  )

  // Expose expand function for external use
  useEffect(() => {
    // Store expand function globally so sidebar can access it
    const windowWithExpand = window as unknown as {
      __expandPlayerFromSidebar?: () => void
    }
    windowWithExpand.__expandPlayerFromSidebar = expandFromSidebar
    return () => {
      delete windowWithExpand.__expandPlayerFromSidebar
    }
  }, [expandFromSidebar])

  if (!state) return null

  return (
    <div className={cn(getPlayerPosition(), className)}>
      {displayMode === 'minimized' && renderMinimizedPlayer()}
      {displayMode === 'normal' && renderNormalPlayer()}
      {displayMode === 'maximized' && renderMaximizedPlayer()}
    </div>
  )
}
