param(
  [string]$ConfigPath = "src-tauri/tauri.windows-signing.conf.json"
)

Set-StrictMode -Version Latest
$ErrorActionPreference = "Stop"

function Read-FirstEnv {
  param([string[]]$Names)

  foreach ($Name in $Names) {
    $Value = [Environment]::GetEnvironmentVariable($Name)
    if (-not [string]::IsNullOrWhiteSpace($Value)) {
      return $Value.Trim()
    }
  }

  throw "Set one of these environment variables: $($Names -join ', ')"
}

function Read-OptionalEnv {
  param(
    [string[]]$Names,
    [string]$DefaultValue
  )

  foreach ($Name in $Names) {
    $Value = [Environment]::GetEnvironmentVariable($Name)
    if (-not [string]::IsNullOrWhiteSpace($Value)) {
      return $Value.Trim()
    }
  }

  return $DefaultValue
}

function Normalize-Thumbprint {
  param([string]$Thumbprint)

  return ($Thumbprint -replace "\s", "").ToUpperInvariant()
}

function Convert-CertificateSecretToBytes {
  param([string]$CertificateSecret)

  $Base64Lines = $CertificateSecret -split "\r?\n" |
    Where-Object { $_ -notmatch "^-+BEGIN " -and $_ -notmatch "^-+END " }
  $CertificateBase64 = ($Base64Lines -join "") -replace "\s", ""

  try {
    return [Convert]::FromBase64String($CertificateBase64)
  } catch {
    throw "Windows code-signing certificate must be base64-encoded PFX data."
  }
}

$CertificateSecret = Read-FirstEnv @("WINDOWS_CODE_SIGNING_CERTIFICATE", "WINDOWS_CERTIFICATE")
$CertificatePassword = Read-FirstEnv @("WINDOWS_CODE_SIGNING_CERTIFICATE_PASSWORD", "WINDOWS_CERTIFICATE_PASSWORD")
$ConfiguredThumbprint = Read-OptionalEnv @("WINDOWS_CODE_SIGNING_CERTIFICATE_THUMBPRINT", "WINDOWS_CERTIFICATE_THUMBPRINT") ""
$DigestAlgorithm = Read-OptionalEnv @("WINDOWS_CODE_SIGNING_DIGEST_ALGORITHM") "sha256"
$TimestampUrl = Read-OptionalEnv @("WINDOWS_CODE_SIGNING_TIMESTAMP_URL", "WINDOWS_TIMESTAMP_URL") "http://timestamp.digicert.com"

$TempRoot = Join-Path ([IO.Path]::GetTempPath()) "tolaria-windows-signing"
if (-not [string]::IsNullOrWhiteSpace($env:RUNNER_TEMP)) {
  $TempRoot = Join-Path $env:RUNNER_TEMP "tolaria-windows-signing"
}
New-Item -ItemType Directory -Force -Path $TempRoot | Out-Null

$PfxPath = Join-Path $TempRoot "certificate.pfx"
[IO.File]::WriteAllBytes($PfxPath, (Convert-CertificateSecretToBytes $CertificateSecret))

$SecurePassword = ConvertTo-SecureString -String $CertificatePassword -Force -AsPlainText
$ImportedCertificates = @(Import-PfxCertificate -FilePath $PfxPath -CertStoreLocation Cert:\CurrentUser\My -Password $SecurePassword)
Remove-Item -Force -ErrorAction SilentlyContinue $PfxPath

$ImportedCertificate = $ImportedCertificates | Where-Object { $_.HasPrivateKey } | Select-Object -First 1
if ($null -eq $ImportedCertificate) {
  throw "The imported Windows code-signing certificate does not include a private key."
}

if ([string]::IsNullOrWhiteSpace($ConfiguredThumbprint)) {
  $CertificateThumbprint = Normalize-Thumbprint $ImportedCertificate.Thumbprint
} else {
  $CertificateThumbprint = Normalize-Thumbprint $ConfiguredThumbprint
}

$StoreCertificate = Get-ChildItem Cert:\CurrentUser\My |
  Where-Object { (Normalize-Thumbprint $_.Thumbprint) -eq $CertificateThumbprint } |
  Select-Object -First 1
if ($null -eq $StoreCertificate) {
  throw "The requested Windows code-signing certificate thumbprint was not found in Cert:\CurrentUser\My."
}

$Config = @{
  bundle = @{
    windows = @{
      certificateThumbprint = $CertificateThumbprint
      digestAlgorithm = $DigestAlgorithm
      timestampUrl = $TimestampUrl
    }
  }
}

$ResolvedConfigPath = Resolve-Path -Path (Split-Path -Parent $ConfigPath) -ErrorAction SilentlyContinue
if ($null -eq $ResolvedConfigPath) {
  New-Item -ItemType Directory -Force -Path (Split-Path -Parent $ConfigPath) | Out-Null
}

$Config | ConvertTo-Json -Depth 10 | Set-Content -Path $ConfigPath -Encoding utf8NoBOM

if (-not [string]::IsNullOrWhiteSpace($env:GITHUB_ENV)) {
  "WINDOWS_CODE_SIGNING_CERTIFICATE_THUMBPRINT=$CertificateThumbprint" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8
}

Write-Host "Prepared Windows Authenticode signing config at $ConfigPath."
