#Requires -Version 7.0
<#
.SYNOPSIS
  Orchestrates the FOCAS driver integration-test loop: bring up the
  focas-mock Docker container, run the managed wire-client integration
  tests, tear down Docker.

.DESCRIPTION
  The FOCAS integration fixture now needs just two things running
  together:
    1. A single focas-mock container listening on :8193 (one service,
       no per-series compose profile ceremony — the mock's native
       FOCAS Ethernet responder handles every call the managed driver
       issues).
    2. The integration-test assembly built. The managed
       `WireFocasClient` dials the mock directly; there is no shim
       DLL, no P/Invoke, no test-bin DLL copy step.
  This script handles both and cleans up on exit.

  Designed to run unattended on a build agent or on a developer box.
  Exit code matches the test suite (0 = all pass or skip-clean,
  non-zero when any integration test failed).

.PARAMETER Profile
  focas-mock profile name to seed at startup (e.g. `ThirtyOne_i`,
  `Sixteen_i`, `fwlib30i64`). Defaults to `ThirtyOne_i`. The fixture
  resolves aliases via `FocasCncSeries`, and tests that need per-series
  state can call `fixture.LoadProfileAsync` directly at test start to
  override the default.

.PARAMETER SkipDocker
  Skip docker up/down. Use when the mock is already running from
  another shell.

.PARAMETER Configuration
  Build configuration — Debug or Release. Default: Debug.

.PARAMETER KeepDocker
  Don't tear down the docker stack on exit. Useful for iterating on
  tests.
#>

param(
    [string]$Profile = "ThirtyOne_i",
    [switch]$SkipDocker,
    [ValidateSet("Debug", "Release")]
    [string]$Configuration = "Debug",
    [switch]$KeepDocker
)

Set-StrictMode -Version 3.0
$ErrorActionPreference = "Stop"

$repoRoot   = (Resolve-Path (Join-Path $PSScriptRoot "..\..")).Path
$integTests = Join-Path $repoRoot "tests\Drivers\ZB.MOM.WW.OtOpcUa.Driver.FOCAS.IntegrationTests"
$dockerYml  = Join-Path $integTests "Docker\docker-compose.yml"

function Write-Step { param([string]$Msg) Write-Host ""; Write-Host "=== $Msg ===" -ForegroundColor Cyan }
function Write-Info { param([string]$Msg) Write-Host "[INFO] $Msg" -ForegroundColor Gray }
function Write-Fail { param([string]$Msg) Write-Host "[FAIL] $Msg" -ForegroundColor Red }

$cleanupScripts = @()
trap {
    Write-Host ""
    Write-Fail "run-focas.ps1 crashed: $_"
    foreach ($c in $cleanupScripts) { try { & $c } catch { Write-Host "cleanup failed: $_" -ForegroundColor DarkYellow } }
    exit 2
}

Write-Step "Build FOCAS IntegrationTests ($Configuration)"
dotnet build (Join-Path $integTests "ZB.MOM.WW.OtOpcUa.Driver.FOCAS.IntegrationTests.csproj") `
    --configuration $Configuration --nologo --verbosity minimal
if ($LASTEXITCODE -ne 0) { throw "dotnet build failed (exit $LASTEXITCODE)" }

if (-not $SkipDocker) {
    Write-Step "docker compose up"
    if (-not (Get-Command docker -ErrorAction SilentlyContinue)) {
        Write-Fail "docker CLI not on PATH. Install Docker Desktop or pass -SkipDocker + run the mock externally."
        exit 4
    }

    docker compose -f $dockerYml up -d --build --wait 2>&1 | Write-Host
    if ($LASTEXITCODE -ne 0) { throw "docker compose up failed (exit $LASTEXITCODE)" }

    if (-not $KeepDocker) {
        $cleanupScripts += {
            Write-Step "docker compose down"
            docker compose -f $dockerYml down --remove-orphans 2>&1 | Write-Host
        }
    }

    Write-Info "probing localhost:8193..."
    $tcp = [System.Net.Sockets.TcpClient]::new()
    try {
        $ok = $tcp.ConnectAsync("127.0.0.1", 8193).Wait([TimeSpan]::FromSeconds(5))
        if (-not $ok -or -not $tcp.Connected) {
            throw "TCP probe to localhost:8193 failed after docker compose --wait succeeded"
        }
    }
    finally { $tcp.Dispose() }
    Write-Info "mock is accepting connections"
}
else {
    Write-Step "Docker (skipped)"
}

Write-Step "dotnet test (wire-backend integration)"
$env:OTOPCUA_FOCAS_SIM_PROFILE = $Profile

dotnet test (Join-Path $integTests "ZB.MOM.WW.OtOpcUa.Driver.FOCAS.IntegrationTests.csproj") `
    --configuration $Configuration --no-build --nologo --verbosity minimal
$testExit = $LASTEXITCODE

foreach ($c in $cleanupScripts) { & $c }

if ($testExit -ne 0) {
    Write-Fail "integration tests failed with exit $testExit"
    exit $testExit
}

Write-Host ""
Write-Host "run-focas.ps1 completed successfully." -ForegroundColor Green
exit 0
