import { supabase, isSupabaseConfigured } from '../supabase'
import { logger } from '../utils/logger'
import type { MusicVibe } from '../types'

export interface MusicTrack {
  id: string
  title: string
  artist: string
  duration: number
  url: string
  vibe: MusicVibe
}

// Public-domain / royalty-free test audio from Apple HLS examples & samples
// Replace with Supabase-hosted tracks in production
const TEST_AUDIO_BASE = 'https://www2.cs.uic.edu/~i101/SoundFiles'

const MOCK_TRACKS: Record<MusicVibe, MusicTrack[]> = {
  electronic: [
    { id: '1', title: 'Energy Pulse', artist: 'Neon Dreams', duration: 240, url: `${TEST_AUDIO_BASE}/StarWars60.wav`, vibe: 'electronic' },
    { id: '2', title: 'Cyber Sprint', artist: 'Digital Flux', duration: 180, url: `${TEST_AUDIO_BASE}/tapioca.wav`, vibe: 'electronic' },
    { id: '3', title: 'High Voltage', artist: 'Circuit Breakers', duration: 200, url: `${TEST_AUDIO_BASE}/preamble10.wav`, vibe: 'electronic' },
  ],
  'hip-hop': [
    { id: '4', title: 'Street Heat', artist: 'Urban Flow', duration: 210, url: `${TEST_AUDIO_BASE}/StarWars60.wav`, vibe: 'hip-hop' },
    { id: '5', title: 'Rhythm Power', artist: 'Beat Masters', duration: 195, url: `${TEST_AUDIO_BASE}/tapioca.wav`, vibe: 'hip-hop' },
    { id: '6', title: 'Flow State', artist: 'MC Dynamic', duration: 220, url: `${TEST_AUDIO_BASE}/preamble10.wav`, vibe: 'hip-hop' },
  ],
  pop: [
    { id: '7', title: 'Summer Energy', artist: 'The Popstars', duration: 185, url: `${TEST_AUDIO_BASE}/StarWars60.wav`, vibe: 'pop' },
    { id: '8', title: 'Upbeat Vibes', artist: 'Chart Toppers', duration: 200, url: `${TEST_AUDIO_BASE}/tapioca.wav`, vibe: 'pop' },
    { id: '9', title: 'Feel Good', artist: 'Radio Hits', duration: 175, url: `${TEST_AUDIO_BASE}/preamble10.wav`, vibe: 'pop' },
  ],
  rock: [
    { id: '10', title: 'Power Chord', artist: 'The Amplifiers', duration: 230, url: `${TEST_AUDIO_BASE}/StarWars60.wav`, vibe: 'rock' },
    { id: '11', title: 'High Gain', artist: 'Distortion', duration: 205, url: `${TEST_AUDIO_BASE}/tapioca.wav`, vibe: 'rock' },
    { id: '12', title: 'Adrenaline', artist: 'Thunderstruck', duration: 215, url: `${TEST_AUDIO_BASE}/preamble10.wav`, vibe: 'rock' },
  ],
  chill: [
    { id: '13', title: 'Smooth Flow', artist: 'Lo-Fi Beats', duration: 250, url: `${TEST_AUDIO_BASE}/StarWars60.wav`, vibe: 'chill' },
    { id: '14', title: 'Zen Mode', artist: 'Calm Collective', duration: 240, url: `${TEST_AUDIO_BASE}/tapioca.wav`, vibe: 'chill' },
    { id: '15', title: 'Deep Breath', artist: 'Mindful Tones', duration: 260, url: `${TEST_AUDIO_BASE}/preamble10.wav`, vibe: 'chill' },
  ],
}

/**
 * Maps download_items genres to workout MusicVibe values.
 * Multiple genres map to the same vibe so we get more tracks per vibe.
 */
const VIBE_TO_GENRES: Record<MusicVibe, string[]> = {
  electronic: ['edm', 'house', 'drum-and-bass', 'dubstep'],
  'hip-hop': ['hip-hop', 'r-and-b'],
  pop: ['pop', 'latin'],
  rock: ['rock', 'metal', 'country'],
  chill: ['ambient'],
}

const SUPABASE_URL = process.env.EXPO_PUBLIC_SUPABASE_URL || 'http://localhost:54321'

class MusicService {
  private cache: Map<MusicVibe, MusicTrack[]> = new Map()

  async loadTracksForVibe(vibe: MusicVibe): Promise<MusicTrack[]> {
    if (this.cache.has(vibe)) {
      return this.cache.get(vibe)!
    }

    if (!isSupabaseConfigured()) {
      logger.log(`[Music] Using mock tracks for vibe: ${vibe}`)
      return MOCK_TRACKS[vibe] || MOCK_TRACKS.electronic
    }

    try {
      const genres = VIBE_TO_GENRES[vibe] || []

      type DownloadItemRow = {
        id: string | null
        video_id: string | null
        title: string | null
        duration_seconds: number | null
        public_url: string | null
        storage_path: string | null
        genre: string | null
      }

      const { data: items, error } = await supabase
        .from('download_items')
        .select('id, video_id, title, duration_seconds, public_url, storage_path, genre')
        .eq('status', 'completed')
        .in('genre', genres)
        .limit(50) as { data: DownloadItemRow[] | null; error: Error | null }

      if (error) {
        logger.error('[Music] Error loading tracks:', error)
        return MOCK_TRACKS[vibe] || MOCK_TRACKS.electronic
      }

      if (!items || items.length === 0) {
        logger.log(`[Music] No tracks found for vibe: ${vibe}, using mock data`)
        return MOCK_TRACKS[vibe] || MOCK_TRACKS.electronic
      }

      const tracks: MusicTrack[] = items
        .filter(item => item.public_url || item.storage_path)
        .map((item, index) => {
          const url = item.public_url
            || `${SUPABASE_URL}/storage/v1/object/public/workout-audio/${item.storage_path}`

          const titleStr = item.title || 'Unknown Track'
          const [artist, trackTitle] = titleStr.includes(' - ')
            ? titleStr.split(' - ').map((s: string) => s.trim())
            : ['YouTube Music', titleStr]

          return {
            id: item.id || `${vibe}-${index}`,
            title: trackTitle || titleStr,
            artist: artist || 'Unknown Artist',
            duration: item.duration_seconds ?? 180,
            url,
            vibe,
          }
        })

      if (tracks.length === 0) {
        logger.log(`[Music] No valid tracks for vibe: ${vibe}, using mock data`)
        return MOCK_TRACKS[vibe] || MOCK_TRACKS.electronic
      }

      this.cache.set(vibe, tracks)
      logger.log(`[Music] Loaded ${tracks.length} tracks for vibe: ${vibe}`)

      return tracks
    } catch (error) {
      logger.error('[Music] Error loading tracks:', error)
      return MOCK_TRACKS[vibe] || MOCK_TRACKS.electronic
    }
  }

  clearCache(vibe?: MusicVibe): void {
    if (vibe) {
      this.cache.delete(vibe)
    } else {
      this.cache.clear()
    }
  }

  getRandomTrack(tracks: MusicTrack[]): MusicTrack | null {
    if (tracks.length === 0) return null
    const randomIndex = Math.floor(Math.random() * tracks.length)
    return tracks[randomIndex]
  }

  getNextTrack(tracks: MusicTrack[], currentTrackId: string, shuffle: boolean = false): MusicTrack | null {
    if (tracks.length === 0) return null
    if (tracks.length === 1) return tracks[0]

    if (shuffle) {
      return this.getRandomTrack(tracks.filter(t => t.id !== currentTrackId))
    }

    const currentIndex = tracks.findIndex(t => t.id === currentTrackId)
    const nextIndex = (currentIndex + 1) % tracks.length
    return tracks[nextIndex]
  }
}

export const musicService = new MusicService()
