param(
  [switch]$EvaluationOnly,
  [string]$PaidTestLicense = $env:SMARTCUT_PAID_TEST_LICENSE
)
$ErrorActionPreference = 'Stop'
$repo = Split-Path -Parent $PSScriptRoot
. (Join-Path $repo 'scripts/hash-utils.ps1')
$preset = 'windows-ucrt-gui-release'
$projectDeclaration = Get-Content -LiteralPath (Join-Path $repo 'CMakeLists.txt') -Raw
if ($projectDeclaration -notmatch 'project\(SmartCut64 VERSION ([0-9]+\.[0-9]+\.[0-9]+) LANGUAGES CXX\)') {
  throw 'Could not determine the SmartCut64 project version from CMakeLists.txt'
}
$version = $Matches[1]
$windowsPowerShell = Join-Path $PSHOME 'powershell.exe'
if (-not (Test-Path -LiteralPath $windowsPowerShell -PathType Leaf)) {
  throw "Could not locate the current Windows PowerShell executable: $windowsPowerShell"
}
$packageRoot = "SmartCut64-$version-win64"
$sourceRoot = "SmartCut64-$version-source"
Push-Location $repo
try {
  $env:PATH = "C:\msys642\ucrt64\bin;C:\msys642\usr\bin;$env:PATH"
  $gitExe = 'C:\Program Files\Git\cmd\git.exe'
  if (-not (Test-Path -LiteralPath $gitExe)) { $gitExe = (Get-Command git.exe).Source }
  $worktreeChanges = & $gitExe status --porcelain --untracked-files=all
  if ($worktreeChanges) { throw "Release gate requires a completely clean worktree, including no untracked source or release files:`n$worktreeChanges" }
  & $windowsPowerShell -NoProfile -NonInteractive -ExecutionPolicy Bypass -File (Join-Path $repo 'scripts/check-private-material.ps1')
  if ($LASTEXITCODE -ne 0) { throw 'Private-material source gate failed' }
  cmake --preset $preset
  if ($LASTEXITCODE -ne 0) { throw 'Release configuration failed' }
  $buildDir = Join-Path $repo "build/$preset"
  $cacheFile = Join-Path $buildDir 'CMakeCache.txt'
  $modulusEntry = @(Get-Content -LiteralPath $cacheFile | Where-Object { $_ -match '^SMARTCUT_LICENSE_PUBLIC_MODULUS_HEX:[^=]+=' } | Select-Object -First 1)
  $publicModulus = if ($modulusEntry.Count -eq 1) { ($modulusEntry[0] -split '=', 2)[1] } else { '' }
  if (-not $EvaluationOnly -and
      ($publicModulus -notmatch '^[0-9A-Fa-f]{512,}$' -or ($publicModulus.Length % 2) -ne 0)) {
    throw 'Commercial release gate requires a configured RSA public licence modulus of at least 2048 bits; use -EvaluationOnly only for a clearly labelled non-paid Evaluation build'
  }
  $serviceEntry = @(Get-Content -LiteralPath $cacheFile | Where-Object { $_ -match '^SMARTCUT_LICENSE_SERVICE_URL:[^=]+=' } | Select-Object -First 1)
  $licenceServiceUrl = if ($serviceEntry.Count -eq 1) { ($serviceEntry[0] -split '=', 2)[1] } else { '' }
  if (-not $EvaluationOnly -and ($licenceServiceUrl -notmatch '^https://[^\s]+$' -or
      $licenceServiceUrl -match '(?i)(example\.(com|org|net)|localhost|127\.0\.0\.1)')) {
    throw 'Commercial release gate requires the real HTTPS SmartCut64 activation-service URL; example and localhost URLs are rejected'
  }

  $paidTestLicensePath = $null
  if (-not $EvaluationOnly) {
    if ([string]::IsNullOrWhiteSpace($PaidTestLicense)) {
      throw 'Commercial release gate requires -PaidTestLicense (or SMARTCUT_PAID_TEST_LICENSE) containing a paid token signed by the configured production key and bound to this build machine'
    }
    $paidTestLicensePath = [IO.Path]::GetFullPath($PaidTestLicense)
    if (-not (Test-Path -LiteralPath $paidTestLicensePath -PathType Leaf)) { throw "Paid release-test licence is unavailable: $paidTestLicensePath" }
  }
  cmake --build --preset $preset
  if ($LASTEXITCODE -ne 0) { throw 'Release build failed' }
  ctest --preset $preset --output-on-failure
  if ($LASTEXITCODE -ne 0) { throw 'Release test suite failed' }
  if (-not $EvaluationOnly) {
    $paidGateOutput = Join-Path $buildDir 'test-results/paid-entitlement-release'
    & cmake `
      "-DWORKER=$(Join-Path $buildDir 'smartcut-worker.exe')" `
      "-DCLI=$(Join-Path $buildDir 'smartcut-cli.exe')" `
      "-DINPUT=$(Join-Path $buildDir 'test-fixtures/m4-av-fixture.mkv')" `
      "-DOUTPUT_PREFIX=$paidGateOutput" `
      "-DLICENSE_FILE=$paidTestLicensePath" `
      -P (Join-Path $repo 'cmake/paid-entitlement-delivery-gate.cmake')
    if ($LASTEXITCODE -ne 0) {
      throw 'The paid token was not accepted by the exact production worker and CLI build, or clean delivery was not preserved'
    }
  }
  Push-Location $buildDir
  try {
    cpack -G ZIP
    if ($LASTEXITCODE -ne 0) { throw 'ZIP package generation failed' }
    cpack -G NSIS
    if ($LASTEXITCODE -ne 0) { throw 'NSIS package generation failed' }
  } finally { Pop-Location }
  & $windowsPowerShell -NoProfile -NonInteractive -ExecutionPolicy Bypass -File (Join-Path $repo 'scripts/rebuild-user-installer.ps1') -BuildDir $buildDir
  if ($LASTEXITCODE -ne 0) { throw 'Per-user installer generation failed' }
  $results = Join-Path $buildDir 'test-results'
  $contract = Join-Path $results 'gui-probe-contract.json'
  $summary = Join-Path $results 'gui-probe-contract.json.release-summary.json'
  if (-not (Test-Path -LiteralPath $contract)) { throw "Missing probe contract: $contract" }
  if (-not (Test-Path -LiteralPath $summary)) { throw "Missing release summary: $summary" }
  $contractJson = Get-Content -Raw -LiteralPath $contract | ConvertFrom-Json
  $summaryJson = Get-Content -Raw -LiteralPath $summary | ConvertFrom-Json
  if ($contractJson.schema -ne 'smartcut-gui-probe-contract-v1' -or $contractJson.audio_info -ne 'PASSED' -or $contractJson.source_identity -ne 'PASSED' -or $contractJson.project_summary -ne 'PASSED') { throw 'Probe contract failed release validation' }
  if ($summaryJson.schema -ne 'smartcut-gui-release-gate-v1' -or $summaryJson.status -ne 'PASSED') { throw 'Release summary failed validation' }
  $package = Join-Path $buildDir "$packageRoot.zip"
  if (-not (Test-Path -LiteralPath $package)) { throw "Missing package: $package" }
  Add-Type -AssemblyName System.IO.Compression.FileSystem
  $archive = [System.IO.Compression.ZipFile]::OpenRead($package)
  try {
    $entries = @($archive.Entries | ForEach-Object FullName)
    $packagePrefix = "$packageRoot/"
    $requiredEntries = @('bin/smartcut-cli.exe', 'bin/smartcut-worker.exe', 'bin/smartcut-gui.exe', 'LICENSE', 'COPYRIGHT', 'COMMERCIAL_DISTRIBUTION.md', 'THIRD_PARTY.md', 'docs/PAID_ENTITLEMENTS.md', 'bin/avcodec-63.dll', 'bin/avdevice-63.dll', 'bin/avfilter-12.dll', 'bin/avformat-63.dll', 'bin/avutil-61.dll', 'bin/swresample-7.dll', 'bin/swscale-10.dll', 'bin/libplacebo-349.dll', 'bin/libvpl-2.dll', 'bin/Qt6Widgets.dll', 'bin/qt.conf', 'bin/tls/qcertonlybackend.dll', 'bin/tls/qopensslbackend.dll', 'bin/tls/qschannelbackend.dll', 'bin/libgcc_s_seh-1.dll', 'bin/libstdc++-6.dll', 'bin/libwinpthread-1.dll', 'bin/libb2-1.dll', 'bin/libpcre2-16-0.dll', 'bin/libzstd.dll', 'bin/zlib1.dll', 'bin/libbrotlidec.dll', 'bin/libbrotlicommon.dll', 'symbols/smartcut-cli.exe.dbg', 'symbols/smartcut-worker.exe.dbg', 'symbols/smartcut-gui.exe.dbg', 'licenses/ffmpeg/COPYING.GPLv2', 'licenses/x264/COPYING', 'licenses/x265/COPYING', 'licenses/libaom/LICENSE', 'licenses/libvpx/LICENSE', 'licenses/runtime/gcc-libs/COPYING.RUNTIME', 'licenses/runtime/libvpl/LICENSE', 'licenses/runtime/ffnvcodec-headers/LICENSE', 'licenses/runtime/amf-headers/LICENSE', 'sbom.m1.json') | ForEach-Object { $packagePrefix + $_ }
    $requiredEntries += @('PRIVACY.md', 'CUSTOMER_TERMS.md', 'REFUND_POLICY.md',
      'SUPPORT.md', 'SECURITY.md', 'docs/PRODUCT_LISTING.md',
      'docs/LEMON_SQUEEZY_LAUNCH.md', 'docs/EXTERNAL_RELEASE_BLOCKERS.md',
      'docs/RELEASE_NOTES.md', 'docs/USER_GUIDE.md') |
      ForEach-Object { $packagePrefix + $_ }
    $missingEntries = @($requiredEntries | Where-Object { $_ -notin $entries })
    if ($missingEntries.Count -gt 0) { throw "Package is missing required entries: $($missingEntries -join ', ')" }
    $forbiddenTestEntries = @($entries | Where-Object {
      $_ -match '(?i)(?:^|/)internal-test-bin/' -or $_ -match '(?i)smartcut-(cli|worker|gui)-test(?:\.exe|\.dbg)?$'
    })
    if ($forbiddenTestEntries.Count -gt 0) {
      throw "Package contains internal entitlement-bypass test executables or symbols: $($forbiddenTestEntries -join ', ')"
    }
    $forbiddenEntitlementEntries = @($entries | Where-Object {
      $_ -match '(?i)\.(pem|der|jks|keystore|p8|pk8|pfx|p12|sc64|key)$'
    })
    if ($forbiddenEntitlementEntries.Count -gt 0) {
      throw "Binary package contains forbidden entitlement or private-key material: $($forbiddenEntitlementEntries -join ', ')"
    }
    $retailGui = $archive.GetEntry($packagePrefix + 'bin/smartcut-gui.exe')
    if (-not $retailGui) { throw 'Retail GUI is missing from the package' }
    $memory = [IO.MemoryStream]::new()
    try {
      $entryStream = $retailGui.Open()
      try { $entryStream.CopyTo($memory) } finally { $entryStream.Dispose() }
      $retailStrings = [Text.Encoding]::ASCII.GetString($memory.ToArray())
      foreach ($forbiddenString in @('--automation-', '--smoke-test', 'SMARTCUT64_LICENSE_SERVICE_URL')) {
        if ($retailStrings.Contains($forbiddenString)) {
          throw "Retail GUI contains internal-only functionality or configuration override: $forbiddenString"
        }
      }
    } finally { $memory.Dispose() }
  } finally { $archive.Dispose() }
  & $windowsPowerShell -NoProfile -NonInteractive -ExecutionPolicy Bypass -File (Join-Path $repo 'scripts/package-install-test.ps1') -Package $package
  if ($LASTEXITCODE -ne 0) { throw 'Package install/uninstall validation failed' }
  $installer = Join-Path $buildDir "$packageRoot.exe"
  if (-not (Test-Path -LiteralPath $installer)) { throw "Missing installer: $installer" }
  & $windowsPowerShell -NoProfile -NonInteractive -ExecutionPolicy Bypass -File (Join-Path $repo 'scripts/installer-install-test.ps1') -Installer $installer
  if ($LASTEXITCODE -ne 0) { throw 'Installer install/uninstall validation failed' }
  $sourceBundle = Join-Path $buildDir "$sourceRoot.zip"
  & $windowsPowerShell -NoProfile -NonInteractive -ExecutionPolicy Bypass -File (Join-Path $repo 'dependencies/scripts/package-source-bundle.ps1') -Output $sourceBundle
  if ($LASTEXITCODE -ne 0 -or -not (Test-Path -LiteralPath $sourceBundle)) { throw 'Corresponding source bundle validation failed' }
  $sourceArchive = [System.IO.Compression.ZipFile]::OpenRead($sourceBundle)
  try {
    $sourceEntries = @($sourceArchive.Entries | ForEach-Object FullName)
    $dependencyManifest = Get-Content -Raw -LiteralPath (Join-Path $repo 'dependencies/manifests/m1-dependencies.json') | ConvertFrom-Json
    $requiredSourceArchiveEntries = @($dependencyManifest.dependencies |
      Where-Object { $_.name -in @('ffmpeg', 'qt') } |
      ForEach-Object {
        $archiveName = if ($_.archiveFile) { $_.archiveFile } else { "$($_.name).archive" }
        "$sourceRoot/sources/$archiveName"
      })
    $requiredSourceEntries = @(
      "$sourceRoot/project/CMakeLists.txt",
      "$sourceRoot/project/src/gui/main.cpp",
      "$sourceRoot/project/src/worker/main.cpp",
      "$sourceRoot/project/schemas/project-v1.schema.json",
      "$sourceRoot/project/LICENSE",
      "$sourceRoot/project/COPYRIGHT",
      "$sourceRoot/project/COMMERCIAL_DISTRIBUTION.md",
      "$sourceRoot/project/docs/PAID_ENTITLEMENTS.md",
      "$sourceRoot/project/docs/RELEASE_NOTES.md",
      "$sourceRoot/project/docs/USER_GUIDE.md",
      "$sourceRoot/project/cmake/entitlement-delivery-gate.cmake",
      "$sourceRoot/project/cmake/paid-entitlement-delivery-gate.cmake",
      "$sourceRoot/project/src/core/entitlement.cpp",
      "$sourceRoot/project/src/core/entitlement.hpp",
      "$sourceRoot/project/src/core/json.hpp",
      "$sourceRoot/project/src/core/control_ipc.cpp",
      "$sourceRoot/project/src/core/control_ipc.hpp",
      "$sourceRoot/project/src/gui/license_manager.cpp",
      "$sourceRoot/project/src/gui/license_manager.hpp",
      "$sourceRoot/project/src/media/trial_watermark.cpp",
      "$sourceRoot/project/src/media/trial_watermark.hpp",
      "$sourceRoot/project/cmake/license_service_config.hpp.in",
      "$sourceRoot/project/PRIVACY.md",
      "$sourceRoot/project/CUSTOMER_TERMS.md",
      "$sourceRoot/project/REFUND_POLICY.md",
      "$sourceRoot/project/SUPPORT.md",
      "$sourceRoot/project/SECURITY.md",
      "$sourceRoot/project/docs/LEMON_SQUEEZY_LAUNCH.md",
      "$sourceRoot/project/docs/PRODUCT_LISTING.md",
      "$sourceRoot/project/services/licensing-bridge/README.md",
      "$sourceRoot/project/services/licensing-bridge/package.json",
      "$sourceRoot/project/services/licensing-bridge/wrangler.toml.example",
      "$sourceRoot/project/services/licensing-bridge/src/worker.mjs",
      "$sourceRoot/project/services/licensing-bridge/test/worker.test.mjs",
      "$sourceRoot/project/scripts/check-private-material.ps1",
      "$sourceRoot/project/cmake/worker-argument-validation-gate.cmake",
      "$sourceRoot/project/tools/New-SmartCut64LicenseKey.ps1",
      "$sourceRoot/project/tools/New-SmartCut64License.ps1",
      "$sourceRoot/project/dependencies/scripts/build-ffmpeg-m1.sh",
      "$sourceRoot/project/dependencies/manifests/hardware-codec-build-packages.json",
      "$sourceRoot/project/dependencies/patches/ffmpeg-scale-d3d11-preview.patch"
    )
    $requiredSourceEntries += $requiredSourceArchiveEntries
    $missingSourceEntries = @($requiredSourceEntries | Where-Object { $_ -notin $sourceEntries })
    if ($missingSourceEntries.Count -gt 0) { throw "Corresponding source bundle is incomplete: $($missingSourceEntries -join ', ')" }
    $forbiddenKeyEntries = @($sourceEntries | Where-Object {
      $_ -match '(?i)\.(pem|der|jks|keystore|p8|pk8|pfx|p12|sc64|key)$'
    })
    if ($forbiddenKeyEntries.Count -gt 0) { throw "Corresponding source bundle contains forbidden private entitlement material: $($forbiddenKeyEntries -join ', ')" }
  } finally { $sourceArchive.Dispose() }
  $checksumFile = Join-Path $buildDir "SmartCut64-$version-SHA256SUMS.txt"
  $checksumLines = @($package, $installer, $sourceBundle) | ForEach-Object {
    $hash = (Get-SmartCutSha256 -LiteralPath $_).ToLowerInvariant()
    "$hash  $([IO.Path]::GetFileName($_))"
  }
  [IO.File]::WriteAllLines($checksumFile, $checksumLines, [Text.Encoding]::ASCII)
  Write-Host "Release gate passed: $summary"
  Write-Host "Package gate passed: $package"
  Write-Host "Installer gate passed: $installer"
  Write-Host "Source bundle gate passed: $sourceBundle"
  Write-Host "Checksums written: $checksumFile"
} finally { Pop-Location }
