param(
    [string]$DockerHost = "ssh://docker-gpu",
    [string]$SshTarget = "docker-gpu",
    [string]$Report = "reports/model-chat/preflight.json",
    [switch]$SkipDockerConfig,
    [switch]$CheckLive
)

$ErrorActionPreference = "Stop"

$root = Split-Path -Parent (Split-Path -Parent $MyInvocation.MyCommand.Path)
$reportPath = Join-Path $root $Report
$steps = @()

function Invoke-ExternalStep {
    param(
        [Parameter(Mandatory = $true)][string]$Name,
        [Parameter(Mandatory = $true)][string]$Command,
        [string[]]$Arguments = @()
    )

    Write-Host ""
    Write-Host "== $Name"
    $started = Get-Date
    $output = @(& $Command @Arguments 2>&1 | ForEach-Object { "$_" })
    $exitCode = if ($null -ne $global:LASTEXITCODE) { $global:LASTEXITCODE } else { 0 }
    $status = if ($exitCode -eq 0) { "ok" } else { "failed" }
    foreach ($line in $output) {
        Write-Host $line
    }
    [pscustomobject]@{
        name = $Name
        status = $status
        exit_code = $exitCode
        duration_ms = [int]((Get-Date) - $started).TotalMilliseconds
        command = @($Command) + $Arguments
        output = $output
    }
}

function Invoke-HttpStep {
    param(
        [Parameter(Mandatory = $true)][string]$Name,
        [Parameter(Mandatory = $true)][string]$Url
    )

    Write-Host ""
    Write-Host "== $Name"
    $started = Get-Date
    try {
        $response = Invoke-RestMethod -Uri $Url -TimeoutSec 20
        Write-Host "ok: $Url"
        [pscustomobject]@{
            name = $Name
            status = "ok"
            exit_code = 0
            duration_ms = [int]((Get-Date) - $started).TotalMilliseconds
            url = $Url
            summary = $response.status
        }
    } catch {
        Write-Host "failed: $Url"
        Write-Host $_.Exception.Message
        [pscustomobject]@{
            name = $Name
            status = "failed"
            exit_code = 1
            duration_ms = [int]((Get-Date) - $started).TotalMilliseconds
            url = $Url
            error = $_.Exception.Message
        }
    }
}

Push-Location $root
try {
    $steps += Invoke-ExternalStep -Name "GPU profiles" -Command "python" -Arguments @("scripts\validate_gpu_profiles.py", "--print")
    $steps += Invoke-ExternalStep -Name "PowerShell syntax" -Command "python" -Arguments @(
        "scripts\check_powershell_scripts.py",
        "scripts\deploy_model_chat_ui.ps1",
        "scripts\switch_gpu_profile.ps1",
        "scripts\manage_model_service.ps1"
    )
    $steps += Invoke-ExternalStep -Name "UI archive" -Command "powershell" -Arguments @(
        "-NoProfile",
        "-ExecutionPolicy",
        "Bypass",
        "-File",
        "scripts\deploy_model_chat_ui.ps1",
        "-DockerHost",
        $DockerHost,
        "-SshTarget",
        $SshTarget,
        "-ArchiveOnly"
    )
    if (-not $SkipDockerConfig) {
        $steps += Invoke-ExternalStep -Name "Compose config" -Command "powershell" -Arguments @(
            "-NoProfile",
            "-ExecutionPolicy",
            "Bypass",
            "-File",
            "scripts\deploy_model_chat_ui.ps1",
            "-DockerHost",
            $DockerHost,
            "-SshTarget",
            $SshTarget,
            "-ConfigOnly"
        )
    }
    if ($CheckLive) {
        $steps += Invoke-HttpStep -Name "Live health" -Url "http://192.168.220.91:8765/api/health"
        $steps += Invoke-HttpStep -Name "Live catalog" -Url "http://192.168.220.91:8765/api/catalog"
    }
} finally {
    Pop-Location
}

$failed = @($steps | Where-Object { $_.status -ne "ok" })
$reportObject = [pscustomobject]@{
    created_at = (Get-Date).ToUniversalTime().ToString("o")
    status = if ($failed.Count) { "failed" } else { "ok" }
    docker_host = $DockerHost
    ssh_target = $SshTarget
    steps = $steps
}

New-Item -ItemType Directory -Force (Split-Path -Parent $reportPath) | Out-Null
$reportObject | ConvertTo-Json -Depth 8 | Set-Content -LiteralPath $reportPath -Encoding UTF8

Write-Host ""
Write-Host "Model Chat UI preflight: $($reportObject.status)"
Write-Host "Report: $reportPath"

if ($failed.Count) {
    exit 1
}
