PSGalleryBatch.psm1

function Find-GalleryModuleBatch {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)]
        [string]$Name,

        [Parameter()]
        [switch]$AllowPrerelease,

        [Parameter()]
        [switch]$Install,

        [Parameter()]
        [switch]$Update,

        [Parameter()]
        [switch]$Silent
    )

    process {
        # Auto-wildcard for convenience
        if ($Name -notmatch '\*') {
            $Name = "*$Name*"
        }

        Write-Host "Searching for modules matching '$Name'..." -ForegroundColor Cyan
        
        $modules = @()

        try {
            # Try to use Find-PSResource (PSResourceGet v3) first as it supports wildcards + prerelease
            if (Get-Command Find-PSResource -ErrorAction SilentlyContinue) {
                Write-Verbose "Using Find-PSResource"
                $modules = @(Find-PSResource -Name $Name -Repository PSGallery -Prerelease:$AllowPrerelease -ErrorAction Stop)
            }
            else {
                Write-Verbose "Using Find-Module (PowerShellGet v2)"
                if ($AllowPrerelease -and $Name -match '\*') {
                    Write-Warning "PowerShellGet (Find-Module) does not support Wildcards with -AllowPrerelease. SEARCHING STABLE ONLY."
                    $modules = @(Find-Module -Name $Name -Repository PSGallery -ErrorAction Stop)
                }
                else {
                    $modules = @(Find-Module -Name $Name -Repository PSGallery -AllowPrerelease:$AllowPrerelease -ErrorAction Stop)
                }
            }
            
            if ($modules.Count -eq 0) {
                Write-Warning "No modules found matching '$Name'."
                return
            }

            Write-Host "Found $($modules.Count) modules." -ForegroundColor Green
            
            $selected = @()
            if ($Silent) {
                Write-Host "Silent mode: Selecting all $($modules.Count) modules." -ForegroundColor Yellow
                $selected = $modules
            }
            else {
                # Invoke UI selection
                $selected = Show-ModuleSelection -Modules $modules
            }
            
            if ($selected) {
                Write-Host "`nProcessing $($selected.Count) selected module(s)..." -ForegroundColor Cyan
                if ($Install) {
                    $selected | Install-GalleryModuleBatch -AllowPrerelease:$AllowPrerelease
                }
                elseif ($Update) {
                    $selected | Update-GalleryModuleBatch -AllowPrerelease:$AllowPrerelease
                }
                else {
                    return $selected
                }
            }
        }
        catch {
            Write-Warning "Search failed: $_"
        }
    }
}

function Show-ModuleSelection {
    param(
        [Parameter(Mandatory = $true)]
        [array]$Modules
    )
    
    # Attempt to use Spectre Console if available
    if (Get-Command Read-SpectreMultiSelection -ErrorAction SilentlyContinue) {
        $choices = $Modules | ForEach-Object {
            $desc = if ($_.Description -and $_.Description.Length -gt 60) { $_.Description.Substring(0, 57) + "..." } else { $_.Description }
            "$($_.Name) ($($_.Version)) - $desc"
        }
        
        $selectedStrings = Read-SpectreMultiSelection -Message "[cyan]Select modules to process (Space to toggle, Enter to confirm)[/]" `
            -Choices $choices `
            -Color "Green" `
            -PageSize 20
            
        if (-not $selectedStrings) { return $null }

        $results = foreach ($sel in $selectedStrings) {
            if ($sel -match '^(.+?)\s+\((.+?)\)\s+-') {
                $mName = $matches[1]
                $mVer = $matches[2]
                $Modules | Where-Object { $_.Name -eq $mName -and $_.Version -eq $mVer } | Select-Object -First 1
            }
        }
        return $results
    }
    else {
        Write-Warning "Spectre Console 'Read-SpectreMultiSelection' not found. Using Out-GridView."
        return $Modules | Out-GridView -Title "Select Modules" -PassThru
    }
}

function Install-GalleryModuleBatch {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
        $InputObject,

        [Parameter()]
        [switch]$AllowPrerelease
    )
    
    begin { $items = @() }
    process { $items += $InputObject }
    end {
        if ($items.Count -eq 0) { return }
        foreach ($mod in $items) {
            Write-Host "Installing: " -ForegroundColor Magenta -NoNewline
            Write-Host "$($mod.Name) ($($mod.Version))" -ForegroundColor White
            try {
                if (Get-Command Install-PSResource -ErrorAction SilentlyContinue) {
                    # Removed -Force (not supported), using -TrustRepository
                    Install-PSResource -Name $mod.Name -Version $mod.Version -Prerelease:$AllowPrerelease -TrustRepository -Scope CurrentUser -ErrorAction Stop
                }
                else {
                    Install-Module -Name $mod.Name -RequiredVersion $mod.Version -AllowPrerelease:$AllowPrerelease -Scope CurrentUser -Force -AllowClobber -ErrorAction Stop
                }
                Write-Host "✓ Successfully installed $($mod.Name)" -ForegroundColor Green
            }
            catch { Write-Error "✗ Failed to install $($mod.Name): $_" }
        }
    }
}

function Update-GalleryModuleBatch {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
        $InputObject,

        [Parameter()]
        [switch]$AllowPrerelease
    )
    
    begin { $items = @() }
    process { $items += $InputObject }
    end {
        if ($items.Count -eq 0) { return }
        foreach ($mod in $items) {
            Write-Host "Updating: " -ForegroundColor Magenta -NoNewline
            Write-Host "$($mod.Name)" -ForegroundColor White
            try {
                if (Get-Command Update-PSResource -ErrorAction SilentlyContinue) {
                    Update-PSResource -Name $mod.Name -Prerelease:$AllowPrerelease -TrustRepository -ErrorAction Stop
                }
                else {
                    Update-Module -Name $mod.Name -AllowPrerelease:$AllowPrerelease -Force -ErrorAction Stop
                }
                Write-Host "✓ Successfully updated $($mod.Name)" -ForegroundColor Green
            }
            catch { Write-Error "✗ Failed to update $($mod.Name): $_" }
        }
    }
}