<template>
  <div>
    <!-- Aurora Background -->
    <AuroraBackground 
      :is-playing="isPlaying" 
      :current-track="currentTrack"
    />

    <!-- Main Container -->
    <MainContainer
      :current-track="currentTrack"
      :is-playing="isPlaying"
      :filtered-count="filteredCount"
      @shuffle-changed="handleShuffleChanged"
      @repeat-changed="handleRepeatChanged"
      @search="handleSearch"
    >
      <!-- Track List -->
      <TrackList 
        :tracks="tracks"
        :display-tracks="displayTracks"
        :current-track="currentTrack"
        :is-playing="isPlaying"
        :loading="loading"
        :loading-track="loadingTrack"
        :failed-tracks="failedTracks"
        @track-selected="handleTrackSelected"
      />
    </MainContainer>

    <!-- Music Controls -->
    <MusicControls
      :current-track="currentTrack"
      :is-playing="isPlaying"
      :current-time="currentTime"
      :duration="duration"
      :volume="volume"
      @previous="previousTrack"
      @next="nextTrack"
      @toggle-play="togglePlay"
      @seek="seekTo"
      @volume-change="setVolume"
    />

    <!-- Audio Element -->
    <audio 
      ref="audioPlayer"
      @loadedmetadata="onLoadedMetadata"
      @timeupdate="onTimeUpdate"
      @ended="onTrackEnded"
      @canplay="onCanPlay"
      @error="onAudioError"
    ></audio>
  </div>
</template>

<script setup>
// Disable SSR for this page since it uses browser APIs and audio elements
definePageMeta({
  ssr: false
})

import { ref, onMounted, onUnmounted, computed, watch } from 'vue'
import { useLocalStorage } from '@vueuse/core'
import { useMusicStore } from '~/stores/music'
import { useToastStore } from '~/stores/toast'

// Import components
import AuroraBackground from '~/components/AuroraBackground.client.vue'
import MainContainer from '~/components/MainContainer.client.vue'
import TrackList from '~/components/TrackList.client.vue'
import MusicControls from '~/components/MusicControls.client.vue'

// Store
const musicStore = useMusicStore()
const toastStore = useToastStore()

// Reactive state
const tracks = computed(() => musicStore.tracks)
const currentTrack = ref(null)
const currentTrackIndex = ref(0)
const isPlaying = ref(false)
const currentTime = ref(0)
const duration = ref(0)
const volume = ref(0.7)
const loading = ref(true)
const loadingTrack = ref(null)
const failedTracks = ref(new Set()) // Track failed tracks

// Theme (handled by ThemeToggle component now)
const isDark = useLocalStorage('theme-dark', false)

// Playback modes
const isShuffled = useLocalStorage('shuffle', false)
const repeatMode = useLocalStorage('repeat', 'none') // 'none', 'all', 'one'
const shuffledIndices = ref([])

// Search state
const searchQuery = ref('')

// Error tracking
const consecutiveErrors = ref(0)

// Refs
const audioPlayer = ref(null)

// Computed - removed progressPercent as it's not used in this component

const displayTracks = computed(() => {
  let tracksToDisplay = tracks.value

  // Aplicar filtro de búsqueda
  if (searchQuery.value.length > 0) {
    tracksToDisplay = tracksToDisplay.filter(track =>
      track.name.toLowerCase().includes(searchQuery.value)
    )
  }

  // Aplicar shuffle si está activado
  if (isShuffled.value && shuffledIndices.value.length > 0) {
    const shuffledTracks = shuffledIndices.value
      .map(index => tracks.value[index])
      .filter(track =>
        searchQuery.value.length === 0 ||
        track.name.toLowerCase().includes(searchQuery.value)
      )
    return shuffledTracks
  }

  return tracksToDisplay
})

const filteredCount = computed(() => {
  if (searchQuery.value.length === 0) return null
  return displayTracks.value.length
})

// Methods
const loadTracks = async () => {
  try {
    await musicStore.fetchTracks()
    if (tracks.value.length > 0) {
      generateShuffledIndices()
      loading.value = false
      return
    }
  } catch (error) {
    console.warn('Failed to load tracks from server, will fallback to cache:', error)
  }
  // Fallback to cached tracks when offline or server fails
  const cached = await musicStore.loadCachedTracks()
  if (cached.length > 0) {
    // Use cached list locally by overwriting store tracks for session display
    musicStore.tracks = cached
    generateShuffledIndices()
  }
  loading.value = false
}

const generateShuffledIndices = () => {
  shuffledIndices.value = Array.from({ length: tracks.value.length }, (_, i) => i)
  // Fisher-Yates shuffle algorithm for truly random results
  for (let i = shuffledIndices.value.length - 1; i > 0; i--) {
    const j = Math.floor(Math.random() * (i + 1))
    ;[shuffledIndices.value[i], shuffledIndices.value[j]] = [shuffledIndices.value[j], shuffledIndices.value[i]]
  }
}

const playTrack = async (track, index) => {
  // Limpiar el estado de error de esta canción si existe
  // (permite reintentar canciones que fallaron previamente)
  if (failedTracks.value.has(track.name)) {
    console.log('[PlayTrack] Clearing previous error state for:', track.name)
    failedTracks.value.delete(track.name)
  }

  loadingTrack.value = track.name
  currentTrack.value = track
  currentTrackIndex.value = isShuffled.value
    ? shuffledIndices.value.indexOf(tracks.value.indexOf(track))
    : index

  if (audioPlayer.value) {
    // Clear previous audio data
    if (audioPlayer.value.currentBlobUrl) {
      URL.revokeObjectURL(audioPlayer.value.currentBlobUrl)
      audioPlayer.value.currentBlobUrl = null
    }
    
    try {
      // Try IndexedDB cached version first
      const cachedBlob = await musicStore.getCachedBlob(track.name)
      if (cachedBlob) {
        const audioUrl = URL.createObjectURL(cachedBlob)
        audioPlayer.value.currentBlobUrl = audioUrl
        audioPlayer.value.src = audioUrl
        audioPlayer.value.load()
        audioPlayer.value.addEventListener('canplay', () => {
          loadingTrack.value = null
          audioPlayer.value.play()
        }, { once: true })
        return
      }

      // Fetch and preload entire song into memory
      const encodedName = encodeURIComponent(track.name)
      const response = await fetch(`/api/music/${encodedName}`, {
        credentials: 'include',
        redirect: 'error' // No seguir redirects de Authentik - convertir en error
      })

      // Check for authentication errors
      if (!response.ok) {
        const errorMsg = `HTTP ${response.status}`

        // If auth error, propagate to music store for auth indicator to detect
        if (response.status === 401 || response.status === 403) {
          console.warn('[PlayTrack] Authentication error:', response.status)
          musicStore.error = `${errorMsg}: Unauthorized - Please log in`
        }

        throw new Error(errorMsg)
      }

      const blob = await response.blob()
      const audioUrl = URL.createObjectURL(blob)

      // No auto-cache: solo reproducir, el usuario decide cachear desde menú
      // Store reference to revoke later
      audioPlayer.value.currentBlobUrl = audioUrl
      audioPlayer.value.src = audioUrl
      console.log('Preloaded track into memory:', track.name)
      audioPlayer.value.load()

      // Auto-play when ready
      audioPlayer.value.addEventListener('canplay', () => {
        loadingTrack.value = null
        audioPlayer.value.play()
      }, { once: true })
    } catch (error) {
      console.error('Failed to preload track:', error)

      // Mark track as failed
      failedTracks.value.add(track.name)
      loadingTrack.value = null

      // Don't try fallback streaming if it's an auth error (it will fail too)
      // Esto incluye errores de redirect de Authentik
      if (error.message && (error.message.includes('401') ||
                           error.message.includes('403') ||
                           error.message.includes('Failed to fetch') ||
                           (error.name === 'TypeError' && error.message.includes('redirect')))) {
        console.warn('[PlayTrack] Skipping fallback due to auth error:', error.message)
        musicStore.error = error.message || 'Authentication error'
        return
      }

      // Try fallback to streaming
      const encodedName = encodeURIComponent(track.name)
      audioPlayer.value.src = `/api/music/${encodedName}`
      audioPlayer.value.load()

      // Auto-play when ready (fallback)
      audioPlayer.value.addEventListener('canplay', () => {
        loadingTrack.value = null
        audioPlayer.value.play()
      }, { once: true })
    }
  }
}

const togglePlay = () => {
  if (!audioPlayer.value || !currentTrack.value) return
  
  if (isPlaying.value) {
    audioPlayer.value.pause()
  } else {
    audioPlayer.value.play()
  }
}

const nextTrack = () => {
  if (tracks.value.length === 0) return
  
  let nextIndex
  const trackList = isShuffled.value ? shuffledIndices.value : Array.from({ length: tracks.value.length }, (_, i) => i)
  
  if (repeatMode.value === 'one') {
    // Repeat current track
    nextIndex = currentTrackIndex.value
  } else {
    // Move to next track
    nextIndex = (currentTrackIndex.value + 1) % trackList.length
    
    if (nextIndex === 0 && repeatMode.value === 'none') {
      // End of playlist and no repeat
      isPlaying.value = false
      return
    }
  }
  
  const actualIndex = isShuffled.value ? trackList[nextIndex] : nextIndex
  const track = tracks.value[actualIndex]
  
  playTrack(track, actualIndex)
  
  setTimeout(() => {
    if (audioPlayer.value) {
      audioPlayer.value.play()
    }
  }, 100)
}

const previousTrack = () => {
  if (tracks.value.length === 0) return
  
  const trackList = isShuffled.value ? shuffledIndices.value : Array.from({ length: tracks.value.length }, (_, i) => i)
  const prevIndex = currentTrackIndex.value === 0 ? trackList.length - 1 : currentTrackIndex.value - 1
  
  const actualIndex = isShuffled.value ? trackList[prevIndex] : prevIndex
  const track = tracks.value[actualIndex]
  
  playTrack(track, actualIndex)
  
  setTimeout(() => {
    if (audioPlayer.value) {
      audioPlayer.value.play()
    }
  }, 100)
}

const handleShuffleChanged = (shuffled) => {
  isShuffled.value = shuffled
  if (shuffled) {
    generateShuffledIndices()
  }
}

const handleRepeatChanged = (mode) => {
  repeatMode.value = mode
}

const handleSearch = (query) => {
  searchQuery.value = query
}

const handleTrackSelected = ({ track, index }) => {
  playTrack(track, index)
}

// Removed formatTime function as it's not used in this component - it's defined in child components where needed

const seekTo = (newTime) => {
  if (!audioPlayer.value) return
  audioPlayer.value.currentTime = newTime
}

const setVolume = (newVolume) => {
  volume.value = Math.max(0, Math.min(1, newVolume))
  
  if (audioPlayer.value) {
    audioPlayer.value.volume = volume.value
  }
}

// Audio event handlers
const onLoadedMetadata = () => {
  if (audioPlayer.value) {
    duration.value = audioPlayer.value.duration
    audioPlayer.value.volume = volume.value
  }
}

const onAudioError = (error) => {
  console.error('Audio error:', error)
  console.error('Failed to load:', currentTrack.value?.name)

  // Mark track as failed
  if (currentTrack.value) {
    failedTracks.value.add(currentTrack.value.name)
  }

  // Clear loading state
  loadingTrack.value = null

  // Increment consecutive error counter
  consecutiveErrors.value++

  // Check if we've hit 2 consecutive errors
  if (consecutiveErrors.value >= 2) {
    // Stop trying and show error toast
    toastStore.error('No se pudieron cargar 2 canciones consecutivas. Reproducción detenida.', 4000)
    isPlaying.value = false
    consecutiveErrors.value = 0 // Reset counter
    console.warn('[AudioError] Stopped playback after 2 consecutive failures')
    return
  }

  // Try next track if we haven't hit the limit
  console.log(`[AudioError] Attempting next track (consecutive errors: ${consecutiveErrors.value})`)
  setTimeout(() => {
    nextTrack()
  }, 1000) // Small delay before trying next track
}

const onTimeUpdate = () => {
  if (audioPlayer.value) {
    currentTime.value = audioPlayer.value.currentTime
  }
}

const onTrackEnded = () => {
  isPlaying.value = false
  nextTrack()
}

const onCanPlay = () => {
  // Track is ready to play - reset error counter
  consecutiveErrors.value = 0
}

// Watchers
watch(isDark, (newValue) => {
  if (import.meta.client) {
    document.documentElement.setAttribute('data-theme', newValue ? 'dark' : 'light')
  }
}, { immediate: true })

// Limpiar errores cuando se restablece la autenticación
watch(() => musicStore.error, (newError, oldError) => {
  // Si el error se limpia (de error a null), limpiar todos los errores de canciones
  if (oldError && !newError && failedTracks.value.size > 0) {
    console.log('[PlayTrack] Auth restored, clearing all failed tracks')
    failedTracks.value.clear()
  }
})

// Limpiar errores cuando se cargan canciones exitosamente
watch(() => musicStore.tracks.length, (newLength, oldLength) => {
  // Si se cargan canciones exitosamente, limpiar errores
  if (newLength > 0 && newLength !== oldLength && failedTracks.value.size > 0) {
    console.log('[PlayTrack] Tracks loaded successfully, clearing failed tracks')
    failedTracks.value.clear()
  }
})

watch(() => audioPlayer.value, (newAudio) => {
  if (newAudio) {
    newAudio.addEventListener('play', () => { isPlaying.value = true })
    newAudio.addEventListener('pause', () => { isPlaying.value = false })
  }
})

// Cleanup function
const cleanupAudio = () => {
  if (audioPlayer.value?.currentBlobUrl) {
    URL.revokeObjectURL(audioPlayer.value.currentBlobUrl)
    audioPlayer.value.currentBlobUrl = null
  }
}

// Handle mobile browser UI bars
const handleViewportChange = () => {
  if (!import.meta.client) return
  
  const vh = window.innerHeight
  const dvh = window.visualViewport ? window.visualViewport.height : vh
  const diff = vh - dvh
  
  const playerControls = document.querySelector('.player-controls')
  if (playerControls) {
    if (diff > 50) {
      // Browser bars are visible, move controls up
      playerControls.style.setProperty('--browser-bar-height', `${diff}px`)
      playerControls.classList.add('browser-bars-visible')
    } else {
      // Browser bars hidden, controls to bottom
      playerControls.style.setProperty('--browser-bar-height', '0px')
      playerControls.classList.remove('browser-bars-visible')
    }
  }
}

// Lifecycle
onMounted(() => {
  loadTracks()
  // Load cached songs metadata
  musicStore.loadCachedNames()
  if (import.meta.client) {
    document.documentElement.setAttribute('data-theme', isDark.value ? 'dark' : 'light')
    
    // Handle mobile browser UI changes
    handleViewportChange()
    window.addEventListener('resize', handleViewportChange)
    if (window.visualViewport) {
      window.visualViewport.addEventListener('resize', handleViewportChange)
    }
    
    // Cleanup when page unloads
    window.addEventListener('beforeunload', cleanupAudio)
    window.addEventListener('pagehide', cleanupAudio)
  }
})

onUnmounted(() => {
  cleanupAudio()
  if (import.meta.client) {
    window.removeEventListener('beforeunload', cleanupAudio)
    window.removeEventListener('pagehide', cleanupAudio)
    window.removeEventListener('resize', handleViewportChange)
    if (window.visualViewport) {
      window.visualViewport.removeEventListener('resize', handleViewportChange)
    }
  }
})
</script>

<style scoped>
/* Page-specific styles */
</style>
