import { createContext, useContext, useState, useEffect, type ReactNode } from 'react'
import { useSocket } from './SocketContext'
import { apiService } from '@/services/api'

export interface Track {
  id: string
  title: string
  artist?: string
  duration: number
  thumbnail?: string
  url: string
}

export type PlayMode = 'continuous' | 'loop-playlist' | 'loop-one' | 'random' | 'single'

interface MusicPlayerContextType {
  // Playback state
  isPlaying: boolean
  currentTime: number
  duration: number
  volume: number
  isMuted: boolean
  playMode: PlayMode
  
  // Current track and playlist
  currentTrack: Track | null
  playlist: Track[]
  currentTrackIndex: number
  
  // UI state
  isMinimized: boolean
  isUltraMinimized: boolean
  showPlaylist: boolean
  
  // Actions
  play: () => void
  pause: () => void
  stop: () => void
  togglePlayPause: () => void
  seekTo: (time: number) => void
  setVolume: (volume: number) => void
  toggleMute: () => void
  setPlayMode: (mode: PlayMode) => void
  nextTrack: () => void
  previousTrack: () => void
  playTrack: (trackIndex: number) => void
  loadPlaylist: (playlistId: number) => void
  addToPlaylist: (track: Track) => void
  removeFromPlaylist: (trackId: string) => void
  clearPlaylist: () => void
  toggleMaximize: () => void
  toggleUltraMinimize: () => void
  togglePlaylistVisibility: () => void
}

const MusicPlayerContext = createContext<MusicPlayerContextType | undefined>(undefined)

export function useMusicPlayer() {
  const context = useContext(MusicPlayerContext)
  if (context === undefined) {
    throw new Error('useMusicPlayer must be used within a MusicPlayerProvider')
  }
  return context
}

interface MusicPlayerProviderProps {
  children: ReactNode
}

export function MusicPlayerProvider({ children }: MusicPlayerProviderProps) {
  const { socket } = useSocket()
  
  // Playback state
  const [isPlaying, setIsPlaying] = useState(false)
  const [currentTime, setCurrentTime] = useState(0)
  const [duration, setDuration] = useState(0)
  const [volume, setVolumeState] = useState(80)
  const [isMuted, setIsMuted] = useState(false)
  const [playMode, setPlayModeState] = useState<PlayMode>('continuous')
  
  // Playlist state
  const [currentTrackIndex, setCurrentTrackIndex] = useState(0)
  const [playlist, setPlaylist] = useState<Track[]>([])
  const [currentPlaylistId, setCurrentPlaylistId] = useState<number | null>(null)
  const [currentTrack, setCurrentTrack] = useState<Track | null>(null)
  
  // UI state
  const [isMinimized, setIsMinimized] = useState(true)
  const [isUltraMinimized, setIsUltraMinimized] = useState(false)
  const [showPlaylist, setShowPlaylist] = useState(false)

  // Fetch initial player state on mount
  useEffect(() => {
    const fetchInitialState = async () => {
      try {
        const response = await apiService.get('/api/player/state')
        const state = await response.json()
        
        // Update all state from backend
        setIsPlaying(state.is_playing || false)
        setCurrentTime(state.current_time || 0)
        setDuration(state.duration || 0)
        setVolumeState(state.volume || 80)
        setIsMuted(state.volume === 0)
        setPlayModeState(state.play_mode || 'continuous')
        setCurrentTrackIndex(state.current_track_index || 0)
        setPlaylist(state.playlist || [])
        setCurrentPlaylistId(state.playlist_id || null)
        setCurrentTrack(state.current_track || null)
        
      } catch (error) {
        console.error('Failed to fetch initial player state:', error)
      }
    }

    fetchInitialState()
  }, [])

  // Listen for real-time player updates via SocketIO
  useEffect(() => {
    if (!socket) {
      return;
    }

    const handlePlayerStateUpdate = (state: any) => {
      setIsPlaying(state.is_playing || false)
      setCurrentTime(state.current_time || 0)
      setDuration(state.duration || 0)
      setVolumeState(state.volume || 80)
      setIsMuted(state.volume === 0)
      setPlayModeState(state.play_mode || 'continuous')
      setCurrentTrackIndex(state.current_track_index || 0)
      setPlaylist(state.playlist || [])
      setCurrentPlaylistId(state.playlist_id || null)
      setCurrentTrack(state.current_track || null)
    }

    socket.on('player_state_update', handlePlayerStateUpdate)

    return () => {
      socket.off('player_state_update', handlePlayerStateUpdate)
    }
  }, [socket])

  const play = async () => {
    try {
      await apiService.post('/api/player/play')
    } catch (error) {
      console.error('Failed to play:', error)
    }
  }

  const pause = async () => {
    try {
      await apiService.post('/api/player/pause')
    } catch (error) {
      console.error('Failed to pause:', error)
    }
  }

  const stop = async () => {
    try {
      await apiService.post('/api/player/stop')
    } catch (error) {
      console.error('Failed to stop:', error)
    }
  }

  const togglePlayPause = async () => {
    if (isPlaying) {
      await pause()
    } else {
      await play()
    }
  }

  const seekTo = async (time: number) => {
    try {
      const position = duration > 0 ? time / duration : 0
      await apiService.post('/api/player/seek', { position })
    } catch (error) {
      console.error('Failed to seek:', error)
    }
  }

  const setVolume = async (newVolume: number) => {
    try {
      await apiService.post('/api/player/volume', { volume: newVolume })
    } catch (error) {
      console.error('Failed to set volume:', error)
    }
  }

  const toggleMute = async () => {
    try {
      const newVolume = isMuted ? 80 : 0
      await apiService.post('/api/player/volume', { volume: newVolume })
    } catch (error) {
      console.error('Failed to toggle mute:', error)
    }
  }

  const nextTrack = async () => {
    try {
      await apiService.post('/api/player/next')
    } catch (error) {
      console.error('Failed to skip to next track:', error)
    }
  }

  const previousTrack = async () => {
    try {
      await apiService.post('/api/player/previous')
    } catch (error) {
      console.error('Failed to skip to previous track:', error)
    }
  }

  const playTrack = async (trackIndex: number) => {
    try {
      await apiService.post('/api/player/play-track', { index: trackIndex })
    } catch (error) {
      console.error('Failed to play track:', error)
    }
  }

  const loadPlaylist = async (playlistId: number) => {
    try {
      await apiService.post('/api/player/playlist', { playlist_id: playlistId })
    } catch (error) {
      console.error('Failed to load playlist:', error)
    }
  }

  const addToPlaylist = (track: Track) => {
    // This would need to be implemented via API
    console.log('Adding to playlist not yet implemented')
  }

  const removeFromPlaylist = (trackId: string) => {
    // This would need to be implemented via API
    console.log('Removing from playlist not yet implemented')
  }

  const clearPlaylist = () => {
    // This would need to be implemented via API
    console.log('Clearing playlist not yet implemented')
  }

  const setPlayMode = async (mode: PlayMode) => {
    try {
      await apiService.post('/api/player/mode', { mode })
    } catch (error) {
      console.error('Failed to set play mode:', error)
    }
  }

  const toggleMaximize = () => {
    setIsMinimized(!isMinimized)
    setIsUltraMinimized(false)  // When maximizing, exit ultra-minimize mode
  }

  const toggleUltraMinimize = () => {
    setIsUltraMinimized(!isUltraMinimized)
    if (!isUltraMinimized) {
      setIsMinimized(true)  // When ultra-minimizing, ensure we're in minimized mode
    }
  }

  const togglePlaylistVisibility = () => {
    setShowPlaylist(!showPlaylist)
  }

  const value: MusicPlayerContextType = {
    // Playback state
    isPlaying,
    currentTime,
    duration,
    volume,
    isMuted,
    playMode,
    
    // Current track and playlist
    currentTrack,
    playlist,
    currentTrackIndex,
    
    // UI state
    isMinimized,
    isUltraMinimized,
    showPlaylist,
    
    // Actions
    play,
    pause,
    stop,
    togglePlayPause,
    seekTo,
    setVolume,
    toggleMute,
    setPlayMode,
    nextTrack,
    previousTrack,
    playTrack,
    loadPlaylist,
    addToPlaylist,
    removeFromPlaylist,
    clearPlaylist,
    toggleMaximize,
    toggleUltraMinimize,
    togglePlaylistVisibility,
  }

  return (
    <MusicPlayerContext.Provider value={value}>
      {children}
    </MusicPlayerContext.Provider>
  )
}