import type { Song } from '~/types/song'
import type { PlayerMode, RepeatMode } from '~/types/player'

export const usePlayerStore = defineStore('player', () => {
  // State
  const isPlaying = ref(false)
  const currentSong = ref<Song | null>(null)
  const currentTime = ref(0)
  const duration = ref(0)
  const volume = ref(0.8)
  const mode = ref<PlayerMode>('guided')
  const repeatMode = ref<RepeatMode>('none')
  const isShuffled = ref(false)
  const playlist = ref<Song[]>([])
  const queue = ref<Song[]>([])
  const isExpanded = ref(false)

  // Computed
  const progress = computed(() => {
    if (duration.value === 0) return 0
    return (currentTime.value / duration.value) * 100
  })

  const formattedCurrentTime = computed(() => formatTime(currentTime.value))
  const formattedDuration = computed(() => formatTime(duration.value))
  const isGuidedMode = computed(() => mode.value === 'guided')

  const currentIndex = computed(() => {
    if (!currentSong.value) return -1
    return playlist.value.findIndex(s => s.id === currentSong.value!.id)
  })

  const hasNext = computed(() => {
    if (repeatMode.value === 'all') return playlist.value.length > 0
    return currentIndex.value < playlist.value.length - 1
  })

  const hasPrev = computed(() => {
    return currentIndex.value > 0
  })

  // Actions
  function setSong(song: Song) {
    currentSong.value = song
    currentTime.value = 0
    duration.value = song.duration
  }

  function setPlaylist(songs: Song[]) {
    playlist.value = songs
  }

  function setMode(newMode: PlayerMode) {
    mode.value = newMode
  }

  function togglePlay() {
    isPlaying.value = !isPlaying.value
  }

  function play() {
    isPlaying.value = true
  }

  function pause() {
    isPlaying.value = false
  }

  function setCurrentTime(time: number) {
    currentTime.value = time
  }

  function setDuration(dur: number) {
    duration.value = dur
  }

  function setVolume(vol: number) {
    volume.value = Math.max(0, Math.min(1, vol))
  }

  function toggleRepeat() {
    const modes: RepeatMode[] = ['none', 'all', 'one']
    const idx = modes.indexOf(repeatMode.value)
    repeatMode.value = modes[(idx + 1) % modes.length]
  }

  function toggleShuffle() {
    isShuffled.value = !isShuffled.value
  }

  function toggleExpanded() {
    isExpanded.value = !isExpanded.value
  }

  function nextSong(): Song | null {
    if (playlist.value.length === 0) return null

    if (repeatMode.value === 'one') {
      currentTime.value = 0
      return currentSong.value
    }

    let nextIdx = currentIndex.value + 1
    if (nextIdx >= playlist.value.length) {
      if (repeatMode.value === 'all') {
        nextIdx = 0
      }
      else {
        pause()
        return null
      }
    }

    const song = playlist.value[nextIdx]
    setSong(song)
    return song
  }

  function prevSong(): Song | null {
    if (playlist.value.length === 0) return null

    // If more than 3 seconds in, restart current song
    if (currentTime.value > 3) {
      currentTime.value = 0
      return currentSong.value
    }

    let prevIdx = currentIndex.value - 1
    if (prevIdx < 0) {
      if (repeatMode.value === 'all') {
        prevIdx = playlist.value.length - 1
      }
      else {
        currentTime.value = 0
        return currentSong.value
      }
    }

    const song = playlist.value[prevIdx]
    setSong(song)
    return song
  }

  return {
    // State
    isPlaying,
    currentSong,
    currentTime,
    duration,
    volume,
    mode,
    repeatMode,
    isShuffled,
    playlist,
    queue,
    isExpanded,
    // Computed
    progress,
    formattedCurrentTime,
    formattedDuration,
    isGuidedMode,
    currentIndex,
    hasNext,
    hasPrev,
    // Actions
    setSong,
    setPlaylist,
    setMode,
    togglePlay,
    play,
    pause,
    setCurrentTime,
    setDuration,
    setVolume,
    toggleRepeat,
    toggleShuffle,
    toggleExpanded,
    nextSong,
    prevSong,
  }
})

function formatTime(seconds: number): string {
  const mins = Math.floor(seconds / 60)
  const secs = Math.floor(seconds % 60)
  return `${mins}:${secs.toString().padStart(2, '0')}`
}
