# Publish Nexus update channel to Coolify-hosted static downloads.
# Never prints API tokens or secrets.
param(
  [string]$DistRoot = "",
  [string]$DownloadBaseUrl = "",
  [switch]$DryRun,
  [switch]$SkipUpload,
  [switch]$Json
)

$ErrorActionPreference = "Stop"

function Save-Evidence {
  param($Report, $Manifest, [string]$Dir, [string]$ChannelUrl)
  ($Manifest | ConvertTo-Json -Depth 6) | Set-Content (Join-Path $Dir "latest-manifest.json") -Encoding UTF8
  ($Report | ConvertTo-Json -Depth 6) | Set-Content (Join-Path $Dir "publish-report.json") -Encoding UTF8
  @"
# Nexus Update Channel Evidence

- Version: $($Manifest.version)
- Build: $($Manifest.build)
- SHA256: $($Manifest.sha256)
- Channel: $ChannelUrl
- Published: $((Get-Date).ToUniversalTime().ToString('o'))
"@ | Set-Content (Join-Path $Dir "SUMMARY.md") -Encoding UTF8
}

function Verify-RemoteChannel {
  param([string]$ChannelUrl, [string]$ExpectedSha256)
  $result = [ordered]@{}

  try {
    $health = Invoke-WebRequest -Uri "https://nexus.ninjakernen.info/health" -UseBasicParsing -TimeoutSec 20
    $result.healthStatus = [int]$health.StatusCode
  } catch {
    $result.healthStatus = "error"
    $result.healthError = $_.Exception.Message
  }

  try {
    $wc = New-Object System.Net.WebClient
    $bytes = $wc.DownloadData("$ChannelUrl/latest.json")
    $text = if ($bytes.Length -ge 3 -and $bytes[0]-eq 0xEF -and $bytes[1]-eq 0xBB -and $bytes[2]-eq 0xBF) {
      [Text.Encoding]::UTF8.GetString($bytes, 3, $bytes.Length - 3)
    } else {
      [Text.Encoding]::UTF8.GetString($bytes)
    }
    $remote = $text | ConvertFrom-Json
    $result.latestJsonStatus = 200
    $result.remoteVersion = $remote.version
    $result.remoteSha256 = $remote.sha256

    $tmp = Join-Path $env:TEMP ("nexus-verify-" + [Guid]::NewGuid().ToString("N") + ".zip")
    Invoke-WebRequest -Uri $remote.packageUrl -OutFile $tmp -UseBasicParsing -TimeoutSec 120
    $hash = (Get-FileHash $tmp -Algorithm SHA256).Hash.ToLowerInvariant()
    Remove-Item $tmp -Force
    $result.downloadedSha256 = $hash
    $result.sha256Match = ($hash -eq $ExpectedSha256)
    $result.packageUrlStatus = 200
  } catch {
    $result.latestJsonStatus = "error"
    $result.verifyError = $_.Exception.Message
  }

  return $result
}

function Get-TempFileDownloadUrl {
  param([string]$FilePath)
  . (Join-Path (Split-Path -Parent $PSScriptRoot) "coolify\_lib\CoolifyApi.ps1")
  return Get-CatboxUploadUrl -FilePath $FilePath
}

$repoRoot = Split-Path -Parent (Split-Path -Parent $PSScriptRoot)
if (-not $DistRoot) { $DistRoot = Join-Path $repoRoot "dist\nexus-laptop-poc" }
if (-not $DownloadBaseUrl) {
  $DownloadBaseUrl = if ($env:NEXUS_DOWNLOAD_BASE_URL) { $env:NEXUS_DOWNLOAD_BASE_URL.TrimEnd('/') } else { "https://nexus.ninjakernen.info/downloads" }
}

$uploadRoot = Join-Path $DistRoot "upload"
$latestPath = Join-Path $uploadRoot "downloads\latest.json"
$zipPath = Join-Path $uploadRoot "downloads\nexus-shell-poc.zip"

if (-not (Test-Path $latestPath)) {
  Write-Host "Upload folder missing — running build-installer.ps1 first..." -ForegroundColor Yellow
  & (Join-Path $PSScriptRoot "build-installer.ps1") -DownloadBaseUrl $DownloadBaseUrl | Out-Null
}

if (-not (Test-Path $latestPath)) { throw "Missing $latestPath — run build-package.ps1 first." }

$manifest = Get-Content $latestPath -Raw | ConvertFrom-Json
$version = [string]$manifest.version
$releaseDir = Join-Path $uploadRoot "downloads\releases\$version"
$evidenceDir = Join-Path $repoRoot "docs\evidence\nexus-update-channel"
New-Item -ItemType Directory -Path $evidenceDir -Force | Out-Null

$report = [ordered]@{
  scope           = "nexus_update_channel_publish"
  version         = $version
  build           = $manifest.build
  sha256Prefix    = ([string]$manifest.sha256).Substring(0, 12)
  sizeBytes       = $manifest.sizeBytes
  downloadBaseUrl = $DownloadBaseUrl
  uploadRoot      = $uploadRoot
  dryRun          = [bool]$DryRun
  uploadStatus    = "skipped"
}

if ($DryRun -or $SkipUpload) {
  $manualPath = Join-Path $evidenceDir "manual-upload-instructions.md"
  @"
# Manual Coolify upload — Nexus update channel

Generated: $((Get-Date).ToUniversalTime().ToString('o'))

## Local upload folder

``````
$uploadRoot
``````

Copy to Coolify volume `/usr/share/nginx/html`:

| Local | Remote |
|-------|--------|
| upload/downloads/latest.json | downloads/latest.json |
| upload/downloads/sha256.txt | downloads/sha256.txt |
| upload/downloads/nexus-shell-poc.zip | downloads/nexus-shell-poc.zip |
| upload/downloads/NexusSetup.exe | downloads/NexusSetup.exe |
| upload/downloads/releases/$version/* | downloads/releases/$version/ |

## Verify

``````powershell
Invoke-RestMethod https://nexus.ninjakernen.info/health
Invoke-RestMethod $DownloadBaseUrl/latest.json
``````
"@ | Set-Content -LiteralPath $manualPath -Encoding UTF8

  $report.manualInstructions = $manualPath
  $report.uploadStatus = if ($DryRun) { "dry_run" } else { "skipped" }
  Save-Evidence $report $manifest $evidenceDir $DownloadBaseUrl
  if ($Json) { $report | ConvertTo-Json -Depth 5 } else { $report | Format-List }
  return $report
}

. (Join-Path (Split-Path -Parent $PSScriptRoot) "coolify\_lib\CoolifyApi.ps1")
Initialize-CoolifyEnv -AllowSecretScript

$base = $script:CoolifyBaseUrl
$token = $env:COOLIFY_API_TOKEN
$appUuid = $env:NEXUS_COOLIFY_APP_UUID

if ([string]::IsNullOrWhiteSpace($appUuid)) {
  $downloadsApp = Get-CoolifyApplicationByName -Name "nexus-downloads"
  if ($downloadsApp) {
    $appUuid = [string]$downloadsApp.uuid
    Write-Host "Resolved nexus-downloads app UUID from Coolify API." -ForegroundColor DarkGray
  }
}

if ([string]::IsNullOrWhiteSpace($appUuid)) {
  throw "Set NEXUS_COOLIFY_APP_UUID for automated deploy, or use -DryRun."
}

$headers = @{ Authorization = "Bearer $token"; Accept = "application/json" }

function Invoke-CoolifyJson {
  param([string]$Method, [string]$Path, [object]$Body = $null)
  $uri = "$base$Path"
  $params = @{ Method = $Method; Uri = $uri; Headers = $headers; TimeoutSec = 300 }
  if ($null -ne $Body) {
    $params.ContentType = "application/json"
    $params.Body = ($Body | ConvertTo-Json -Depth 8 -Compress)
  }
  return Invoke-RestMethod @params
}

Write-Host "Staging temporary HTTPS URLs for container wget..." -ForegroundColor Cyan
$filesToUpload = @(
  @{ Local = $latestPath; Remote = "/usr/share/nginx/html/downloads/latest.json" }
  @{ Local = Join-Path $uploadRoot "downloads\sha256.txt"; Remote = "/usr/share/nginx/html/downloads/sha256.txt" }
  @{ Local = $zipPath; Remote = "/usr/share/nginx/html/downloads/nexus-shell-poc.zip" }
  @{ Local = Join-Path $releaseDir "manifest.json"; Remote = "/usr/share/nginx/html/downloads/releases/$version/manifest.json" }
  @{ Local = Join-Path $releaseDir "sha256.txt"; Remote = "/usr/share/nginx/html/downloads/releases/$version/sha256.txt" }
  @{ Local = Join-Path $releaseDir "nexus-shell-poc.zip"; Remote = "/usr/share/nginx/html/downloads/releases/$version/nexus-shell-poc.zip" }
  @{ Local = Join-Path $uploadRoot "downloads\NexusSetup.exe"; Remote = "/usr/share/nginx/html/downloads/NexusSetup.exe" }
  @{ Local = Join-Path $releaseDir "NexusSetup.exe"; Remote = "/usr/share/nginx/html/downloads/releases/$version/NexusSetup.exe" }
)

$wgetParts = @("mkdir -p /usr/share/nginx/html/downloads/releases/$version")
foreach ($f in $filesToUpload) {
  if (-not (Test-Path $f.Local)) {
    Write-Host "Skipping missing upload file: $($f.Local)" -ForegroundColor Yellow
    continue
  }
  $url = Get-TempFileDownloadUrl -FilePath $f.Local
  $wgetParts += "wget -qO $($f.Remote) '$url'"
}
$wgetCmd = ($wgetParts -join " && ")

Write-Host "Deploying to Coolify app (uuid from env)..." -ForegroundColor Cyan
Invoke-CoolifyJson -Method Patch -Path "/api/v1/applications/$appUuid" -Body @{
  post_deployment_command = $wgetCmd
} | Out-Null

$deploy = Invoke-CoolifyJson -Method Get -Path "/api/v1/deploy?uuid=$appUuid&force=true"
$report.coolifyAppUuid = $appUuid
$report.deployUuid = $deploy.deployment_uuid
$report.uploadStatus = "deploy_triggered"

Write-Host "Waiting for deploy..." -ForegroundColor Cyan
Start-Sleep -Seconds 120

$report.verify = Verify-RemoteChannel -ChannelUrl $DownloadBaseUrl -ExpectedSha256 ([string]$manifest.sha256)
$report.healthUrl = "https://nexus.ninjakernen.info/health"

Save-Evidence $report $manifest $evidenceDir $DownloadBaseUrl

if ($Json) { $report | ConvertTo-Json -Depth 6 } else { $report | Format-List }
return $report
