Public/Get-ShellPhishShowPrep.ps1

function Get-ShellPhishShowPrep {
    <#
    .SYNOPSIS
        Pre-show report: show details, venue history, and recent setlists.
    .PARAMETER Date
        Show date in YYYY-MM-DD format.
    .PARAMETER RecentCount
        Number of recent shows to fetch setlists for. Default 5.
    .PARAMETER ExportPath
        Optional file path (.csv or .json) to export results.
    .PARAMETER DelayMs
        Delay in milliseconds between API calls. Default 500.
    .EXAMPLE
        PS C:\> Get-ShellPhishShowPrep -Date 2026-07-04
    #>

    [CmdletBinding()]
    param (
        [Parameter(Mandatory=$true)]
        [ValidatePattern('^\d{4}-\d{2}-\d{2}$')]
        [string]$Date,

        [Parameter()]
        [int]$RecentCount = 5,

        [Parameter()]
        [string]$ExportPath,

        [Parameter()]
        [int]$DelayMs = 500
    )

    Write-Verbose "Fetching show for $Date..."
    $showResponse = (Get-ShellPhishShows -Date $Date).data

    if (-not $showResponse) {
        Write-Warning "No show found for $Date"
        return
    }

    $show = if ($showResponse -is [array]) { $showResponse[0] } else { $showResponse }

    Write-Host "`n=== SHOW INFO ===" -ForegroundColor Cyan
    Write-Host "Date: $($show.showdate)"
    Write-Host "Venue: $($show.venue)"
    Write-Host "City: $($show.city), $($show.state) $($show.country)"
    Write-Host "Artist: $($show.artist_name)"

    # Venue history - find past shows at this venue
    $today = (Get-Date).ToString('yyyy-MM-dd')
    if ($show.venueid) {
        Write-Verbose "Fetching venue history..."
        Start-Sleep -Milliseconds $DelayMs
        $venueShows = (Get-ShellPhishShows -ArtistId 1).data |
            Where-Object { $_.venueid -eq $show.venueid -and $_.showdate -ne $Date -and $_.showdate -lt $today } |
            Sort-Object showdate -Descending

        if ($venueShows) {
            Write-Host "`n=== VENUE HISTORY ($($venueShows.Count) previous shows) ===" -ForegroundColor Cyan
            $venueShows | Select-Object -First 10 | ForEach-Object {
                Write-Host " $($_.showdate)"
            }
            if ($venueShows.Count -gt 10) {
                Write-Host " ... and $($venueShows.Count - 10) more"
            }
        }
    }

    # Fetch past shows (shared by recent setlists + song gap analysis)
    Write-Verbose "Fetching past shows for setlists and gap analysis..."
    Start-Sleep -Milliseconds $DelayMs
    $pastShows = (Get-ShellPhishShows -Artist phish).data |
        Where-Object { $_.showdate -lt $today } |
        Sort-Object showdate -Descending

    # Recent setlists
    $recentShows = $pastShows | Select-Object -First $RecentCount

    if ($recentShows) {
        Write-Host "`n=== RECENT SETLISTS ===" -ForegroundColor Cyan
        foreach ($recent in $recentShows) {
            Start-Sleep -Milliseconds $DelayMs
            $setlist = (Get-ShellPhishSetlists -ShowDate $recent.showdate).data
            Write-Host "`n $($recent.showdate) - $($recent.venue)" -ForegroundColor Yellow
            if ($setlist) {
                $sets = $setlist | Group-Object -Property set
                foreach ($set in $sets) {
                    $songNames = ($set.Group | ForEach-Object { $_.song }) -join ', '
                    Write-Host " $($set.Name): $songNames"
                }
            }
        }
    }

    # Song gap analysis - songs common in last 25 but absent from last 5
    $last25 = $pastShows | Select-Object -First 25
    $last5  = $pastShows | Select-Object -First 5

    if ($last25.Count -ge 6) {
        Write-Verbose "Analyzing song gaps across last 25 shows..."

        # Collect songs from last 5 shows
        $recentSongs = @{}
        foreach ($s in $last5) {
            Start-Sleep -Milliseconds $DelayMs
            $sl = (Get-ShellPhishSetlists -ShowDate $s.showdate).data
            if ($sl) {
                foreach ($entry in $sl) {
                    $recentSongs[$entry.song] = $true
                }
            }
        }

        # Collect songs from shows 6-25
        $olderShows = $last25 | Select-Object -Skip 5
        $olderSongCounts = @{}
        foreach ($s in $olderShows) {
            Start-Sleep -Milliseconds $DelayMs
            $sl = (Get-ShellPhishSetlists -ShowDate $s.showdate).data
            if ($sl) {
                foreach ($entry in $sl) {
                    if (-not $recentSongs.ContainsKey($entry.song)) {
                        if ($olderSongCounts.ContainsKey($entry.song)) {
                            $olderSongCounts[$entry.song]++
                        } else {
                            $olderSongCounts[$entry.song] = 1
                        }
                    }
                }
            }
        }

        if ($olderSongCounts.Count -gt 0) {
            $predictions = $olderSongCounts.GetEnumerator() |
                Sort-Object Value -Descending |
                Select-Object -First 20

            Write-Host "`n=== SONGS DUE (played in last 25 but not last 5) ===" -ForegroundColor Cyan
            foreach ($p in $predictions) {
                Write-Host " $($p.Value)x $($p.Key)" -ForegroundColor Yellow
            }
        }
    }

    # Build export data
    if ($ExportPath) {
        $exportData = [PSCustomObject]@{
            ShowDate    = $show.showdate
            Venue       = $show.venue
            City        = $show.city
            State       = $show.state
            Country     = $show.country
            Artist      = $show.artist_name
            VenueShowCount = if ($venueShows) { $venueShows.Count } else { 0 }
        }
        Export-ShellPhishData -Data @($exportData) -ExportPath $ExportPath
    }
}