name: build-windows

on:
  push:
    branches: [main, master]
  workflow_dispatch:
    inputs:
      version_suffix:
        description: "Version suffix (e.g. 'cst', 'beta1'). Empty = vanilla."
        type: string
        default: ""

env:
  RUST_VERSION: "1.75"
  LLVM_VERSION: "15.0.6"
  # bindgen (pulled in via scrap → libvpx-sys) reads LIBCLANG_PATH; the runner
  # provisioner installs LLVM here.
  LLVM_HOME: 'C:\tools\llvm-15.0.6'
  VCPKG_COMMIT_ID: "120deac3062162151622ca4860575a33844ba10b"

jobs:
  build-x64:
    name: build-hello-agent-x64
    runs-on: [self-hosted, windows-10]
    timeout-minutes: 90
    env:
      VCPKG_ROOT: C:\vcpkg
      VCPKG_BINARY_SOURCES: "clear;files,C:\\vcpkg-cache,readwrite"
      LIBCLANG_PATH: 'C:\tools\llvm-15.0.6\bin'
    steps:
      - name: Checkout hello-agent (with vendored rustdesk)
        uses: actions/checkout@v4
        # We vendor the rustdesk source under vendor/rustdesk/ so this
        # checkout is fully self-contained — no sibling repo, no submodules.

      - name: Verify host toolchain
        shell: pwsh
        run: |
          $required = 'pwsh','git','bash','python','rustc','cargo','rustup','clang'
          $missing = @()
          foreach ($tool in $required) {
            $cmd = Get-Command $tool -ErrorAction SilentlyContinue
            if (-not $cmd) { $missing += $tool; continue }
            $ver = & $tool --version 2>&1 | Select-Object -First 1
            Write-Host ("{0,-10} {1}  ({2})" -f $tool, $cmd.Source, $ver)
          }
          if ($missing.Count -gt 0) {
            Write-Error ("Missing tools on runner: {0}" -f ($missing -join ', '))
            exit 1
          }
          if (-not $env:VCPKG_ROOT -or -not (Test-Path "$env:VCPKG_ROOT\vcpkg.exe")) {
            Write-Error "VCPKG_ROOT not set or vcpkg.exe missing at $env:VCPKG_ROOT"
            exit 1
          }
          if (-not (Test-Path "$env:LIBCLANG_PATH\libclang.dll")) {
            Write-Error "libclang.dll not found at $env:LIBCLANG_PATH"
            exit 1
          }

      - name: Configure Rust toolchain
        shell: pwsh
        run: |
          rustup toolchain install $env:RUST_VERSION --profile minimal --component rustfmt
          if ($LASTEXITCODE -ne 0) { throw "rustup toolchain install failed ($LASTEXITCODE)" }
          rustup default $env:RUST_VERSION
          if ($LASTEXITCODE -ne 0) { throw "rustup default failed ($LASTEXITCODE)" }
          rustup target add x86_64-pc-windows-msvc
          rustc --version
          cargo --version

      - name: Configure git safe.directory
        shell: pwsh
        run: git config --global --add safe.directory '*'

      - name: vcpkg install dependencies (x64-windows-static)
        shell: bash
        env:
          VCPKG_DEFAULT_HOST_TRIPLET: x64-windows-static
        # vcpkg.json sits at vendor/rustdesk/vcpkg.json (alongside the
        # rustdesk Cargo.toml). Run from there so manifest mode picks it up.
        run: |
          mkdir -p /c/vcpkg-cache
          cd vendor/rustdesk
          if ! "$VCPKG_ROOT/vcpkg" install \
              --triplet x64-windows-static \
              --x-install-root="$VCPKG_ROOT/installed"; then
            find "$VCPKG_ROOT/" -name "*.log" -exec sh -c 'echo "===== {} ====="; cat "{}"' \;
            exit 1
          fi

      # Build hello-agent. We do NOT pre-build vendor/rustdesk/libs/virtual_display/dylib
      # the way the upstream rustdesk workflow does. That dylib produces a
      # standalone `dylib_virtual_display.dll` runtime artifact that the
      # rustdesk Flutter exe ships side-by-side; hello-agent doesn't bundle
      # it (no virtual-display feature in v0), and the `virtual_display`
      # crate that librustdesk *does* link against has no compile-time dep
      # on the dylib — it loads it by name at runtime if present.
      #
      # Pre-building it would also force a second cargo invocation inside
      # the vendor/rustdesk/ workspace, which has no Cargo.lock of its own
      # and would re-resolve git deps from HEAD (breaking the tray-icon
      # 0.21.3 pin we keep at the hello-agent root).
      - name: Cargo build hello-agent
        shell: pwsh
        run: |
          cargo build --release --bin hello-agent --locked
          if ($LASTEXITCODE -ne 0) { throw "hello-agent build failed" }
          if (-not (Test-Path target\release\hello-agent.exe)) {
            throw "target\release\hello-agent.exe missing after cargo build"
          }

      - name: Compute version suffix and stage artifact
        shell: pwsh
        run: |
          $suffix = "${env:VERSION_SUFFIX}"
          if ($suffix) { $tag = "0.1.0-$suffix" } else { $tag = "0.1.0" }
          New-Item -ItemType Directory -Force -Path .\SignOutput | Out-Null
          Copy-Item -Force `
            target\release\hello-agent.exe `
            ".\SignOutput\hello-agent-$tag-x86_64.exe"
          Write-Host "staged: SignOutput\hello-agent-$tag-x86_64.exe"
        env:
          VERSION_SUFFIX: ${{ inputs.version_suffix }}

      - name: Report signing status of build artifacts
        shell: pwsh
        run: |
          $artifacts = Get-ChildItem .\SignOutput -Include *.exe -File
          if (-not $artifacts) {
            Write-Warning "No artifacts found in SignOutput\"
            return
          }
          $unsigned = @()
          foreach ($f in $artifacts) {
            $sig = Get-AuthenticodeSignature -FilePath $f.FullName
            $size = '{0,8:N0}' -f $f.Length
            switch ($sig.Status) {
              'Valid' {
                Write-Host ("[ SIGNED ] {0}  ({1} bytes) signed by: {2}" -f $f.Name, $size, $sig.SignerCertificate.Subject)
              }
              'NotSigned' {
                Write-Host ("[UNSIGNED] {0}  ({1} bytes)" -f $f.Name, $size)
                $unsigned += $f.Name
              }
              default {
                Write-Host ("[ {0,-7} ] {1}  ({2} bytes) -- {3}" -f $sig.Status, $f.Name, $size, $sig.StatusMessage)
                $unsigned += $f.Name
              }
            }
          }
          if ($unsigned.Count -gt 0) {
            $list = $unsigned -join ', '
            Write-Host "::warning title=Unsigned artifacts::$list -- SmartScreen will warn end users. Wire up signing before distributing."
          }

      - name: Upload artifacts
        uses: actions/upload-artifact@v3
        with:
          name: hello-agent-windows-x64-${{ github.sha }}
          path: SignOutput/hello-agent-*.exe
          if-no-files-found: error
          retention-days: 14
