# Build the punktfunk Windows client as signed MSIX packages (x64 + ARM64) and publish them to
# Gitea's generic package registry, so Windows boxes can download + install a real package (Start
# tile, clean install/uninstall) instead of a loose exe. Runs on the self-hosted Windows runner
# (host mode; scripts/ci/setup-windows-runner.ps1) — the MSVC/WinUI/FFmpeg toolchain + the Windows
# SDK's makeappx/signtool are baked into the runner's daemon env, same as windows.yml.
#
# Both arches come off the ONE x64 runner: x86_64 natively, aarch64 cross-compiled (the x64 MSVC
# toolset has the ARM64 cross compiler; the matrix points FFMPEG_DIR at the ARM64 FFmpeg tree). See
# windows.yml for the cross-build rationale + the BOM/MAX_PATH runner gotchas.
#
# Registry (public, unom org): https://git.unom.io/unom/-/packages  (generic group)
# Packaging internals: clients/windows/packaging/README.md.
#
# Versioning — single project version; MSIX requires a strictly 4-part numeric version, so:
#   vX.Y.Z tag -> X.Y.Z.0  (THE release; any -rc/+meta pre-release suffix is dropped for MSIX).
#                Published to the generic registry + the stable `latest/` alias + attached to the
#                unified Gitea Release alongside every other platform's artifact.
#   main push / dispatch -> 0.3.<run_number>.0  (canary; climbs monotonically by run number).
#                Published to the generic registry + the `canary/` alias.
# Both arches share the version; artifacts are arch-suffixed (..._x64.msix / ..._arm64.msix).
#
# Signing (packaging/pack-msix.ps1): if the MSIX_CERT_PFX_B64 / MSIX_CERT_PASSWORD Actions secrets
# are set (a real or shared code-signing .pfx whose subject DN == Publisher), the package is signed
# with them. Otherwise an ephemeral self-signed cert is generated and its public .cer is published
# next to the .msix (users import it to Trusted People before install). Drop in a real cert later
# with no workflow change — just add the secrets (+ pass -Publisher if its subject differs).
name: windows-msix

on:
  push:
    branches: [main]
    paths:
      - 'clients/windows/**'
      - 'crates/punktfunk-core/**'
      - 'Cargo.lock'
      - 'Cargo.toml'
      - '.gitea/workflows/windows-msix.yml'
    tags: ['v*']
  workflow_dispatch:

env:
  REGISTRY: git.unom.io
  OWNER: unom
  PKG: punktfunk-client-windows

jobs:
  package:
    runs-on: windows-amd64
    timeout-minutes: 90
    strategy:
      fail-fast: false
      matrix:
        include:
          - arch: x64
            target: x86_64-pc-windows-msvc
            ffmpeg: C:\Users\Public\ffmpeg
            td: C:\t
          - arch: arm64
            target: aarch64-pc-windows-msvc
            ffmpeg: C:\Users\Public\ffmpeg-arm64
            td: C:\t-a64
    steps:
      - uses: actions/checkout@v4

      - name: Configure + version
        shell: pwsh
        run: |
          # windows-reactor's build.rs unwraps CARGO_WORKSPACE_DIR; CARGO_TARGET_DIR (per-arch, short)
          # dodges the MAX_PATH wall in the CMake-from-source crates (see windows.yml). FFMPEG_DIR
          # selects the arch's import libs + is read by pack-msix.ps1 for the runtime DLLs. All via
          # GITHUB_ENV.
          "CARGO_WORKSPACE_DIR=$env:GITHUB_WORKSPACE" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8
          "CARGO_TARGET_DIR=${{ matrix.td }}" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8
          "FFMPEG_DIR=${{ matrix.ffmpeg }}" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8
          rustup target add ${{ matrix.target }}
          $parts = if ($env:GITHUB_REF -like 'refs/tags/v*') {
            # MSIX needs a purely-numeric 4-part version: drop any -rc/+meta pre-release suffix.
            (($env:GITHUB_REF_NAME -replace '^v', '') -replace '[-+].*$', '').Split('.')
          } else {
            @('0', '3', $env:GITHUB_RUN_NUMBER)
          }
          while ($parts.Count -lt 4) { $parts += '0' }
          $v = ($parts[0..3] -join '.')
          "MSIX_VERSION=$v" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8
          Write-Output "MSIX version $v  arch ${{ matrix.arch }}  target ${{ matrix.target }}"

      - name: Build (release)
        shell: pwsh
        run: cargo build --release -p punktfunk-client-windows --target ${{ matrix.target }}

      - name: Pack + sign MSIX
        shell: pwsh
        env:
          MSIX_CERT_PFX_B64: ${{ secrets.MSIX_CERT_PFX_B64 }}
          MSIX_CERT_PASSWORD: ${{ secrets.MSIX_CERT_PASSWORD }}
        run: |
          & clients/windows/packaging/pack-msix.ps1 `
            -Version $env:MSIX_VERSION -Arch ${{ matrix.arch }} `
            -TargetDir ${{ matrix.td }}\${{ matrix.target }}\release -OutDir ${{ matrix.td }}\msix

      - name: Publish to Gitea generic registry
        shell: pwsh
        env:
          REGISTRY_TOKEN: ${{ secrets.REGISTRY_TOKEN }}
        run: |
          $PSNativeCommandUseErrorActionPreference = $false
          $base = "https://$($env:REGISTRY)/api/packages/$($env:OWNER)/generic/$($env:PKG)"
          # stable release -> `latest/` alias; canary main build -> `canary/` alias.
          $alias = if ($env:GITHUB_REF -like 'refs/tags/v*') { 'latest' } else { 'canary' }
          # version-less, arch-suffixed alias names so each channel keeps one predictable URL.
          $aliasNames = @{
            "$($env:MSIX_PATH)"     = "$($env:PKG)_${{ matrix.arch }}.msix"
            "$($env:MSIX_CER_PATH)" = "$($env:PKG)_${{ matrix.arch }}.cer"
          }
          $files = @($env:MSIX_PATH, $env:MSIX_CER_PATH) | Where-Object { $_ -and (Test-Path $_) }
          if (-not $files) { throw "pack produced no artifacts to publish" }
          function Put($f, $url) {
            curl.exe -fsS --user "enricobuehler:$($env:REGISTRY_TOKEN)" --upload-file "$f" "$url"
            if ($LASTEXITCODE -ne 0) { throw "upload failed ($LASTEXITCODE): $url" }
            Write-Output "published $url"
          }
          foreach ($f in $files) {
            $name = Split-Path $f -Leaf
            # 1) immutable, versioned path
            Put $f "$base/$($env:MSIX_VERSION)/$name"
            # 2) channel alias (delete-then-reupload; the generic registry 409s on an existing file)
            $an = $aliasNames["$f"]
            curl.exe -fsS -o NUL --user "enricobuehler:$($env:REGISTRY_TOKEN)" -X DELETE "$base/$alias/$an" 2>$null
            Put $f "$base/$alias/$an"
          }

      # On a real release, also attach the MSIX (+ its .cer) to the unified Gitea Release. Both
      # arch legs attach to the same release concurrently — the helper's create-or-fetch handles
      # the race, and x64/arm64 filenames differ so the assets don't collide.
      - name: Attach MSIX to the Gitea release (stable tags only)
        if: startsWith(gitea.ref, 'refs/tags/v')
        shell: pwsh
        env:
          GITEA_TOKEN: ${{ secrets.REGISTRY_TOKEN }}
        run: |
          . scripts/ci/gitea-release.ps1
          $rid = Ensure-GiteaRelease -Tag $env:GITHUB_REF_NAME -Name $env:GITHUB_REF_NAME -Prerelease 'auto'
          foreach ($f in @($env:MSIX_PATH, $env:MSIX_CER_PATH)) {
            if ($f -and (Test-Path $f)) { Upsert-GiteaAsset -ReleaseId $rid -File $f }
          }
