name: Windows Build Test

on:
  workflow_dispatch:
    inputs:
      version:
        description: "Version for SignPath parameter (e.g., 1.0.0-test.1)"
        required: false
        default: "dev"

permissions:
  contents: read
  actions: read

jobs:
  windows-build-sign:
    runs-on: windows-latest

    steps:
      - name: Checkout code
        uses: actions/checkout@v6
        with:
          fetch-depth: 0

      - name: Setup pnpm
        uses: pnpm/action-setup@v4

      - name: Setup Node.js
        uses: actions/setup-node@v6
        with:
          node-version: "24"
          cache: "pnpm"

      - name: Prefer HTTPS for public GitHub git dependencies
        run: |
          git config --global "url.https://github.com/.insteadOf" "git@github.com:"
          git config --global --add "url.https://github.com/.insteadOf" "ssh://git@github.com/"

      - name: Install dependencies
        run: pnpm install

      - name: Download uv binaries for Windows
        run: pnpm run uv:download:win

      - name: Build Windows
        run: pnpm run package:win

      - name: Validate unsigned Windows artifacts before SignPath
        shell: pwsh
        run: |
          $unsignedExeFiles = Get-ChildItem -Path "release" -Filter *.exe -File
          if (-not $unsignedExeFiles) {
            throw "No unsigned .exe files found in release/ before SignPath upload"
          }
          $unsignedCount = $unsignedExeFiles.Count
          "UNSIGNED_EXE_COUNT=$unsignedCount" | Out-File -FilePath $env:GITHUB_ENV -Append
          Write-Host "Found $unsignedCount unsigned .exe file(s):"
          $unsignedExeFiles | ForEach-Object { Write-Host " - $($_.Name)" }

      # Required by SignPath Trusted Build: artifact must exist on GitHub first.
      - name: Upload unsigned Windows artifacts for SignPath
        id: upload-unsigned-windows-artifact
        uses: actions/upload-artifact@v4
        with:
          name: unsigned-win-exe-${{ github.run_id }}-${{ github.run_attempt }}
          path: release/*.exe
          retention-days: 1

      - name: Sign Windows artifacts via SignPath
        id: signpath-sign-windows
        uses: signpath/github-action-submit-signing-request@v2
        with:
          api-token: ${{ secrets.SIGNPATH_API_TOKEN }}
          organization-id: "78e37079-23df-4800-b41c-33312ad7c1e3"
          project-slug: "ValueCell"
          signing-policy-slug: "ValueCell-sign"
          github-artifact-id: ${{ steps.upload-unsigned-windows-artifact.outputs.artifact-id }}
          wait-for-completion: true
          output-artifact-directory: release/signed

      - name: Replace unsigned executables with signed ones
        shell: pwsh
        run: |
          Write-Host "SignPath GitHub artifact ID: ${{ steps.upload-unsigned-windows-artifact.outputs.artifact-id }}"
          $signedExeFiles = Get-ChildItem -Path "release/signed" -Filter *.exe -File -Recurse
          if (-not $signedExeFiles) {
            throw "No signed .exe files found in release/signed"
          }
          $signedCount = $signedExeFiles.Count
          if ($env:UNSIGNED_EXE_COUNT -and ($signedCount -ne [int]$env:UNSIGNED_EXE_COUNT)) {
            throw "Signed .exe count ($signedCount) does not match unsigned count ($env:UNSIGNED_EXE_COUNT)"
          }
          foreach ($file in $signedExeFiles) {
            Copy-Item -Path $file.FullName -Destination "release/$($file.Name)" -Force
          }
          $finalExeFiles = Get-ChildItem -Path "release" -Filter *.exe -File
          if ($env:UNSIGNED_EXE_COUNT -and ($finalExeFiles.Count -ne [int]$env:UNSIGNED_EXE_COUNT)) {
            throw "Final release .exe count ($($finalExeFiles.Count)) does not match unsigned count ($env:UNSIGNED_EXE_COUNT)"
          }
          Write-Host "Signed executables copied to release/ ($($finalExeFiles.Count) file(s))"

      - name: Upload signed Windows artifacts
        uses: actions/upload-artifact@v4
        with:
          name: signed-win-exe-${{ github.run_id }}-${{ github.run_attempt }}
          path: |
            release/*.exe
            release/latest*.yml
          retention-days: 7