BountyHunter.psm1

# BountyHunter.psm1

# — Load registry from JSON
$moduleJson = Join-Path $PSScriptRoot 'modules.json'
if (Test-Path $moduleJson) {
    try {
        $Global:BountyModuleIndex = Get-Content $moduleJson -Raw | ConvertFrom-Json
    } catch {
        Write-Warning "Failed to parse modules.json: $_"
        $Global:BountyModuleIndex = @()
    }
} else {
    Write-Warning "modules.json not found at $moduleJson"
    $Global:BountyModuleIndex = @()
}

# ------------------------
# 1. Discovery
# ------------------------

function Get-BountyModules {
    [CmdletBinding()]
    param(
        [string]$Tag
    )

    $list = $Global:BountyModuleIndex
    if ($Tag) {
        $list = $list | Where-Object { $_.Tags -contains $Tag }
    }
    $list | Select-Object Name, Description, @{n='Tags';e={($_.Tags -join ', ')}}
}

function Get-BountyStatus {
    [CmdletBinding()]
    param()

    $results = foreach ($mod in $Global:BountyModuleIndex) {
        # Local installation info
        $inst    = Get-Module -ListAvailable -Name $mod.Name |
                   Sort-Object Version -Descending | Select-Object -First 1
        $instVer = if ($inst) { [version]$inst.Version } else { $null }
        $status  = if ($inst) { '✅ Installed' } else { '❌ Missing' }

        # Remote gallery info
        try {
            $remote    = Find-Module -Name $mod.Name -ErrorAction Stop
            $remoteVer = [version]$remote.Version
        } catch {
            $remoteVer = $null
        }

        $outdated = if ($instVer -and $remoteVer) {
            $remoteVer -gt $instVer
        } else {
            $false
        }

        [PSCustomObject]@{
            Name             = $mod.Name
            Status           = $status
            InstalledVersion = if ($instVer) { $instVer.ToString() } else { '<none>' }
            LatestVersion    = if ($remoteVer) { $remoteVer.ToString() } else { '<unknown>' }
            Outdated         = if ($outdated) { '⚠️ Yes' } else { '😊 No' }
        }
    }

    # Output as table by default
    $results | Format-Table -AutoSize
}

function Install-BountyModules {
    [CmdletBinding()]
    param(
        [switch]$Force
    )

    foreach ($mod in $Global:BountyModuleIndex) {
        $installed = Get-Module -ListAvailable -Name $mod.Name |
                     Sort-Object Version -Descending | Select-Object -First 1
        if (-not $installed -or $Force) {
            try {
                Write-Host "📦 Installing $($mod.Name)..." -ForegroundColor Cyan
                Install-Module -Name $mod.Name -Force:$Force -Scope CurrentUser -ErrorAction Stop
                Write-Host "✅ Installed $($mod.Name)" -ForegroundColor Green
            } catch {
                Write-Warning "❌ Failed to install $($mod.Name): $_"
            }
        } else {
            Write-Host "✔️ Already installed: $($mod.Name)" -ForegroundColor Yellow
        }
    }
}

function Update-BountyModules {
    [CmdletBinding()]
    param()

    foreach ($mod in $Global:BountyModuleIndex) {
        try {
            $installed = Get-Module -ListAvailable -Name $mod.Name |
                         Sort-Object Version -Descending | Select-Object -First 1
            $remote    = Find-Module -Name $mod.Name -ErrorAction Stop

            if ($installed -and [version]$remote.Version -gt [version]$installed.Version) {
                Write-Host "⬆️ Updating $($mod.Name) from $($installed.Version) to $($remote.Version)..." -ForegroundColor Cyan
                Install-Module -Name $mod.Name -Force -Scope CurrentUser -ErrorAction Stop
                Write-Host "✅ Updated $($mod.Name)" -ForegroundColor Green
            } elseif (-not $installed) {
                Write-Host "📦 Not installed: $($mod.Name), installing now..." -ForegroundColor Cyan
                Install-Module -Name $mod.Name -Force -Scope CurrentUser -ErrorAction Stop
                Write-Host "✅ Installed $($mod.Name)" -ForegroundColor Green
            } else {
                Write-Host "✔️ $($mod.Name) is up to date" -ForegroundColor Yellow
            }
        } catch {
            Write-Warning "❌ Failed to update $($mod.Name): $_"
        }
    }
}