param(
    [string]$Version = "0.1.0-go-skeleton",
    [string]$Product = "qycw",
    [string]$OutputDirectory = (Join-Path $PSScriptRoot "..\..\..\auth\backend\releases"),
    [string]$SecretsFile = (Join-Path $PSScriptRoot "..\.release.env"),
    [switch]$Development
)

$ErrorActionPreference = "Stop"
$serverRoot = (Resolve-Path (Join-Path $PSScriptRoot ".." )).Path
$manifestTool = Join-Path $serverRoot "cmd\release-manifest"
$OutputDirectory = [System.IO.Path]::GetFullPath($OutputDirectory)
New-Item -ItemType Directory -Force -Path $OutputDirectory | Out-Null
if (Test-Path -LiteralPath $SecretsFile) {
    foreach ($line in Get-Content -LiteralPath $SecretsFile) {
        if ($line -match '^([A-Z0-9_]+)=(.+)$' -and -not [Environment]::GetEnvironmentVariable($matches[1])) {
            [Environment]::SetEnvironmentVariable($matches[1], $matches[2], "Process")
        }
    }
}

function Require-EnvironmentVariable([string]$Name) {
    $value = [Environment]::GetEnvironmentVariable($Name)
    if ([string]::IsNullOrWhiteSpace($value)) {
        throw "$Name is required for production packaging"
    }
    return $value.Trim()
}

if ($Development) {
    $licensePublicKey = (& go run $manifestTool -print-license-public-key).Trim()
    $licenseKeyId = "dev-key-2026-01"
    $version = "$Version-dev"
} else {
    $licensePublicKey = Require-EnvironmentVariable "LICENSE_PUBLIC_KEY"
    $licenseKeyId = Require-EnvironmentVariable "LICENSE_KEY_ID"
    [void](Require-EnvironmentVariable "UPDATE_SIGNING_PRIVATE_KEY")
    [void](Require-EnvironmentVariable "UPDATE_SIGNING_KEY_ID")
}

$targets = @(
    @{ OS = "windows"; Arch = "amd64" },
    @{ OS = "windows"; Arch = "arm64" },
    @{ OS = "linux"; Arch = "amd64" },
    @{ OS = "linux"; Arch = "arm64" },
    @{ OS = "darwin"; Arch = "amd64" },
    @{ OS = "darwin"; Arch = "arm64" }
)

$originalGoOS = $env:GOOS
$originalGoArch = $env:GOARCH
$originalCGO = $env:CGO_ENABLED
try {
    Push-Location $serverRoot
    foreach ($target in $targets) {
        $os = $target.OS
        $arch = $target.Arch
        $extension = if ($os -eq "windows") { ".exe" } else { "" }
        $staging = Join-Path $OutputDirectory ".staging-$os-$arch"
        if (Test-Path -LiteralPath $staging) {
            Remove-Item -LiteralPath $staging -Recurse -Force
        }
        New-Item -ItemType Directory -Path $staging | Out-Null

        $env:GOOS = $os
        $env:GOARCH = $arch
        $env:CGO_ENABLED = "0"
        $ldflags = "-s -w -X qycw/go-server/internal/license.EmbeddedPublicKeyBase64=$licensePublicKey -X qycw/go-server/internal/license.EmbeddedPublicKeyID=$licenseKeyId"
        & go build -trimpath -ldflags $ldflags -o (Join-Path $staging "api$extension") ./cmd/api
        if ($LASTEXITCODE -ne 0) { throw "build api for $os/$arch failed" }
        & go build -trimpath -ldflags $ldflags -o (Join-Path $staging "worker$extension") ./cmd/worker
        if ($LASTEXITCODE -ne 0) { throw "build worker for $os/$arch failed" }

        $env:GOOS = $originalGoOS
        $env:GOARCH = $originalGoArch
        $env:CGO_ENABLED = $originalCGO
        $manifestArgs = @("run", $manifestTool, "-product", $Product, "-version", $version, "-os", $os, "-arch", $arch, "-api", (Join-Path $staging "api$extension"), "-worker", (Join-Path $staging "worker$extension"), "-output", (Join-Path $staging "release-manifest.json"))
        if ($Development) { $manifestArgs += "-development" }
        & go @manifestArgs
        if ($LASTEXITCODE -ne 0) { throw "sign manifest for $os/$arch failed" }

        $archive = Join-Path $OutputDirectory "$Product`_$version`_$os`_$arch.zip"
        if (Test-Path -LiteralPath $archive) {
            Remove-Item -LiteralPath $archive -Force
        }
        Compress-Archive -Path (Join-Path $staging "*") -DestinationPath $archive -CompressionLevel Optimal
        $hash = (Get-FileHash -LiteralPath $archive -Algorithm SHA256).Hash.ToLowerInvariant()
        Set-Content -LiteralPath "$archive.sha256" -Value "$hash  $([System.IO.Path]::GetFileName($archive))" -NoNewline
        Remove-Item -LiteralPath $staging -Recurse -Force
        Write-Host "Created $archive"
    }
} finally {
    $env:GOOS = $originalGoOS
    $env:GOARCH = $originalGoArch
    $env:CGO_ENABLED = $originalCGO
    Pop-Location -ErrorAction SilentlyContinue
}
