# native process mode (called by start.ps1 when Docker is unavailable)
param(
    [switch]$Rebuild,
    [switch]$NoBrowser,
    [switch]$ShowConsole  # show service windows (debug); default: hidden
)

$ErrorActionPreference = "Stop"
$Root = $PSScriptRoot
Set-Location -LiteralPath $Root
$LogDir = Join-Path $Root ".runtime\logs"
New-Item -ItemType Directory -Force -Path $LogDir | Out-Null

# Always wipe previous native/docker leftovers before binding ports
Write-Host "==> Pre-clean before native start" -ForegroundColor DarkGray
& (Join-Path $Root "scripts\Stop-Stack.ps1") -Quiet
Start-Sleep -Seconds 1

Write-Host "==> Native mode: need Go / Python / Node / PostgreSQL" -ForegroundColor Yellow
if (-not $ShowConsole) {
    Write-Host "  services run hidden; logs -> .runtime\logs\" -ForegroundColor DarkGray
}

function Clear-Port([int]$port) {
    $conns = Get-NetTCPConnection -LocalPort $port -State Listen -ErrorAction SilentlyContinue
    foreach ($c in $conns) {
        $procId = $c.OwningProcess
        if ($procId -gt 0) {
            Write-Host "  free port $port (pid=$procId)"
            & taskkill.exe /F /T /PID $procId 2>$null | Out-Null
            Stop-Process -Id $procId -Force -ErrorAction SilentlyContinue
        }
    }
}

Write-Host "==> Clearing ports 8888/8001/8180/5173"
foreach ($p in 8888, 8001, 8180, 5173) { Clear-Port $p }
Start-Sleep -Seconds 1

function Reset-LogFile([string]$path) {
    try {
        if (Test-Path -LiteralPath $path) {
            # 句柄未释放时 Set-Content 会失败：先挪走旧文件
            $prev = "$path.prev"
            Remove-Item -LiteralPath $prev -Force -ErrorAction SilentlyContinue
            Move-Item -LiteralPath $path -Destination $prev -Force -ErrorAction Stop
        }
        Set-Content -LiteralPath $path -Value "" -Encoding UTF8
        return $path
    } catch {
        $alt = ($path -replace '\.log$', ".$(Get-Date -Format 'HHmmss').log")
        Set-Content -LiteralPath $alt -Value "" -Encoding UTF8
        return $alt
    }
}

function Start-Svc($name, $workDir, $filePath, $argumentList) {
    $outLog = Reset-LogFile (Join-Path $LogDir "$name.out.log")
    $errLog = Reset-LogFile (Join-Path $LogDir "$name.err.log")
    $pidFile = Join-Path $LogDir "$name.pid"

    if ($ShowConsole) {
        $argStr = ""
        if ($argumentList) {
            $parts = @()
            foreach ($a in $argumentList) {
                if ($a -match '\s') { $parts += ('"' + $a + '"') } else { $parts += $a }
            }
            $argStr = $parts -join ' '
        }
        $cmd = "Set-Location -LiteralPath '$workDir'; Write-Host '[$name]' -ForegroundColor Cyan; & '$filePath' $argStr"
        $p = Start-Process -FilePath "powershell.exe" -ArgumentList @(
            "-NoExit", "-NoProfile", "-ExecutionPolicy", "Bypass", "-Command", $cmd
        ) -WorkingDirectory $workDir -PassThru
    } else {
        $p = Start-Process -FilePath $filePath `
            -ArgumentList $argumentList `
            -WorkingDirectory $workDir `
            -WindowStyle Hidden `
            -RedirectStandardOutput $outLog `
            -RedirectStandardError $errLog `
            -PassThru
    }
    if ($p) { Set-Content -LiteralPath $pidFile -Value $p.Id -Encoding ASCII }
    Write-Host "  started $name (pid=$($p.Id))" -ForegroundColor DarkGray
}

$plat = Join-Path $Root "platform\platform.exe"
$gw = Join-Path $Root "gateway\gateway.exe"
# 默认重编译，避免改 Go 源码后 restart 仍跑旧 exe
$needPlat = $Rebuild -or -not (Test-Path $plat)
$needGw = $Rebuild -or -not (Test-Path $gw)
if (-not $needPlat -and (Test-Path $plat)) {
    $exeTime = (Get-Item $plat).LastWriteTime
    $newer = Get-ChildItem -Path (Join-Path $Root "platform") -Recurse -Include *.go -ErrorAction SilentlyContinue |
        Where-Object { $_.LastWriteTime -gt $exeTime } |
        Select-Object -First 1
    if ($newer) { $needPlat = $true }
}
if (-not $needGw -and (Test-Path $gw)) {
    $exeTime = (Get-Item $gw).LastWriteTime
    $newer = Get-ChildItem -Path (Join-Path $Root "gateway") -Recurse -Include *.go -ErrorAction SilentlyContinue |
        Where-Object { $_.LastWriteTime -gt $exeTime } |
        Select-Object -First 1
    if ($newer) { $needGw = $true }
}
if ($needPlat) {
    Write-Host "  building platform.exe ..." -ForegroundColor DarkGray
    Push-Location (Join-Path $Root "platform")
    go build -o platform.exe .
    Pop-Location
}
if ($needGw) {
    Write-Host "  building gateway.exe ..." -ForegroundColor DarkGray
    Push-Location (Join-Path $Root "gateway")
    go build -o gateway.exe .
    Pop-Location
}

Write-Host "==> Ensure web frontend (vite /#/preview)" -ForegroundColor DarkGray
& (Join-Path $Root "scripts\Ensure-Web.ps1")
# $? 判断 PS 脚本成败；勿单靠 $LASTEXITCODE（会残留 docker/compose 等 native 失败码）
if (-not $?) { throw "Ensure-Web failed" }

$pyCmd = Get-Command python -ErrorAction SilentlyContinue
if (-not $pyCmd) { $pyCmd = Get-Command py -ErrorAction SilentlyContinue }
if (-not $pyCmd) { throw "python not found" }
$py = $pyCmd.Source

$npmCmd = Get-Command npm.cmd -ErrorAction SilentlyContinue
if (-not $npmCmd) { $npmCmd = Get-Command npm -ErrorAction SilentlyContinue }
if (-not $npmCmd) { throw "npm not found" }

# AI 截图直达本机 Vite
$env:WEB_BASE = "http://127.0.0.1:5173"
$env:PLATFORM_BASE = "http://127.0.0.1:8888"
$env:GATEWAY_BASE = "http://127.0.0.1:8180"
$env:GENERATE_LOG_DIR = Join-Path $Root ".runtime\logs\generate"
$env:FIDELITY_SHOT_DIR = Join-Path $Root ".runtime\fidelity_shots"

Start-Svc "platform" (Join-Path $Root "platform") $plat @("-f", "etc/platform.yaml")
Start-Sleep -Seconds 2
Start-Svc "ai-service" (Join-Path $Root "ai-service") $py @("-m", "uvicorn", "app:app", "--host", "127.0.0.1", "--port", "8001", "--reload")
Start-Sleep -Seconds 1
Start-Svc "gateway" (Join-Path $Root "gateway") $gw @("-f", "etc/gateway.yaml")
Start-Sleep -Seconds 1
Start-Svc "web" (Join-Path $Root "web") $npmCmd.Source @("run", "dev", "--", "--host", "127.0.0.1", "--port", "5173", "--strictPort")

Write-Host "==> Waiting for services..."
$deadline = (Get-Date).AddSeconds(45)
do {
    $webOk = $false
    $gwOk = $false
    try {
        $r = Invoke-WebRequest -Uri "http://127.0.0.1:5173/" -UseBasicParsing -TimeoutSec 2
        if ($r.StatusCode -lt 500) { $webOk = $true }
    } catch {}
    try {
        $r = Invoke-WebRequest -Uri "http://127.0.0.1:8180/gateway/health" -UseBasicParsing -TimeoutSec 2
        if ($r.StatusCode -lt 500) { $gwOk = $true }
    } catch {}
    if ($webOk -and $gwOk) { break }
    Start-Sleep -Seconds 1
} while ((Get-Date) -lt $deadline)

if ($webOk -and $gwOk) {
    Write-Host "OK  Web http://127.0.0.1:5173  Gateway http://127.0.0.1:8180  account demo/demo123" -ForegroundColor Green
    Write-Host "    logs  $LogDir" -ForegroundColor DarkGray
} else {
    Write-Host "WARN  some services not ready yet. Check logs:" -ForegroundColor Yellow
    Write-Host "  $LogDir"
    Write-Host "  web=$webOk gateway=$gwOk"
    Write-Host "  (debug with visible windows: .\start-host.ps1 -ShowConsole)"
}

# 后台看门狗：ai-service / gateway 挂掉自动拉起
$watchPidFile = Join-Path $LogDir "watchdog.pid"
if (Test-Path $watchPidFile) {
    $oldWatch = Get-Content $watchPidFile -ErrorAction SilentlyContinue
    if ($oldWatch) { Stop-Process -Id ([int]$oldWatch) -Force -ErrorAction SilentlyContinue }
}
$watchScript = Join-Path $Root "watch-services.ps1"
$watchOut = Join-Path $LogDir "watchdog.out.log"
$watchErr = Join-Path $LogDir "watchdog.err.log"
Set-Content -LiteralPath $watchOut -Value "" -Encoding UTF8
Set-Content -LiteralPath $watchErr -Value "" -Encoding UTF8
$wp = Start-Process -FilePath "powershell.exe" `
    -ArgumentList @("-NoProfile", "-ExecutionPolicy", "Bypass", "-File", $watchScript) `
    -WorkingDirectory $Root `
    -WindowStyle Hidden `
    -RedirectStandardOutput $watchOut `
    -RedirectStandardError $watchErr `
    -PassThru
if ($wp) {
    Set-Content -LiteralPath $watchPidFile -Value $wp.Id -Encoding ASCII
    Write-Host "  started watchdog (pid=$($wp.Id)) - auto-restarts ai-service if down" -ForegroundColor DarkGray
}

if (-not $NoBrowser) { Start-Process "http://127.0.0.1:5173" }