<#
.SYNOPSIS
    Downloads or refreshes all scanner executables defined in scanners.json.
.DESCRIPTION
    Reads scanner definitions from scanners.json and downloads each scanner EXE
    to the downloads\ subdirectory. Skips scanners with null download URLs.
.PARAMETER Force
    Re-download all scanners even if they already exist locally.
.EXAMPLE
    .\Download-Scanners.ps1
    .\Download-Scanners.ps1 -Force
#>
[CmdletBinding()]
param(
    [switch]$Force
)

Set-StrictMode -Version Latest
$ErrorActionPreference = 'Stop'
$ProgressPreference = 'SilentlyContinue'

$ConfigPath   = Join-Path $PSScriptRoot 'scanners.json'
$DownloadsDir = Join-Path $PSScriptRoot 'downloads'

if (-not (Test-Path $ConfigPath)) {
    Write-Host "[ERROR] scanners.json not found at: $ConfigPath" -ForegroundColor Red
    exit 1
}

$config = Get-Content $ConfigPath -Raw | ConvertFrom-Json

if (-not (Test-Path $DownloadsDir)) {
    New-Item -ItemType Directory -Path $DownloadsDir -Force | Out-Null
    Write-Host "[INFO] Created downloads directory: $DownloadsDir" -ForegroundColor Cyan
}

$results = [System.Collections.Generic.List[pscustomobject]]::new()

foreach ($scanner in $config.scanners) {
    $urlToUse = $null
    $fileToSave = $null

    # Manual-download entries: print instructions and skip
    if ($scanner.PSObject.Properties['manual_download'] -and $scanner.manual_download -eq $true) {
        $note = if ($scanner.PSObject.Properties['manual_download_note']) { $scanner.manual_download_note } else { 'Place EXE manually in downloads\' }
        Write-Host "  [MANUAL] $($scanner.name) — $note" -ForegroundColor Yellow
        $results.Add([pscustomobject]@{ Scanner = $scanner.name; Status = 'MANUAL'; File = ''; Size = 0 })
        continue
    }

    if ($scanner.installer_exe -and $scanner.download_url) {
        $urlToUse  = $scanner.download_url
        $fileToSave = Join-Path $DownloadsDir (Split-Path $scanner.installer_exe -Leaf)
    }
    elseif ($scanner.download_url) {
        $urlToUse  = $scanner.download_url
        $leafName  = Split-Path $scanner.exe -Leaf
        $fileToSave = Join-Path $DownloadsDir $leafName
    }
    else {
        Write-Host "  [SKIP] $($scanner.name) — no download URL configured" -ForegroundColor Yellow
        $results.Add([pscustomobject]@{ Scanner = $scanner.name; Status = 'SKIPPED'; File = ''; Size = 0 })
        continue
    }

    if ((Test-Path $fileToSave) -and -not $Force) {
        $existingSize = (Get-Item $fileToSave).Length
        Write-Host "  [OK]   $($scanner.name) already exists ($([math]::Round($existingSize / 1MB, 1)) MB)" -ForegroundColor Green
        $results.Add([pscustomobject]@{ Scanner = $scanner.name; Status = 'EXISTS'; File = $fileToSave; Size = $existingSize })
        continue
    }

    Write-Host "  [....] $($scanner.name) — downloading from $urlToUse" -ForegroundColor Cyan
    try {
        $wc = New-Object System.Net.WebClient
        $wc.Headers.Add('User-Agent', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)')
        $wc.DownloadFile($urlToUse, $fileToSave)
        $wc.Dispose()

        if (-not (Test-Path $fileToSave)) {
            throw "File not found after download attempt"
        }
        $downloadedSize = (Get-Item $fileToSave).Length
        if ($downloadedSize -eq 0) {
            throw "Downloaded file is 0 bytes — URL may be invalid or redirected"
        }

        Write-Host "  [OK]   $($scanner.name) downloaded ($([math]::Round($downloadedSize / 1MB, 1)) MB) -> $fileToSave" -ForegroundColor Green
        $results.Add([pscustomobject]@{ Scanner = $scanner.name; Status = 'DOWNLOADED'; File = $fileToSave; Size = $downloadedSize })
    }
    catch {
        Write-Host "  [ERROR] $($scanner.name) — $($_.Exception.Message)" -ForegroundColor Red
        if (Test-Path $fileToSave) {
            Remove-Item $fileToSave -Force -ErrorAction SilentlyContinue
        }
        $results.Add([pscustomobject]@{ Scanner = $scanner.name; Status = 'FAILED'; File = $fileToSave; Size = 0 })
    }
}

Write-Host ""
Write-Host "=== Download Summary ===" -ForegroundColor Cyan
$results | Format-Table -AutoSize

$manual = $results | Where-Object { $_.Status -eq 'MANUAL' }
if ($manual) {
    Write-Host "[INFO] $($manual.Count) scanner(s) require manual download — see notes above." -ForegroundColor Yellow
}

$failed = $results | Where-Object { $_.Status -eq 'FAILED' }
if ($failed) {
    Write-Host "[WARNING] $($failed.Count) scanner(s) failed to download. Scan coverage will be incomplete." -ForegroundColor Yellow
    exit 1
}

exit 0
