name: Reusable Windows Build

on:
  workflow_call:

permissions:
  contents: read
  packages: read

jobs:
  build:
    name: Compile (${{ matrix.name }})
    strategy:
      fail-fast: false
      matrix:
        include:
          - name: CMake Release
            type: CMake
            artifact: windows-cmake-release
          - name: Solution Debug
            type: Solution
            configuration: Debug
            artifact: windows-solution-debug
          - name: Solution OpenGL
            type: Solution
            configuration: OpenGL
            artifact: windows-solution-opengl
          - name: Solution DirectX
            type: Solution
            configuration: DirectX
            artifact: windows-solution-directx
    runs-on: windows-2025
    env:
      VCPKG_BINARY_CACHE_ACCESS: ${{ secrets.VCPKG_PACKAGES_TOKEN != '' && ((github.event_name == 'push' && github.ref == 'refs/heads/main') || github.event_name == 'workflow_dispatch') && 'readwrite' || 'read' }}
      VCPKG_BINARY_SOURCES: "clear;nuget,https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json,${{ secrets.VCPKG_PACKAGES_TOKEN != '' && ((github.event_name == 'push' && github.ref == 'refs/heads/main') || github.event_name == 'workflow_dispatch') && 'readwrite' || 'read' }};nugettimeout,600"
      VCPKG_NUGET_REPOSITORY: https://github.com/${{ github.repository }}.git
      VCPKG_NUGET_API_KEY: ${{ secrets.VCPKG_PACKAGES_TOKEN != '' && ((github.event_name == 'push' && github.ref == 'refs/heads/main') || github.event_name == 'workflow_dispatch') && secrets.VCPKG_PACKAGES_TOKEN || github.token }}
      FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
      SCCACHE_DIR: ${{ github.workspace }}\.sccache
    steps:
      - name: Install VS 2026 Build Tools (v145 toolset)
        if: matrix.type == 'Solution'
        shell: pwsh
        run: |
          $acceptedExitCodes = @(0, 3010)
          for ($attempt = 1; $attempt -le 3; $attempt++) {
            choco install visualstudio2026-workload-vctools --yes --ignore-package-exit-codes=3010 --no-progress
            if ($acceptedExitCodes -contains $LASTEXITCODE) {
              exit 0
            }

            Write-Warning "Chocolatey install failed with exit code $LASTEXITCODE on attempt $attempt."
            if ($attempt -lt 3) {
              Start-Sleep -Seconds (30 * $attempt)
            }
          }

          Write-Warning "Chocolatey could not install the VS 2026 v145 workload. Continuing so the next step can use any runner-provided toolset."

      - name: Setup MSBuild.exe
        if: matrix.type == 'Solution'
        uses: microsoft/setup-msbuild@v3
        with:
          vs-prerelease: true
          vs-version: "latest"

      - name: Verify v145 platform toolset
        if: matrix.type == 'Solution'
        shell: pwsh
        run: |
          $programFilesX86 = [Environment]::GetFolderPath("ProgramFilesX86")
          $vswhere = Join-Path $programFilesX86 "Microsoft Visual Studio\Installer\vswhere.exe"
          if (-not (Test-Path $vswhere)) {
            throw "vswhere.exe not found"
          }

          $installPath = & $vswhere -latest -prerelease -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath
          if (-not $installPath) {
            throw "Visual Studio with VC tools was not found"
          }

          $vcMsbuildRoot = Join-Path $installPath "MSBuild\Microsoft\VC"
          $toolset = Get-ChildItem -Path $vcMsbuildRoot -Directory -Recurse -Filter v145 -ErrorAction SilentlyContinue |
            Where-Object { $_.FullName -match "\\PlatformToolsets\\v145$" } |
            Select-Object -First 1
          if (-not $toolset) {
            Get-ChildItem -Path $vcMsbuildRoot -Directory -Recurse -ErrorAction SilentlyContinue |
              Where-Object { $_.FullName -match "\\PlatformToolsets\\v\d+$" } |
              Sort-Object FullName |
              ForEach-Object { Write-Host "Found platform toolset: $($_.FullName)" }
            throw "v145 platform toolset was not found under $vcMsbuildRoot"
          }

          Write-Host "Using v145 platform toolset at $($toolset.FullName)"

      - name: Checkout repository
        uses: actions/checkout@v6

      - name: Export GitHub Actions cache environment variables
        uses: actions/github-script@v9
        with:
          script: |
            core.exportVariable('ACTIONS_CACHE_URL', process.env.ACTIONS_CACHE_URL || '');
            core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || '');

      - name: Get vcpkg baseline
        shell: pwsh
        run: |
          $json = Get-Content vcpkg.json -Raw | ConvertFrom-Json
          $vcpkgCommitId = $json.'builtin-baseline'
          "VCPKG_GIT_COMMIT_ID=$vcpkgCommitId" | Out-File -FilePath $env:GITHUB_ENV -Append

      - name: Remove Windows pre-installed MySQL
        if: matrix.type == 'CMake'
        shell: pwsh
        run: Remove-Item -Recurse -Force C:\mysql* -ErrorAction SilentlyContinue

      - name: Prepare sccache directory
        if: matrix.type == 'CMake'
        shell: pwsh
        run: New-Item -ItemType Directory -Force -Path $env:SCCACHE_DIR | Out-Null

      - name: CCache
        if: matrix.type == 'CMake'
        uses: hendrikmuhs/ccache-action@v1.2.23
        with:
          max-size: "1G"
          variant: "sccache"
          key: ccache-windows-release
          restore-keys: |
            ccache-windows

      - name: Setup NuGet source for GitHub Packages
        shell: pwsh
        env:
          NUGET_AUTH_TOKEN: ${{ env.VCPKG_NUGET_API_KEY }}
        run: |
          $feed = "https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json"
          $nuget = (Get-Command nuget.exe -ErrorAction SilentlyContinue).Source
          if (-not $nuget) {
            throw "nuget.exe not found in PATH"
          }

          & $nuget sources remove -Name "GitHubPackages" 2>&1 | Out-Null
          & $nuget sources add `
            -Name "GitHubPackages" `
            -Source $feed `
            -UserName "${{ github.repository_owner }}" `
            -Password "$env:NUGET_AUTH_TOKEN" `
            -StorePasswordInClearText

          & $nuget setapikey "$env:NUGET_AUTH_TOKEN" -Source $feed
          & $nuget sources list

      - name: Setup vcpkg
        uses: lukka/run-vcpkg@v11
        with:
          vcpkgDirectory: ${{ matrix.type == 'Solution' && format('{0}/vcpkg', github.workspace) || '' }}
          vcpkgGitURL: "https://github.com/microsoft/vcpkg.git"
          vcpkgGitCommitId: ${{ env.VCPKG_GIT_COMMIT_ID }}

      - name: Run CMake
        if: matrix.type == 'CMake'
        uses: lukka/run-cmake@v10
        with:
          configurePreset: windows-release
          buildPreset: windows-release
          configurePresetAdditionalArgs: "['-DTOGGLE_BIN_FOLDER=ON', '-DOPTIONS_ENABLE_IPO=OFF', '-DOTCLIENT_BUILD_TESTS=OFF']"

      - name: Upload artifacts (CMake)
        if: matrix.type == 'CMake'
        uses: actions/upload-artifact@v7
        with:
          name: ${{ matrix.artifact }}
          path: build/windows-release/bin/

      - name: Build project (MSBuild solution)
        if: matrix.type == 'Solution'
        shell: pwsh
        run: |
          $vcpkgRoot = Join-Path (Get-Location) "vcpkg"
          $outDir = Join-Path (Get-Location) "artifacts/${{ matrix.configuration }}"
          New-Item -ItemType Directory -Force -Path $outDir | Out-Null

          msbuild.exe vc18/otclient.sln `
            /m `
            /p:Configuration=${{ matrix.configuration }} `
            /p:Platform=x64 `
            /p:VcpkgEnableManifest=true `
            /p:VcpkgRoot="$vcpkgRoot" `
            /p:OutDir="$outDir\\" `
            /p:GITHUB_WORKSPACE="${{ github.workspace }}"

      - name: Verify vcpkg binary cache push
        if: matrix.type == 'CMake' && success() && env.VCPKG_BINARY_CACHE_ACCESS == 'readwrite'
        shell: pwsh
        run: |
          $logs = Get-ChildItem -Path . -Recurse -Filter vcpkg-manifest-install.log -ErrorAction SilentlyContinue
          if (-not $logs) {
            Write-Error "No vcpkg manifest logs found."
            exit 1
          }
          $pushed = $false
          foreach ($log in $logs) {
            if (Select-String -Path $log.FullName -Pattern "to [1-9][0-9]* binary cache\(s\)" -Quiet) {
              $pushed = $true
              break
            }
          }
          if (-not $pushed) {
            $zeroPush = $false
            foreach ($log in $logs) {
              if (Select-String -Path $log.FullName -Pattern "to 0 binary cache\(s\)" -Quiet) {
                $zeroPush = $true
                break
              }
            }
            if ($zeroPush) {
              Write-Error "Binary cache push reported 0 caches and no successful push was found."
              exit 1
            }
            Write-Host "No binary cache push summary found; assuming no package was built for upload."
          }

      - name: Upload artifacts (Solution)
        if: matrix.type == 'Solution'
        uses: actions/upload-artifact@v7
        with:
          name: ${{ matrix.artifact }}
          path: artifacts/${{ matrix.configuration }}/
