# Author:: Lance Albertson <lance@osuosl.org>
# Copyright:: Copyright 2024-2026, Cinc Project
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# Test-stage helper for the self-hosted windows-2016 runner.
#
# The runner is shared with the build jobs, which depend on the
# operator-installed toolchain at C:\cinc-project\omnibus-toolchain.
# To validate a freshly-built MSI without destroying that install, we
# rename it aside before installing the test MSI, then uninstall the
# test MSI and restore the operator files on cleanup.
#
# Note: this restores the operator toolchain's FILES, not its MSI
# registration. The toolchain is functional from files alone; the
# operator's periodic re-install re-registers it (see
# CINC_MAINTENANCE_PLAN.md).
#
# Usage:
#   test-toolchain.ps1 install   # before_script
#   test-toolchain.ps1 run       # script
#   test-toolchain.ps1 cleanup   # after_script

param([Parameter(Mandatory = $true)][string]$Stage)

$installDir = "C:\cinc-project\omnibus-toolchain"
$asideDir = "C:\cinc-project\omnibus-toolchain.test"
$profilePath = "test/integration/cinc-tests"

function Resolve-Msi {
  (Get-ChildItem "data\windows\$env:PLATFORM_VER\omnibus-toolchain*.msi" -ErrorAction SilentlyContinue).FullName
}

switch ($Stage) {
  "install" {
    $ErrorActionPreference = "Stop"

    # Recover the operator toolchain from a cancelled prior test run.
    if (Test-Path $asideDir) {
      Remove-Item -Recurse -Force $installDir -ErrorAction SilentlyContinue
      Move-Item $asideDir $installDir
    }

    # Rename the operator install aside so the test MSI cannot clobber it.
    if (Test-Path $installDir) {
      Move-Item $installDir $asideDir
    }

    $msi = Resolve-Msi
    if (-not $msi) { throw "No MSI found under data\windows\$env:PLATFORM_VER" }
    Write-Host "Installing $msi to $installDir ..."
    # -PassThru so we can read .ExitCode; /l*v writes a verbose MSI log
    # next to the workspace so install failures under /qn can be
    # diagnosed instead of failing silently.
    $log = Join-Path (Get-Location) "msiexec-install.log"
    $proc = Start-Process msiexec -Wait -PassThru `
      -ArgumentList "/qn", "/i", "$msi", "/l*v", "$log"

    function Dump-InstallDiagnostics {
      Write-Host "===== msiexec-install.log (last 200 lines) ====="
      if (Test-Path $log) { Get-Content $log -Tail 200 } else { Write-Host "(no log written)" }
      Write-Host "===== install dir contents ====="
      if (Test-Path $installDir) { Get-ChildItem $installDir -Recurse -Depth 2 -ErrorAction SilentlyContinue } else { Write-Host "($installDir does not exist)" }
      Write-Host "===== end diagnostics ====="
    }

    if ($proc.ExitCode -ne 0) {
      Dump-InstallDiagnostics
      throw "msiexec /i $msi exited $($proc.ExitCode)."
    }
    if (-not (Test-Path "$installDir\embedded\bin\cinc-auditor.bat")) {
      Dump-InstallDiagnostics
      throw "msiexec /i reported success but $installDir\embedded\bin\cinc-auditor.bat is missing."
    }
    Write-Host "Installed $installDir"
  }

  "run" {
    $ErrorActionPreference = "Stop"
    & "$installDir\embedded\bin\cinc-auditor.bat" exec $profilePath `
      --no-distinct-exit --reporter cli junit:junit.xml
    # cinc-auditor.bat is a native command; PowerShell does not turn a
    # non-zero exit into a script failure on its own. Propagate it so a
    # tool error fails the job (test failures still exit 0 thanks to
    # --no-distinct-exit, matching the shell script's behavior).
    exit $LASTEXITCODE
  }

  "cleanup" {
    # Runs from after_script: tolerate prior-step failure, never throw.
    $ErrorActionPreference = "Continue"

    $msi = Resolve-Msi
    if ($msi) { Start-Process msiexec -Wait -ArgumentList "/qn", "/x", "$msi" }

    Remove-Item -Recurse -Force $installDir -ErrorAction SilentlyContinue
    if (Test-Path $asideDir) { Move-Item $asideDir $installDir }
  }

  default {
    Write-Error "Usage: test-toolchain.ps1 {install|run|cleanup}"
    exit 1
  }
}
