# Verify Ninja Nexus Coolify deployment end-to-end.
# Reads: COOLIFY_API_TOKEN, COOLIFY_BASE_URL, COOLIFY_SERVER_ID, NEXUS_DOMAIN
param(
    [switch]$Json
)

$ErrorActionPreference = "Stop"
. (Join-Path $PSScriptRoot "_lib\CoolifyApi.ps1")
Initialize-CoolifyEnv -AllowSecretScript

$domainUrl = Get-NexusDomainUrl
$report = [ordered]@{
    scope  = "verify_nexus_coolify"
    domain = $env:NEXUS_DOMAIN
    checks = [ordered]@{}
}

function Test-Http {
    param([string]$Url, [string]$Name, [string]$Method = "GET", [hashtable]$Form = $null)
    $entry = [ordered]@{ url = $Url; name = $Name }
    try {
        if ($Method -eq "POST" -and $Form) {
            $resp = Invoke-WebRequest -Uri $Url -Method Post -Body $Form -UseBasicParsing -TimeoutSec 30
        } else {
            $resp = Invoke-WebRequest -Uri $Url -UseBasicParsing -TimeoutSec 30
        }
        $entry.status = [int]$resp.StatusCode
        $entry.ok = ($resp.StatusCode -ge 200 -and $resp.StatusCode -lt 300)
        if ($Url -match '\.json$') {
            $entry.bodyPreview = $resp.Content.Substring(0, [Math]::Min(120, $resp.Content.Length))
        }
    } catch {
        $entry.status = "error"
        $entry.ok = $false
        $entry.error = $_.Exception.Message
    }
    return $entry
}

$project = Get-CoolifyProjectByName -Name "Ninja Nexus"
$report.checks.projectExists = [bool]$project
if ($project) { $report.checks.projectUuid = $project.uuid }

foreach ($svc in @("nexus-backend", "nexus-downloads")) {
    $app = Get-CoolifyApplicationByName -Name $svc
    $report.checks[$svc] = if ($app) {
        [ordered]@{ exists = $true; uuid = $app.uuid; status = $app.status; fqdn = $app.fqdn }
    } else {
        [ordered]@{ exists = $false }
    }
}

$db = Get-CoolifyDatabaseByName -Name "nexus-db"
$report.checks.nexusDb = if ($db) {
    [ordered]@{ exists = $true; uuid = $db.uuid; status = $db.status }
} else {
    [ordered]@{ exists = $false }
}

$report.checks.homePage = Test-Http -Url $domainUrl -Name "download_page"
$report.checks.health = Test-Http -Url "$domainUrl/health" -Name "health"
$report.checks.latestJson = Test-Http -Url "$domainUrl/downloads/latest.json" -Name "latest_json"

try {
    $latest = Invoke-RestMethod -Uri "$domainUrl/downloads/latest.json" -TimeoutSec 20
    $report.checks.manifestVersion = $latest.version
    $report.checks.manifestSha256Prefix = ([string]$latest.sha256).Substring(0, [Math]::Min(12, ([string]$latest.sha256).Length))

    $tmp = Join-Path $env:TEMP ("nexus-verify-" + [Guid]::NewGuid().ToString("N") + ".zip")
    Invoke-WebRequest -Uri $latest.packageUrl -OutFile $tmp -UseBasicParsing -TimeoutSec 120
    $hash = (Get-FileHash $tmp -Algorithm SHA256).Hash.ToLowerInvariant()
    Remove-Item $tmp -Force
    $report.checks.downloadedSha256Prefix = $hash.Substring(0, 12)
    $report.checks.sha256Match = ($hash -eq [string]$latest.sha256)

    if ($latest.installerUrl) {
        $head = Invoke-WebRequest -Uri $latest.installerUrl -Method Head -UseBasicParsing -TimeoutSec 30
        $report.checks.installerStatus = [int]$head.StatusCode
        $report.checks.installerUrl = [string]$latest.installerUrl
    }
} catch {
    $report.checks.zipVerify = @{ ok = $false; error = $_.Exception.Message }
}

$tokenResp = Test-Http -Url "$domainUrl/connect/token" -Name "login" -Method "POST" -Form @{
    grant_type = "password"
    client_id  = "nexus-shell"
    username   = "user@nexus.local"
    password   = "NexusUser1!"
}

if ($tokenResp.ok) {
    try {
        $tokenJson = $tokenResp
        $raw = Invoke-RestMethod -Uri "$domainUrl/connect/token" -Method Post -Body @{
            grant_type = "password"
            client_id  = "nexus-shell"
            username   = "user@nexus.local"
            password   = "NexusUser1!"
        } -TimeoutSec 20
        $report.checks.login = @{ ok = $true; tokenType = $raw.token_type }

        $profile = Invoke-RestMethod -Uri "$domainUrl/api/users/me" -Headers @{
            Authorization = "Bearer $($raw.access_token)"
        } -TimeoutSec 20
        $report.checks.profile = @{
            ok    = $true
            email = $profile.email
            role  = $profile.role
        }
    } catch {
        $report.checks.login = @{ ok = $false; error = $_.Exception.Message }
    }
} else {
    $report.checks.login = @{ ok = $false; status = $tokenResp.status; error = $tokenResp.error }
}

$failures = @()
foreach ($key in @("projectExists", "homePage", "health", "latestJson", "sha256Match", "login")) {
    $val = $report.checks[$key]
    if ($val -is [bool] -and -not $val) { $failures += $key }
    elseif ($val -is [hashtable] -and $val.Contains("ok") -and -not $val.ok) { $failures += $key }
}

$report.summary = if ($failures.Count -eq 0) { "pass" } else { "partial_fail: " + ($failures -join ", ") }

if ($Json) { $report | ConvertTo-Json -Depth 8 } else { $report | ConvertTo-Json -Depth 8 }
return $report
