import type { Song } from '~/types/song'

let audio: HTMLAudioElement | null = null
let animationFrameId: number | null = null
// Track which milestones have been fired for the current song
const firedMilestones = new Set<number>()

export function useAudioPlayer() {
  const store = usePlayerStore()
  const { trackAudioPlay, trackAudioComplete, trackAudioProgress } = useTracking()

  function getAudio(): HTMLAudioElement {
    if (!audio) {
      audio = new Audio()
      audio.preload = 'metadata'
      audio.volume = store.volume

      audio.addEventListener('loadedmetadata', () => {
        store.setDuration(audio!.duration)
      })

      audio.addEventListener('ended', () => {
        if (store.currentSong) {
          trackAudioComplete(store.currentSong.id, store.currentSong.title)
        }
        firedMilestones.clear()
        const next = store.nextSong()
        if (next) {
          loadAndPlay(next)
        }
      })

      audio.addEventListener('error', (e) => {
        console.error('Audio error:', e)
        store.pause()
      })
    }
    return audio
  }

  function startTimeUpdate() {
    if (animationFrameId) return
    const update = () => {
      if (audio && !audio.paused) {
        store.setCurrentTime(audio.currentTime)
        // Track progress milestones (25 / 50 / 75 %)
        if (audio.duration > 0 && store.currentSong) {
          const pct = (audio.currentTime / audio.duration) * 100
          for (const milestone of [25, 50, 75] as const) {
            if (pct >= milestone && !firedMilestones.has(milestone)) {
              firedMilestones.add(milestone)
              trackAudioProgress(store.currentSong.id, milestone)
            }
          }
        }
      }
      animationFrameId = requestAnimationFrame(update)
    }
    animationFrameId = requestAnimationFrame(update)
  }

  function stopTimeUpdate() {
    if (animationFrameId) {
      cancelAnimationFrame(animationFrameId)
      animationFrameId = null
    }
  }

  async function loadAndPlay(song: Song) {
    const el = getAudio()
    store.setSong(song)
    firedMilestones.clear()

    // Try OGG first, fall back to MP3
    const oggPath = song.file.replace(/\.mp3$/, '.ogg')
    const canOgg = el.canPlayType('audio/ogg; codecs=vorbis')

    el.src = canOgg ? oggPath : song.file
    el.volume = store.volume

    try {
      await el.play()
      store.play()
      startTimeUpdate()
      trackAudioPlay(song.id, song.title)
    }
    catch {
      // If OGG failed, try MP3
      if (el.src !== song.file) {
        el.src = song.file
        try {
          await el.play()
          store.play()
          startTimeUpdate()
          trackAudioPlay(song.id, song.title)
        }
        catch (err) {
          console.error('Playback failed:', err)
        }
      }
    }
  }

  function pause() {
    getAudio().pause()
    store.pause()
    stopTimeUpdate()
  }

  function resume() {
    const el = getAudio()
    if (el.src) {
      el.play()
      store.play()
      startTimeUpdate()
    }
  }

  function togglePlayPause() {
    if (store.isPlaying) {
      pause()
    }
    else {
      resume()
    }
  }

  function seek(time: number) {
    const el = getAudio()
    el.currentTime = time
    store.setCurrentTime(time)
  }

  function setVolume(vol: number) {
    store.setVolume(vol)
    getAudio().volume = store.volume
  }

  function playNext() {
    const song = store.nextSong()
    if (song) loadAndPlay(song)
  }

  function playPrev() {
    const song = store.prevSong()
    if (song) {
      loadAndPlay(song)
    }
  }

  // Watch volume changes from store
  watch(() => store.volume, (vol) => {
    if (audio) audio.volume = vol
  })

  return {
    loadAndPlay,
    pause,
    resume,
    togglePlayPause,
    seek,
    setVolume,
    playNext,
    playPrev,
    getAudio,
  }
}
