modules/Core/PlaybackCommands.psm1

# PlaybackCommands Module
# Contains all core functions for controlling Spotify playback.

# --- Spotify Auto-Start Helper ---
function Start-SpotifyIfNeeded {
    <#
    .SYNOPSIS
    Starts Spotify app if no devices are available and waits for it to become ready
    .OUTPUTS
    Returns $true if a device becomes available, $false otherwise
    #>

    Write-Host "🚀 Starting Spotify..." -ForegroundColor Cyan

    # Try common Spotify paths
    $spotifyPaths = @(
        "$env:APPDATA\Spotify\Spotify.exe",
        "$env:LOCALAPPDATA\Microsoft\WindowsApps\Spotify.exe",
        "spotify"
    )

    $started = $false
    foreach ($path in $spotifyPaths) {
        try {
            Start-Process $path -ErrorAction Stop
            $started = $true
            break
        } catch {
            continue
        }
    }

    if (-not $started) {
        Write-Host "❌ Could not find Spotify. Please install it or start it manually." -ForegroundColor Red
        return $false
    }

    # Wait for Spotify to register as a device (up to 15 seconds)
    Write-Host "⏳ Waiting for Spotify to start..." -ForegroundColor Yellow
    $maxAttempts = 15
    for ($i = 1; $i -le $maxAttempts; $i++) {
        Start-Sleep -Seconds 1
        try {
            $devicesResponse = Invoke-SpotifyApi -Method GET -Path "/me/player/devices"
            if ($devicesResponse -and $devicesResponse.devices -and $devicesResponse.devices.Count -gt 0) {
                Write-Host "✅ Spotify is ready!" -ForegroundColor Green
                return $true
            }
        } catch {
            # API might fail while Spotify is starting, continue waiting
        }
        Write-Host " Waiting... ($i/$maxAttempts)" -ForegroundColor DarkGray
    }

    Write-Host "❌ Spotify started but no device appeared. Try again in a moment." -ForegroundColor Red
    return $false
}

# --- Notification Helper ---
function Show-TrackNotification {
    <#
    .SYNOPSIS
    Shows a Windows toast notification for track changes
    #>

    param(
        [Parameter(ParameterSetName='TrackInfo')]
        $TrackInfo,

        [Parameter(ParameterSetName='Custom')]
        [string]$Title,

        [Parameter(ParameterSetName='Custom')]
        [string]$Message,

        [ValidateSet('play', 'pause', 'next', 'previous', '')]
        [string]$Action = ''
    )

    try {
        # Determine notification content
        if ($TrackInfo) {
            # Add action indicator
            $actionIcon = switch ($Action) {
                'play' { '▶️' }
                'pause' { '⏸️' }
                'next' { '⏭️' }
                'previous' { '⏮️' }
                default { '🎵' }
            }

            if ($TrackInfo.type -eq "episode") {
                $notifyTitle = "$actionIcon 🎙️ $($TrackInfo.name)"
                $notifyMessage = "📺 $($TrackInfo.show.name)"
                $appLogo = $TrackInfo.images[0].url
            } else {
                $artists = ($TrackInfo.artists | ForEach-Object { $_.name }) -join ", "
                $albumName = if ($TrackInfo.album) { $TrackInfo.album.name } else { "Unknown Album" }

                $notifyTitle = "$actionIcon 🎵 $($TrackInfo.name)"
                $notifyMessage = "💿 $albumName`n👤 $artists"
                $appLogo = if ($TrackInfo.album -and $TrackInfo.album.images) { $TrackInfo.album.images[0].url } else { $null }
            }
        } else {
            $notifyTitle = $Title
            $notifyMessage = $Message
            $appLogo = $null
        }

        # Try BurntToast first (best experience)
        if (Get-Module -ListAvailable -Name BurntToast) {
            Import-Module BurntToast -ErrorAction SilentlyContinue

            $toastParams = @{
                Text = $notifyTitle, $notifyMessage
                Silent = $true
            }

            # Add album art if available
            if ($appLogo) {
                $toastParams['AppLogo'] = $appLogo
            }

            New-BurntToastNotification @toastParams
        }
        else {
            # Fallback: Use Windows balloon tip via .NET
            Add-Type -AssemblyName System.Windows.Forms -ErrorAction SilentlyContinue

            if ([System.Windows.Forms.SystemInformation]::TerminalServerSession -eq $false) {
                $balloon = New-Object System.Windows.Forms.NotifyIcon
                $balloon.Icon = [System.Drawing.SystemIcons]::Information
                $balloon.BalloonTipIcon = [System.Windows.Forms.ToolTipIcon]::Info
                $balloon.BalloonTipTitle = $notifyTitle
                $balloon.BalloonTipText = $notifyMessage
                $balloon.Visible = $true
                $balloon.ShowBalloonTip(3000)

                # Clean up after a delay
                Start-Sleep -Milliseconds 3500
                $balloon.Dispose()
            }
        }
    }
    catch {
        # Silently fail - notifications are optional
        Write-Verbose "Notification failed: $($_.Exception.Message)"
    }
}

function play {
    param([string]$TrackReference)

    # Path 2: Play a specific track/episode
    if (-not [string]::IsNullOrWhiteSpace($TrackReference)) {
        $trackUri = $TrackReference
        # Check if it's a number (track/episode index from search)
        if ($TrackReference -match '^\d+$') {
            $itemIndex = [int]$TrackReference - 1
            $sessionTracks = Get-SessionTracks
            if ($sessionTracks -and $itemIndex -ge 0 -and $itemIndex -lt $sessionTracks.Count) {
                $item = $sessionTracks[$itemIndex]
                $trackUri = $item.uri
                $itemName = $item.name
                if ($item.search_type -eq "episode" -or $item.type -eq "episode") {
                    $showName = $item.show.name
                    Write-Host "🎯 Playing podcast episode #$TrackReference ($itemName from $showName)..." -ForegroundColor Magenta
                } else {
                    $artists = ($item.artists | ForEach-Object { $_.name }) -join ", "
                    Write-Host "🎯 Playing track #$TrackReference ($itemName by $artists)..." -ForegroundColor Cyan
                }
            } else {
                Write-Host "❌ Invalid item number. Use 'search' to find tracks and episodes first." -ForegroundColor Red
                return
            }
        }

        # Ensure it's a valid Spotify URI
        if (-not ($trackUri.StartsWith("spotify:track:") -or $trackUri.StartsWith("spotify:episode:"))) {
            Write-Host "❌ Invalid URI. Must be a Spotify track or episode URI." -ForegroundColor Red
            return
        }

        try {
            # Try to play on active device first
            $body = @{ uris = @($trackUri) }
            Invoke-SpotifyApi -Method PUT -Path "/me/player/play" -Body $body | Out-Null
            if ($trackUri.StartsWith("spotify:episode:")) {
                Write-Host "▶️ Playing podcast episode" -ForegroundColor Magenta
            } else {
                Write-Host "▶️ Playing track" -ForegroundColor Green
            }
            # Show notification
            Start-Sleep -Milliseconds 300
            try {
                $currentTrack = Invoke-SpotifyApi -Method GET -Path "/me/player/currently-playing"
                if ($currentTrack -and $currentTrack.item) {
                    Show-TrackNotification -TrackInfo $currentTrack.item -Action 'play'
                }
            } catch { }
        }
        catch {
            # If no active device, try to activate one
            Write-Host "🎵 No active device. Looking for available devices..." -ForegroundColor Yellow
            try {
                $devicesResponse = Invoke-SpotifyApi -Method GET -Path "/me/player/devices"
                if (-not $devicesResponse -or -not $devicesResponse.devices -or $devicesResponse.devices.Count -eq 0) {
                    # No devices found - try to start Spotify automatically
                    if (-not (Start-SpotifyIfNeeded)) {
                        return
                    }
                    # Re-fetch devices after starting Spotify
                    $devicesResponse = Invoke-SpotifyApi -Method GET -Path "/me/player/devices"
                    if (-not $devicesResponse -or -not $devicesResponse.devices -or $devicesResponse.devices.Count -eq 0) {
                        Write-Host "❌ Still no devices available." -ForegroundColor Red
                        return
                    }
                }

                $firstDevice = $devicesResponse.devices[0]
                Write-Host "🔄 Activating device: $($firstDevice.name)..." -ForegroundColor Cyan
                $transferBody = @{ device_ids = @($firstDevice.id); play = $false }
                Invoke-SpotifyApi -Method PUT -Path "/me/player" -Body $transferBody | Out-Null
                Start-Sleep -Milliseconds 500

                # Try again to play
                $body = @{ uris = @($trackUri) }
                Invoke-SpotifyApi -Method PUT -Path "/me/player/play" -Body $body | Out-Null
                if ($trackUri.StartsWith("spotify:episode:")) {
                    Write-Host "▶️ Playing podcast episode" -ForegroundColor Magenta
                } else {
                    Write-Host "▶️ Playing track" -ForegroundColor Green
                }
                # Show notification
                Start-Sleep -Milliseconds 300
                try {
                    $currentTrack = Invoke-SpotifyApi -Method GET -Path "/me/player/currently-playing"
                    if ($currentTrack -and $currentTrack.item) {
                        Show-TrackNotification -TrackInfo $currentTrack.item -Action 'play'
                    }
                } catch { }
            }
            catch {
                Write-Host "❌ Could not play track: $($_.Exception.Message)" -ForegroundColor Red
            }
        }
        return
    }

    # Path 1: Resume playback or play recent
    try {
        Invoke-SpotifyApi -Method PUT -Path "/me/player/play" | Out-Null
        Write-Host "▶️ Resumed playback" -ForegroundColor Green
        # Show notification with current track
        Start-Sleep -Milliseconds 300
        try {
            $currentTrack = Invoke-SpotifyApi -Method GET -Path "/me/player/currently-playing"
            if ($currentTrack -and $currentTrack.item) {
                Show-TrackNotification -TrackInfo $currentTrack.item -Action 'play'
            }
        } catch { }
    }
    catch {
        # This is the expected error when nothing is active.
        # Now we try to be smart and play a recent track.
        Write-Host "🎵 No active playback found. Trying to start from your recent tracks..." -ForegroundColor Yellow
        try {
            $devicesResponse = Invoke-SpotifyApi -Method GET -Path "/me/player/devices"
            if (-not $devicesResponse -or -not $devicesResponse.devices -or $devicesResponse.devices.Count -eq 0) {
                # No devices found - try to start Spotify automatically
                if (-not (Start-SpotifyIfNeeded)) {
                    return
                }
                # Re-fetch devices after starting Spotify
                $devicesResponse = Invoke-SpotifyApi -Method GET -Path "/me/player/devices"
                if (-not $devicesResponse -or -not $devicesResponse.devices -or $devicesResponse.devices.Count -eq 0) {
                    Write-Host "❌ Still no devices available." -ForegroundColor Red
                    return
                }
            }

            $activeDevice = $devicesResponse.devices | Where-Object { $_.is_active -eq $true } | Select-Object -First 1
            if (-not $activeDevice) {
                $firstDevice = $devicesResponse.devices[0]
                Write-Host "🔄 Activating device: $($firstDevice.name)..." -ForegroundColor Cyan
                $transferBody = @{ device_ids = @($firstDevice.id); play = $false }
                Invoke-SpotifyApi -Method PUT -Path "/me/player" -Body $transferBody | Out-Null
                Start-Sleep -Milliseconds 500
            }

            $recentTracks = Invoke-SpotifyApi -Method GET -Path "/me/player/recently-played" -Query @{ limit = 1 }
            if ($recentTracks -and $recentTracks.items -and $recentTracks.items.Count -gt 0) {
                $lastTrack = $recentTracks.items[0].track
                $body = @{ uris = @($lastTrack.uri) }
                Invoke-SpotifyApi -Method PUT -Path "/me/player/play" -Body $body | Out-Null
                Write-Host "▶️ Started playing: $($lastTrack.name) by $(($lastTrack.artists | ForEach-Object { $_.name }) -join ', ')" -ForegroundColor Green
            } else {
                Write-Host "❌ No recent tracks found to play." -ForegroundColor Red
            }
        }
        catch {
            Write-Host "❌ Could not start playback: $($_.Exception.Message)" -ForegroundColor Red
        }
    }
}

function pause {
    try {
        # Get current track BEFORE pausing for notification
        $currentTrack = $null
        try {
            $currentTrack = Invoke-SpotifyApi -Method GET -Path "/me/player/currently-playing"
        } catch { }

        Invoke-SpotifyApi -Method PUT -Path "/me/player/pause" | Out-Null
        Write-Host "⏸️ Paused playback" -ForegroundColor Yellow

        # Show notification with track info
        if ($currentTrack -and $currentTrack.item) {
            Show-TrackNotification -TrackInfo $currentTrack.item -Action 'pause'
        }
    }
    catch {
        $errorMessage = $_.Exception.Message

        # Check error type based on message content
        if ($errorMessage -match "401|Unauthorized|AUTHENTICATION_ERROR") {
            Write-Host "🔐 Authentication Error: Your Spotify session has expired." -ForegroundColor Red
            Write-Host "💡 Solution: Run .\spotifyCLI.ps1 to re-authenticate" -ForegroundColor Yellow
        }
        elseif ($errorMessage -match "404|Not Found") {
            Write-Host "❌ Could not pause playback. Make sure Spotify is open and playing." -ForegroundColor Red
            Write-Host "💡 API Error: $errorMessage" -ForegroundColor Yellow
        }
        else {
            Write-Host "❌ An unexpected error occurred: $errorMessage" -ForegroundColor Red
        }
    }
}

function next {
    try {
        Invoke-SpotifyApi -Method POST -Path "/me/player/next" | Out-Null
        Write-Host "⏭️ Skipped to next track" -ForegroundColor Green
        # Wait a moment for Spotify to update, then show current track
        Start-Sleep -Milliseconds 500
        try {
            $currentTrack = Invoke-SpotifyApi -Method GET -Path "/me/player/currently-playing"
            if ($currentTrack -and $currentTrack.item) {
                $item = $currentTrack.item
                if ($item.type -eq "episode") {
                    Write-Host "🎙️ Now playing: $($item.name)" -ForegroundColor Magenta
                } else {
                    $artists = ($item.artists | ForEach-Object { $_.name }) -join ", "
                    Write-Host "🎵 Now playing: $($item.name) by $artists" -ForegroundColor Cyan
                }
                # Show toast notification
                Show-TrackNotification -TrackInfo $item -Action 'next'
            }
        } catch {
            # Silently ignore if we can't get track info
        }
    }
    catch {
        $errorMessage = $_.Exception.Message

        # Check error type based on message content
        if ($errorMessage -match "401|Unauthorized|AUTHENTICATION_ERROR") {
            Write-Host "🔐 Authentication Error: Your Spotify session has expired." -ForegroundColor Red
            Write-Host "💡 Solution: Run .\spotifyCLI.ps1 to re-authenticate" -ForegroundColor Yellow
        }
        elseif ($errorMessage -match "404|Not Found") {
            Write-Host "❌ Could not skip to next track. Make sure Spotify is playing music." -ForegroundColor Red
            Write-Host "💡 API Error: $errorMessage" -ForegroundColor Yellow
        }
        else {
            Write-Host "❌ An unexpected error occurred: $errorMessage" -ForegroundColor Red
        }
    }
}

function previous {
    try {
        Invoke-SpotifyApi -Method POST -Path "/me/player/previous" | Out-Null
        Write-Host "⏮️ Skipped to previous track" -ForegroundColor Green
        # Wait a moment for Spotify to update, then show current track
        Start-Sleep -Milliseconds 500
        try {
            $currentTrack = Invoke-SpotifyApi -Method GET -Path "/me/player/currently-playing"
            if ($currentTrack -and $currentTrack.item) {
                $item = $currentTrack.item
                if ($item.type -eq "episode") {
                    Write-Host "🎙️ Now playing: $($item.name)" -ForegroundColor Magenta
                } else {
                    $artists = ($item.artists | ForEach-Object { $_.name }) -join ", "
                    Write-Host "🎵 Now playing: $($item.name) by $artists" -ForegroundColor Cyan
                }
                # Show toast notification
                Show-TrackNotification -TrackInfo $item -Action 'previous'
            }
        } catch {
            # Silently ignore if we can't get track info
        }
    }
    catch {
        $errorMessage = $_.Exception.Message
        if ($errorMessage -match "401|Unauthorized|AUTHENTICATION_ERROR") {
            Write-Host "🔐 Authentication Error: Your Spotify session has expired." -ForegroundColor Red
            Write-Host "💡 Solution: Run .\spotifyCLI.ps1 to re-authenticate" -ForegroundColor Yellow
        }
        elseif ($errorMessage -match "404|Not Found") {
            Write-Host "❌ Could not skip to previous track. Make sure Spotify is playing music." -ForegroundColor Red
            Write-Host "💡 API Error: $errorMessage" -ForegroundColor Yellow
        }
        else {
            Write-Host "❌ An unexpected error occurred: $errorMessage" -ForegroundColor Red
        }
    }
}

function volume {
    <#
    .SYNOPSIS
    Control Spotify volume
    .PARAMETER Level
    Volume level (0-100)
    .EXAMPLE
    volume 75
    Set volume to 75%
    #>

    param([int]$Level)
    if ($Level -lt 0 -or $Level -gt 100) {
        Write-Host "❌ Volume must be between 0 and 100" -ForegroundColor Red
        return
    }
    try {
        $query = @{ volume_percent = $Level }
        Invoke-SpotifyApi -Method PUT -Path "/me/player/volume" -Query $query | Out-Null
        Write-Host "🔊 Volume set to $Level%" -ForegroundColor Green
    }
    catch {
        $errorMessage = $_.Exception.Message
        if ($errorMessage -match "401|Unauthorized|AUTHENTICATION_ERROR") {
            Write-Host "🔐 Authentication Error: Your Spotify session has expired." -ForegroundColor Red
            Write-Host "💡 Solution: Run .\spotifyCLI.ps1 to re-authenticate" -ForegroundColor Yellow
        }
        elseif ($errorMessage -match "404|Not Found") {
            Write-Host "❌ Could not set volume. Make sure a device is active and supports volume control." -ForegroundColor Red
            Write-Host "💡 API Error: $errorMessage" -ForegroundColor Yellow
        }
        else {
            Write-Host "❌ An unexpected error occurred: $errorMessage" -ForegroundColor Red
        }
    }
}

function seek {
    <#
    .SYNOPSIS
    Seek in current track or podcast episode
    .PARAMETER Seconds
    Seconds to seek (positive = forward, negative = backward)
    .EXAMPLE
    seek 30
    Seek forward 30 seconds
    .EXAMPLE
    seek -10
    Seek backward 10 seconds
    .EXAMPLE
    seek -30
    Seek backward 30 seconds (useful for podcast replay)
    #>

    param([int]$Seconds)
    try {
        $currentTrack = Invoke-SpotifyApi -Method GET -Path "/me/player/currently-playing"
        if (-not $currentTrack -or -not $currentTrack.item) {
            Write-Host "❌ No track or episode currently playing." -ForegroundColor Red
            return
        }

        $item = $currentTrack.item
        $isPodcast = $item.type -eq "episode" -or ($currentTrack.currently_playing_type -eq "episode")
        $currentPosition = $currentTrack.progress_ms
        $newPosition = $currentPosition + ($Seconds * 1000)
        $maxPosition = $item.duration_ms
        
        if ($newPosition -lt 0) { $newPosition = 0 }
        if ($newPosition -gt $maxPosition) { $newPosition = $maxPosition }

        $query = @{ position_ms = $newPosition }
        Invoke-SpotifyApi -Method PUT -Path "/me/player/seek" -Query $query | Out-Null

        $direction = if ($Seconds -gt 0) { "forward" } else { "backward" }
        $absSeconds = [Math]::Abs($Seconds)
        if ($isPodcast) {
            Write-Host "⏩ Seeked $direction $absSeconds seconds in podcast episode" -ForegroundColor Magenta
            # Show current position for podcast episodes (more useful for long content)
            $currentTimeStr = Format-Time $newPosition
            $totalTimeStr = Format-Time $maxPosition
            Write-Host "📍 Position: $currentTimeStr / $totalTimeStr" -ForegroundColor Gray
        } else {
            Write-Host "⏩ Seeked $direction $absSeconds seconds" -ForegroundColor Green
        }
    }
    catch {
        $errorMessage = $_.Exception.Message
        if ($errorMessage -match "401|Unauthorized|AUTHENTICATION_ERROR") {
            Write-Host "🔐 Authentication Error: Your Spotify session has expired." -ForegroundColor Red
            Write-Host "💡 Solution: Run .\spotifyCLI.ps1 to re-authenticate" -ForegroundColor Yellow
        }
        elseif ($errorMessage -match "404|Not Found") {
            Write-Host "❌ Could not seek. Make sure a track is playing on an active device." -ForegroundColor Red
            Write-Host "💡 API Error: $errorMessage" -ForegroundColor Yellow
        }
        else {
            Write-Host "❌ An unexpected error occurred during seek: $errorMessage" -ForegroundColor Red
        }
    }
}

function skip-forward {
    <#
    .SYNOPSIS
    Skip forward 30 seconds (common podcast control)
    .EXAMPLE
    skip-forward
    Skip forward 30 seconds in current episode or track
    #>

    seek 30
}

function skip-back {
    <#
    .SYNOPSIS
    Skip backward 15 seconds (common podcast control)
    .EXAMPLE
    skip-back
    Skip backward 15 seconds in current episode or track
    #>

    seek -15
}

function replay {
    <#
    .SYNOPSIS
    Skip backward 30 seconds (useful for podcast replay)
    .EXAMPLE
    replay
    Skip backward 30 seconds to replay content
    #>

    seek -30
}

function shuffle {
    <#
    .SYNOPSIS
    Control shuffle mode
    .PARAMETER State
    Shuffle state: 'on', 'off', or 'toggle'
    .EXAMPLE
    shuffle on
    Enable shuffle
    .EXAMPLE
    shuffle toggle
    Toggle shuffle state
    #>

    param([ValidateSet('on', 'off', 'toggle')][string]$State = 'toggle')
    try {
        if ($State -eq 'toggle') {
            # Get current state first
            $currentState = Invoke-SpotifyApi -Method GET -Path "/me/player"
            $currentShuffle = $currentState.shuffle_state
            $newState = -not $currentShuffle
        } else {
            $newState = ($State -eq 'on')
        }
        $query = @{ state = $newState.ToString().ToLower() }
        Invoke-SpotifyApi -Method PUT -Path "/me/player/shuffle" -Query $query | Out-Null
        $stateText = if ($newState) { "enabled" } else { "disabled" }
        $icon = if ($newState) { "🔀" } else { "➡️" }
        Write-Host "$icon Shuffle $stateText" -ForegroundColor Green
    }
    catch {
        $errorMessage = $_.Exception.Message
        if ($errorMessage -match "401|Unauthorized|AUTHENTICATION_ERROR") {
            Write-Host "🔐 Authentication Error: Your Spotify session has expired." -ForegroundColor Red
            Write-Host "💡 Solution: Run .\spotifyCLI.ps1 to re-authenticate" -ForegroundColor Yellow
        }
        elseif ($errorMessage -match "404|Not Found") {
            Write-Host "❌ Could not change shuffle state. Make sure a track is playing on an active device." -ForegroundColor Red
            Write-Host "💡 API Error: $errorMessage" -ForegroundColor Yellow
        }
        else {
            Write-Host "❌ An unexpected error occurred: $errorMessage" -ForegroundColor Red
        }
    }
}

function repeat {
    <#
    .SYNOPSIS
    Control repeat mode
    .PARAMETER Mode
    Repeat mode: 'track', 'context', 'off'
    .EXAMPLE
    repeat track
    Repeat current track
    .EXAMPLE
    repeat off
    Disable repeat
    #>

    param([ValidateSet('track', 'context', 'off')][string]$Mode = 'off')
    try {
        $query = @{ state = $Mode }
        Invoke-SpotifyApi -Method PUT -Path "/me/player/repeat" -Query $query | Out-Null
        $icon = switch ($Mode) {
            "track" { "🔂" }
            "context" { "🔁" }
            "off" { "➡️" }
        }
        $modeText = switch ($Mode) {
            "track" { "current track" }
            "context" { "playlist/album" }
            "off" { "disabled" }
        }
        Write-Host "$icon Repeat $modeText" -ForegroundColor Green
    }
    catch {
        $errorMessage = $_.Exception.Message
        if ($errorMessage -match "401|Unauthorized|AUTHENTICATION_ERROR") {
            Write-Host "🔐 Authentication Error: Your Spotify session has expired." -ForegroundColor Red
            Write-Host "💡 Solution: Run .\spotifyCLI.ps1 to re-authenticate" -ForegroundColor Yellow
        }
        elseif ($errorMessage -match "404|Not Found") {
            Write-Host "❌ Could not change repeat state. Make sure a track is playing on an active device." -ForegroundColor Red
            Write-Host "💡 API Error: $errorMessage" -ForegroundColor Yellow
        }
        else {
            Write-Host "❌ An unexpected error occurred: $errorMessage" -ForegroundColor Red
        }
    }
}

function transfer {
    <#
    .SYNOPSIS
    Transfer playback to another device
    .PARAMETER DeviceId
    Device ID or number (from devices list) to transfer to
    .EXAMPLE
    transfer 1
    Transfer playback to device #1 from devices list
    .EXAMPLE
    transfer abc123
    Transfer playback to device with ID abc123
    #>

    param([string]$DeviceId)
    try {
        if ([string]::IsNullOrWhiteSpace($DeviceId)) {
            Write-Host "Usage: transfer <device_number_or_id>" -ForegroundColor Yellow
            Write-Host "Use 'devices' command to see available devices" -ForegroundColor Gray
            return
        }

        $actualDeviceId = $DeviceId
        $deviceName = ""

        # Check if it's a number (device index from 'devices' command)
        if ($DeviceId -match '^\d+$') {
            $deviceIndex = [int]$DeviceId - 1
            $sessionDevices = Get-SessionDevices
            if ($sessionDevices -and $deviceIndex -ge 0 -and $deviceIndex -lt $sessionDevices.Count) {
                $actualDeviceId = $sessionDevices[$deviceIndex].id
                $deviceName = $sessionDevices[$deviceIndex].name
                Write-Host "🎯 Transferring to device #$DeviceId ($deviceName)..." -ForegroundColor Cyan
            } else {
                # If session is stale or number is invalid, give a helpful error.
                Write-Host "❌ Invalid device number. Run 'devices' first to see an up-to-date list." -ForegroundColor Red
                return
            }
        } else {
             # It's a raw ID, let's try to find its name for a better user message.
             $devicesResponse = Invoke-SpotifyApi -Method GET -Path "/me/player/devices"
             $foundDevice = $devicesResponse.devices | Where-Object { $_.id -eq $actualDeviceId }
             if ($foundDevice) {
                 $deviceName = $foundDevice.name
             }
             Write-Host "🎯 Transferring to device '$($deviceName)' ($actualDeviceId)..." -ForegroundColor Cyan
        }

        $body = @{ device_ids = @($actualDeviceId) }
        Invoke-SpotifyApi -Method PUT -Path "/me/player" -Body $body | Out-Null

        Write-Host "📱 Playback successfully transferred to '$($deviceName)'" -ForegroundColor Green
    }
    catch {
        $errorMessage = $_.Exception.Message
        if ($errorMessage -match "401|Unauthorized|AUTHENTICATION_ERROR") {
            Write-Host "🔐 Authentication Error: Your Spotify session has expired." -ForegroundColor Red
            Write-Host "💡 Solution: Run .\spotifyCLI.ps1 to re-authenticate" -ForegroundColor Yellow
        }
        elseif ($errorMessage -match "404|Not Found") {
            Write-Host "❌ Could not transfer playback." -ForegroundColor Red
            Write-Host "💡 Make sure the device ID is correct and the device is online." -ForegroundColor Yellow
            Write-Host "💡 API Error: $errorMessage" -ForegroundColor Yellow
        }
        else {
            Write-Host "❌ An unexpected error occurred: $errorMessage" -ForegroundColor Red
        }
    }
}

function export-now-playing {
    <#
    .SYNOPSIS
    Export currently playing track info to files for OBS/streaming
    .PARAMETER OutputPath
    Directory to save files (default: current directory)
    .PARAMETER Watch
    Continuously update files (useful for OBS)
    .EXAMPLE
    export-now-playing
    Export current track to files in current directory
    .EXAMPLE
    export-now-playing -OutputPath "C:\OBS\nowplaying"
    Export to specific directory
    .EXAMPLE
    export-now-playing -Watch
    Continuously update files every 2 seconds
    #>

    param(
        [string]$OutputPath = ".",
        [switch]$Watch
    )

    # Ensure directory exists
    if (-not (Test-Path $OutputPath)) {
        New-Item -ItemType Directory -Path $OutputPath -Force | Out-Null
    }

    $trackFile = Join-Path $OutputPath "track.txt"
    $artistFile = Join-Path $OutputPath "artist.txt"
    $albumFile = Join-Path $OutputPath "album.txt"
    $nowPlayingFile = Join-Path $OutputPath "nowplaying.txt"

    if ($Watch) {
        Write-Host "📝 Starting continuous export to $OutputPath" -ForegroundColor Cyan
        Write-Host "💡 Files will update every 2 seconds" -ForegroundColor Yellow
        Write-Host "💡 Press Ctrl+C to stop" -ForegroundColor Yellow
        Write-Host ""

        try {
            while ($true) {
                try {
                    $currentTrack = Invoke-SpotifyApi -Method GET -Path "/me/player/currently-playing"
                    if ($currentTrack -and $currentTrack.item) {
                        $item = $currentTrack.item

                        if ($currentTrack.currently_playing_type -eq "episode" -or $item.type -eq "episode") {
                            # Podcast episode
                            Set-Content -Path $trackFile -Value $item.name -Encoding UTF8
                            Set-Content -Path $artistFile -Value $item.show.name -Encoding UTF8
                            Set-Content -Path $albumFile -Value "Podcast" -Encoding UTF8
                            Set-Content -Path $nowPlayingFile -Value "🎙️ $($item.name) - $($item.show.name)" -Encoding UTF8
                        } else {
                            # Music track
                            $artists = ($item.artists | ForEach-Object { $_.name }) -join ", "
                            Set-Content -Path $trackFile -Value $item.name -Encoding UTF8
                            Set-Content -Path $artistFile -Value $artists -Encoding UTF8
                            Set-Content -Path $albumFile -Value $item.album.name -Encoding UTF8
                            Set-Content -Path $nowPlayingFile -Value "🎵 $($item.name) - $artists" -Encoding UTF8
                        }

                        Write-Host "✅ Updated at $(Get-Date -Format 'HH:mm:ss')" -ForegroundColor Green
                    } else {
                        # Clear files if nothing is playing
                        "" | Set-Content -Path $trackFile -Encoding UTF8
                        "" | Set-Content -Path $artistFile -Encoding UTF8
                        "" | Set-Content -Path $albumFile -Encoding UTF8
                        "Not playing" | Set-Content -Path $nowPlayingFile -Encoding UTF8
                    }
                } catch {
                    Write-Warning "Failed to update: $($_.Exception.Message)"
                }

                Start-Sleep -Seconds 2
            }
        } catch {
            Write-Host ""
            Write-Host "📝 Export stopped." -ForegroundColor Yellow
        }
    } else {
        try {
            $currentTrack = Invoke-SpotifyApi -Method GET -Path "/me/player/currently-playing"
            if (-not $currentTrack -or -not $currentTrack.item) {
                Write-Host "❌ No track or episode currently playing." -ForegroundColor Red
                return
            }

            $item = $currentTrack.item

            if ($currentTrack.currently_playing_type -eq "episode" -or $item.type -eq "episode") {
                # Podcast episode
                Set-Content -Path $trackFile -Value $item.name -Encoding UTF8
                Set-Content -Path $artistFile -Value $item.show.name -Encoding UTF8
                Set-Content -Path $albumFile -Value "Podcast" -Encoding UTF8
                Set-Content -Path $nowPlayingFile -Value "🎙️ $($item.name) - $($item.show.name)" -Encoding UTF8

                Write-Host "📝 Exported podcast episode:" -ForegroundColor Magenta
                Write-Host " $($item.name)" -ForegroundColor White
                Write-Host " from $($item.show.name)" -ForegroundColor Gray
            } else {
                # Music track
                $artists = ($item.artists | ForEach-Object { $_.name }) -join ", "
                Set-Content -Path $trackFile -Value $item.name -Encoding UTF8
                Set-Content -Path $artistFile -Value $artists -Encoding UTF8
                Set-Content -Path $albumFile -Value $item.album.name -Encoding UTF8
                Set-Content -Path $nowPlayingFile -Value "🎵 $($item.name) - $artists" -Encoding UTF8

                Write-Host "📝 Exported track:" -ForegroundColor Green
                Write-Host " $($item.name)" -ForegroundColor White
                Write-Host " by $artists" -ForegroundColor Gray
                Write-Host " from $($item.album.name)" -ForegroundColor Gray
            }

            Write-Host ""
            Write-Host "Files saved to:" -ForegroundColor Cyan
            Write-Host " $trackFile" -ForegroundColor Gray
            Write-Host " $artistFile" -ForegroundColor Gray
            Write-Host " $albumFile" -ForegroundColor Gray
            Write-Host " $nowPlayingFile" -ForegroundColor Gray
        }
        catch {
            $errorMessage = $_.Exception.Message
            if ($errorMessage -match "401|Unauthorized|AUTHENTICATION_ERROR") {
                Write-Host "🔐 Authentication Error: Your Spotify session has expired." -ForegroundColor Red
                Write-Host "💡 Solution: Run .\spotifyCLI.ps1 to re-authenticate" -ForegroundColor Yellow
            }
            elseif ($errorMessage -match "404|Not Found") {
                Write-Host "❌ Could not get current track." -ForegroundColor Red
                Write-Host "💡 API Error: $errorMessage" -ForegroundColor Yellow
            }
            else {
                Write-Host "❌ An unexpected error occurred: $errorMessage" -ForegroundColor Red
            }
        }
    }
}

function copy-track-link {
    <#
    .SYNOPSIS
    Copy current track or episode Spotify link to clipboard
    .EXAMPLE
    copy-track-link
    Copy Spotify link for currently playing track to clipboard
    #>

    try {
        $currentTrack = Invoke-SpotifyApi -Method GET -Path "/me/player/currently-playing"
        if (-not $currentTrack -or -not $currentTrack.item) {
            Write-Host "❌ No track or episode currently playing." -ForegroundColor Red
            return
        }

        $item = $currentTrack.item
        $link = ""
        $name = ""

        if ($currentTrack.currently_playing_type -eq "episode" -or $item.type -eq "episode") {
            # Podcast episode
            $episodeId = $item.id
            $link = "https://open.spotify.com/episode/$episodeId"
            $name = $item.name
            Write-Host "🎙️ $name" -ForegroundColor Magenta
        } else {
            # Music track
            $trackId = $item.id
            $link = "https://open.spotify.com/track/$trackId"
            $artists = ($item.artists | ForEach-Object { $_.name }) -join ", "
            $name = "$($item.name) by $artists"
            Write-Host "🎵 $name" -ForegroundColor Green
        }

        # Copy to clipboard
        Set-Clipboard -Value $link
        Write-Host "📋 Link copied to clipboard: $link" -ForegroundColor Cyan
    }
    catch {
        $errorMessage = $_.Exception.Message
        if ($errorMessage -match "401|Unauthorized|AUTHENTICATION_ERROR") {
            Write-Host "🔐 Authentication Error: Your Spotify session has expired." -ForegroundColor Red
            Write-Host "💡 Solution: Run .\spotifyCLI.ps1 to re-authenticate" -ForegroundColor Yellow
        }
        elseif ($errorMessage -match "404|Not Found") {
            Write-Host "❌ Could not get current track." -ForegroundColor Red
            Write-Host "💡 API Error: $errorMessage" -ForegroundColor Yellow
        }
        else {
            Write-Host "❌ An unexpected error occurred: $errorMessage" -ForegroundColor Red
        }
    }
}

function volume-low {
    <#
    .SYNOPSIS
    Set volume to 25% (low preset)
    .EXAMPLE
    volume-low
    Set volume to 25%
    #>

    volume 25
}

function volume-medium {
    <#
    .SYNOPSIS
    Set volume to 50% (medium preset)
    .EXAMPLE
    volume-medium
    Set volume to 50%
    #>

    volume 50
}

function volume-high {
    <#
    .SYNOPSIS
    Set volume to 75% (high preset)
    .EXAMPLE
    volume-high
    Set volume to 75%
    #>

    volume 75
}

Export-ModuleMember -Function @(
    'play',
    'pause',
    'next',
    'previous',
    'volume',
    'volume-low',
    'volume-medium',
    'volume-high',
    'copy-track-link',
    'export-now-playing',
    'seek',
    'skip-forward',
    'skip-back',
    'replay',
    'shuffle',
    'repeat',
    'transfer'
)