param(
  [switch]$Clean
)

$ErrorActionPreference = "Stop"

$scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
$repoRoot = Resolve-Path (Join-Path $scriptDir "..\..")
$frontendDir = Join-Path $repoRoot "frontend"
$frontendOut = Join-Path $frontendDir "out"
$srcTauriDir = Join-Path $scriptDir "src-tauri"
$tauriConfigPath = Join-Path $srcTauriDir "tauri.conf.json"
$companionDir = Join-Path $srcTauriDir "companion-www"
$backendRuntimeDir = Join-Path $srcTauriDir "backend-runtime"
$iconsScript = Join-Path $scriptDir "scripts\generate-icons.cjs"
$exportScript = Join-Path $scriptDir "scripts\build-frontend-export.cjs"
$backendRuntimeScript = Join-Path $scriptDir "scripts\build-backend-runtime.cjs"
$manifestScript = Join-Path $scriptDir "scripts\write-release-manifest.cjs"
$localUpdaterKey = Join-Path $repoRoot "release-secrets\shadowbroker-updater.key"
$localUpdaterKeyPassword = Join-Path $repoRoot "release-secrets\shadowbroker-updater.key.pass"

function Invoke-External {
  param(
    [Parameter(Mandatory = $true)]
    [string[]]$Command,
    [string]$WorkingDirectory = $scriptDir
  )

  $exe = $Command[0]
  $args = @()
  if ($Command.Length -gt 1) {
    $args = $Command[1..($Command.Length - 1)]
  }

  Push-Location $WorkingDirectory
  try {
    & $exe @args
    if ($LASTEXITCODE -ne 0) {
      throw "Command failed: $($Command -join ' ')"
    }
  }
  finally {
    Pop-Location
  }
}

function Write-Utf8NoBom {
  param(
    [Parameter(Mandatory = $true)]
    [string]$Path,
    [Parameter(Mandatory = $true)]
    [string]$Content
  )

  $encoding = New-Object System.Text.UTF8Encoding($false)
  [System.IO.File]::WriteAllText($Path, $Content, $encoding)
}

foreach ($tool in @("cargo", "npm", "node")) {
  if (-not (Get-Command $tool -ErrorAction SilentlyContinue)) {
    throw "$tool is required for desktop packaging."
  }
}

Push-Location $scriptDir
try {
  & cargo tauri -V *> $null
  if ($LASTEXITCODE -ne 0) {
    throw "The Tauri CLI is required for desktop packaging. Install it with: cargo install tauri-cli@^2"
  }
}
finally {
  Pop-Location
}

if ($Clean) {
  Write-Host "=== Cleaning previous desktop release artifacts ==="
  foreach ($path in @(
    $frontendOut,
    $companionDir,
    $backendRuntimeDir,
    (Join-Path $srcTauriDir "icons"),
    (Join-Path $srcTauriDir "target\\release\\bundle"),
    (Join-Path $srcTauriDir "target\\release\\wix"),
    (Join-Path $srcTauriDir "target\\release\\nsis")
  )) {
    if (Test-Path $path) {
      Remove-Item -LiteralPath $path -Recurse -Force
    }
  }
  Write-Host ""
}

Write-Host "=== Generating branded desktop icons ==="
Invoke-External -Command @("node", $iconsScript)
Write-Host ""

Write-Host "=== Building frontend static export for desktop packaging ==="
Invoke-External -Command @("node", $exportScript)
Write-Host ""

Write-Host "=== Staging managed backend runtime for desktop packaging ==="
Invoke-External -Command @("node", $backendRuntimeScript)
Write-Host ""

if (-not (Test-Path $frontendOut)) {
  throw "frontend/out was not produced by NEXT_OUTPUT=export npm run build"
}
if (-not (Test-Path $backendRuntimeDir)) {
  throw "src-tauri/backend-runtime was not produced by build-backend-runtime.cjs"
}

Write-Host "Copying frontend export to companion-www..."
if (Test-Path $companionDir) {
  Remove-Item -LiteralPath $companionDir -Recurse -Force
}
Copy-Item -LiteralPath $frontendOut -Destination $companionDir -Recurse
$fileCount = (Get-ChildItem -LiteralPath $companionDir -Recurse -File | Measure-Object).Count
Write-Host "  -> $fileCount files"
Write-Host ""

Push-Location $srcTauriDir
$tauriConfigBackup = $null
try {
  if (-not $env:SHADOWBROKER_BACKEND_URL) {
    $env:SHADOWBROKER_BACKEND_URL = "http://127.0.0.1:8000"
  }
  if (
    -not $env:TAURI_SIGNING_PRIVATE_KEY -and
    -not $env:TAURI_SIGNING_PRIVATE_KEY_PATH -and
    (Test-Path $localUpdaterKey)
  ) {
    $env:TAURI_SIGNING_PRIVATE_KEY = Get-Content -LiteralPath $localUpdaterKey -Raw
    if (($null -eq $env:TAURI_SIGNING_PRIVATE_KEY_PASSWORD) -and (Test-Path $localUpdaterKeyPassword)) {
      $env:TAURI_SIGNING_PRIVATE_KEY_PASSWORD = Get-Content -LiteralPath $localUpdaterKeyPassword -Raw
    }
  }

  Write-Host "=== ShadowBroker Tauri Build ==="
  Write-Host "Frontend dist:    $frontendOut"
  Write-Host "Companion www:    $companionDir"
  Write-Host "Backend runtime:  $backendRuntimeDir"
  Write-Host "Backend URL:      $env:SHADOWBROKER_BACKEND_URL"
  if ($env:TAURI_SIGNING_PRIVATE_KEY -or $env:TAURI_SIGNING_PRIVATE_KEY_PATH) {
    Write-Host "Updater signing:  enabled"
  } else {
    Write-Host "Updater signing:  disabled (set TAURI_SIGNING_PRIVATE_KEY_PATH to emit update signatures)"
    $tauriConfigBackup = Get-Content -LiteralPath $tauriConfigPath -Raw
    $tauriConfig = $tauriConfigBackup | ConvertFrom-Json
    if ($tauriConfig.bundle.createUpdaterArtifacts) {
      $tauriConfig.bundle.createUpdaterArtifacts = $false
      $tauriConfig |
        ConvertTo-Json -Depth 100 |
        ForEach-Object { Write-Utf8NoBom -Path $tauriConfigPath -Content ($_ + "`n") }
    }
  }
  Write-Host ""

  cargo tauri build
  if ($LASTEXITCODE -ne 0) {
    throw "cargo tauri build failed."
  }

  $bundleDir = Join-Path $srcTauriDir "target\release\bundle"
  if (Test-Path $bundleDir) {
    Write-Host ""
    Write-Host "=== Writing release manifest ==="
    Invoke-External -Command @("node", $manifestScript, $bundleDir)
  }
}
finally {
  if ($null -ne $tauriConfigBackup) {
    Write-Utf8NoBom -Path $tauriConfigPath -Content $tauriConfigBackup
  }
  Pop-Location
}
