modules/Core/SetlistCommands.psm1

# Setlist Commands Module - Concert setlists via setlist.fm API

function Search-SetlistFm {
    param(
        [Parameter(Mandatory)]
        [string]$ArtistName
    )

    $apiKey = $env:SETLISTFM_API_KEY
    if (-not $apiKey) {
        Write-Host ""
        Write-Host " No setlist.fm API key found." -ForegroundColor Red
        Write-Host ""
        Write-Host " To use this feature:" -ForegroundColor Yellow
        Write-Host " 1. Register for free at https://api.setlist.fm" -ForegroundColor Gray
        Write-Host " 2. Go to your profile and copy your API key" -ForegroundColor Gray
        Write-Host " 3. Add to your .env file: SETLISTFM_API_KEY=your_key_here" -ForegroundColor Gray
        Write-Host " 4. Restart the CLI" -ForegroundColor Gray
        Write-Host ""
        return $null
    }

    $headers = @{
        "x-api-key" = $apiKey
        "Accept"    = "application/json"
    }

    $encodedArtist = [System.Uri]::EscapeDataString($ArtistName)
    $url = "https://api.setlist.fm/rest/1.0/search/setlists?artistName=$encodedArtist&p=1"

    try {
        $response = Invoke-RestMethod -Uri $url -Headers $headers -Method GET
    }
    catch {
        $statusCode = $_.Exception.Response.StatusCode.value__
        if ($statusCode -eq 404) {
            Write-Host " No setlists found for '$ArtistName'." -ForegroundColor Yellow
        }
        elseif ($statusCode -eq 403) {
            Write-Host " Invalid setlist.fm API key. Check your .env file." -ForegroundColor Red
        }
        else {
            Write-Host " setlist.fm API error: $($_.Exception.Message)" -ForegroundColor Red
        }
        return $null
    }

    if (-not $response.setlist -or $response.setlist.Count -eq 0) {
        Write-Host " No setlists found for '$ArtistName'." -ForegroundColor Yellow
        return $null
    }

    # Filter to setlists that actually have songs, take up to 5
    $withSongs = $response.setlist | Where-Object {
        $songCount = 0
        if ($_.sets -and $_.sets.set) {
            foreach ($set in $_.sets.set) {
                if ($set.song) { $songCount += $set.song.Count }
            }
        }
        $songCount -gt 0
    } | Select-Object -First 5

    if ($withSongs.Count -eq 0) {
        Write-Host " Found setlists for '$ArtistName' but none have song data." -ForegroundColor Yellow
        return $null
    }

    return @($withSongs)
}

function Show-SetlistResults {
    param(
        [Parameter(Mandatory)]
        [array]$Setlists
    )

    Write-Host ""
    Write-Host " RECENT CONCERTS" -ForegroundColor Cyan
    Write-Host " ===============" -ForegroundColor Cyan
    Write-Host ""

    for ($i = 0; $i -lt $Setlists.Count; $i++) {
        $s = $Setlists[$i]
        $artistName = $s.artist.name
        $venueName = if ($s.venue.name) { $s.venue.name } else { "Unknown venue" }
        $cityName = if ($s.venue.city.name) { $s.venue.city.name } else { "Unknown city" }
        $eventDate = $s.eventDate  # dd-MM-yyyy format

        # Count songs
        $songCount = 0
        if ($s.sets -and $s.sets.set) {
            foreach ($set in $s.sets.set) {
                if ($set.song) { $songCount += $set.song.Count }
            }
        }

        $num = $i + 1
        Write-Host " $num. " -ForegroundColor Yellow -NoNewline
        Write-Host "$artistName" -ForegroundColor White -NoNewline
        Write-Host " @ " -ForegroundColor Gray -NoNewline
        Write-Host "$venueName, $cityName" -ForegroundColor Cyan -NoNewline
        Write-Host " - $eventDate " -ForegroundColor Gray -NoNewline
        Write-Host "($songCount songs)" -ForegroundColor DarkGray
    }

    Write-Host ""
    $choice = Read-Host " Pick a concert (1-$($Setlists.Count)), or press Enter to cancel"

    if ([string]::IsNullOrWhiteSpace($choice)) {
        return -1
    }

    $index = 0
    if ([int]::TryParse($choice, [ref]$index)) {
        if ($index -ge 1 -and $index -le $Setlists.Count) {
            return $index - 1
        }
    }

    Write-Host " Invalid selection." -ForegroundColor Red
    return -1
}

function Show-SetlistSongs {
    param(
        [Parameter(Mandatory)]
        $Setlist
    )

    $artistName = $Setlist.artist.name
    $venueName = if ($Setlist.venue.name) { $Setlist.venue.name } else { "Unknown venue" }
    $cityName = if ($Setlist.venue.city.name) { $Setlist.venue.city.name } else { "Unknown city" }
    $eventDate = $Setlist.eventDate

    Write-Host ""
    Write-Host " $artistName @ $venueName, $cityName" -ForegroundColor Cyan
    Write-Host " $eventDate" -ForegroundColor Gray
    Write-Host " ----------------------------------------" -ForegroundColor DarkGray

    $songs = @()
    $setNumber = 0

    foreach ($set in $Setlist.sets.set) {
        $setNumber++
        if ($Setlist.sets.set.Count -gt 1) {
            $setLabel = if ($set.name) { $set.name } elseif ($set.encore -and $set.encore -gt 0) { "Encore" } else { "Set $setNumber" }
            Write-Host ""
            Write-Host " $setLabel" -ForegroundColor Yellow
        }

        if ($set.song) {
            foreach ($song in $set.song) {
                $songs += $song.name
                $num = $songs.Count
                $coverInfo = ""
                if ($song.cover -and $song.cover.name) {
                    $coverInfo = " (cover: $($song.cover.name))"
                }
                Write-Host " $num. $($song.name)$coverInfo" -ForegroundColor White
            }
        }
    }

    Write-Host ""
    return $songs
}

function New-SetlistPlaylist {
    param(
        [Parameter(Mandatory)]
        [string]$ArtistName,

        [Parameter(Mandatory)]
        [string[]]$Songs,

        [string]$VenueName = "",
        [string]$EventDate = ""
    )

    Write-Host " Searching Spotify for $($Songs.Count) songs..." -ForegroundColor Gray

    $matchedUris = @()
    $missedSongs = @()

    foreach ($song in $Songs) {
        $query = "track:$song artist:$ArtistName"
        $searchQuery = @{
            q     = $query
            type  = "track"
            limit = "1"
        }

        try {
            $result = Invoke-SpotifyApi -Method GET -Path "/search" -Query $searchQuery
            if ($result.tracks -and $result.tracks.items -and $result.tracks.items.Count -gt 0) {
                $matchedUris += $result.tracks.items[0].uri
                Write-Host " + $song" -ForegroundColor Green
            }
            else {
                $missedSongs += $song
                Write-Host " - $song (not found)" -ForegroundColor DarkGray
            }
        }
        catch {
            $missedSongs += $song
            Write-Host " - $song (search error)" -ForegroundColor DarkGray
        }
    }

    if ($matchedUris.Count -eq 0) {
        Write-Host ""
        Write-Host " No songs could be matched on Spotify." -ForegroundColor Red
        return
    }

    Write-Host ""
    Write-Host " Matched $($matchedUris.Count)/$($Songs.Count) songs." -ForegroundColor Cyan

    # Get current user ID
    try {
        $userProfile = Invoke-SpotifyApi -Method GET -Path "/me"
        $userId = $userProfile.id
    }
    catch {
        Write-Host " Could not get user profile." -ForegroundColor Red
        return
    }

    # Build playlist name
    $playlistName = "$ArtistName"
    if ($VenueName) { $playlistName += " @ $VenueName" }
    if ($EventDate) { $playlistName += " $EventDate" }

    # Create playlist
    $playlistBody = @{
        name        = $playlistName
        description = "Concert setlist - created by Spotify CLI"
        public      = $false
    }

    try {
        Write-Host " Creating playlist '$playlistName'..." -ForegroundColor Gray
        $playlist = Invoke-SpotifyApi -Method POST -Path "/users/$userId/playlists" -Body $playlistBody
    }
    catch {
        Write-Host " Failed to create playlist: $($_.Exception.Message)" -ForegroundColor Red
        return
    }

    # Add tracks (batch up to 100)
    try {
        $addBody = @{ uris = $matchedUris }
        Invoke-SpotifyApi -Method POST -Path "/playlists/$($playlist.id)/tracks" -Body $addBody | Out-Null
    }
    catch {
        Write-Host " Failed to add tracks: $($_.Exception.Message)" -ForegroundColor Red
        return
    }

    Write-Host ""
    Write-Host " Playlist created with $($matchedUris.Count)/$($Songs.Count) tracks!" -ForegroundColor Green
    if ($missedSongs.Count -gt 0) {
        Write-Host " Missing: $($missedSongs -join ', ')" -ForegroundColor DarkGray
    }
    Write-Host " $($playlist.external_urls.spotify)" -ForegroundColor Cyan
    Write-Host ""

    # Offer to play
    $playChoice = Read-Host " Play now? [Y/n]"
    if ($playChoice -ne 'n' -and $playChoice -ne 'N') {
        try {
            $body = @{ context_uri = $playlist.uri }
            Invoke-SpotifyApi -Method PUT -Path "/me/player/play" -Body $body | Out-Null
            Write-Host " Playing!" -ForegroundColor Green
        }
        catch {
            Write-Host " Could not start playback. Make sure a device is active." -ForegroundColor Yellow
        }
    }
}

function Invoke-SetlistCommand {
    param(
        [Parameter(Position = 0, ValueFromRemainingArguments)]
        $Arguments
    )

    # Flatten and join arguments into artist name
    $artistName = if ($Arguments) {
        ($Arguments | ForEach-Object { "$_" }) -join " "
    } else { "" }

    $artistName = $artistName.Trim()

    if ([string]::IsNullOrWhiteSpace($artistName)) {
        Write-Host ""
        Write-Host " SETLIST - Concert Setlist Finder" -ForegroundColor Cyan
        Write-Host " ================================" -ForegroundColor Cyan
        Write-Host ""
        Write-Host " Usage: /setlist <artist name>" -ForegroundColor White
        Write-Host ""
        Write-Host " Examples:" -ForegroundColor Yellow
        Write-Host " /setlist Tame Impala" -ForegroundColor Gray
        Write-Host " /setlist Metallica" -ForegroundColor Gray
        Write-Host " /setlist Taylor Swift" -ForegroundColor Gray
        Write-Host ""
        Write-Host " Shows recent concerts and their setlists." -ForegroundColor Gray
        Write-Host " Optionally creates a Spotify playlist from the setlist." -ForegroundColor Gray
        Write-Host ""
        Write-Host " Requires a free API key from https://api.setlist.fm" -ForegroundColor DarkGray
        Write-Host ""
        return
    }

    Write-Host ""
    Write-Host " Searching setlist.fm for '$artistName'..." -ForegroundColor Gray

    # Search setlist.fm
    $setlists = Search-SetlistFm -ArtistName $artistName
    if (-not $setlists) { return }

    # Show results and let user pick
    $selectedIndex = Show-SetlistResults -Setlists $setlists
    if ($selectedIndex -lt 0) {
        Write-Host " Cancelled." -ForegroundColor Gray
        return
    }

    $selected = $setlists[$selectedIndex]

    # Show song list
    $songs = Show-SetlistSongs -Setlist $selected

    if ($songs.Count -eq 0) {
        Write-Host " No songs in this setlist." -ForegroundColor Yellow
        return
    }

    # Offer to create playlist
    $createChoice = Read-Host " Create Spotify playlist from this setlist? [Y/n]"
    if ($createChoice -eq 'n' -or $createChoice -eq 'N') {
        Write-Host " Done." -ForegroundColor Gray
        return
    }

    $venueName = if ($selected.venue.name) { $selected.venue.name } else { "" }
    $eventDate = if ($selected.eventDate) { $selected.eventDate } else { "" }

    New-SetlistPlaylist -ArtistName $selected.artist.name -Songs $songs -VenueName $venueName -EventDate $eventDate
}

# Export and alias
New-Alias -Name 'setlist' -Value 'Invoke-SetlistCommand' -Force
Export-ModuleMember -Function 'Invoke-SetlistCommand' -Alias 'setlist'