param(
    [Parameter(Position = 0)]
    [string]$Action = "help"
)

$ErrorActionPreference = "Stop"

$scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
$rootDir = (Resolve-Path (Join-Path $scriptDir "..")).Path
$exePath = Join-Path $rootDir "safesightd.exe"
$configPath = Join-Path $rootDir "safesightd.json"
$logPath = Join-Path $rootDir "safesightd.local.log"
$errLogPath = Join-Path $rootDir "safesightd.local.err.log"

function Write-Info {
    param([string]$Message)
    Write-Host "[safesightd] $Message"
}

function Get-SafesightdProcess {
    return Get-Process -Name "safesightd" -ErrorAction SilentlyContinue | Select-Object -First 1
}

function Get-HealthInfo {
    $listen = "127.0.0.1:18080"
    if (Test-Path $configPath) {
        $cfg = Get-Content -Raw $configPath | ConvertFrom-Json
        if ($cfg.listen -and -not [string]::IsNullOrWhiteSpace([string]$cfg.listen)) {
            $listen = [string]$cfg.listen
        }
    }

    $parts = $listen.Split(":")
    $hostName = $parts[0]
    $port = $parts[-1]
    if ([string]::IsNullOrWhiteSpace($hostName) -or $hostName -in @("0.0.0.0", "::")) {
        $hostName = "127.0.0.1"
    }

    $url = "http://{0}:{1}/health" -f $hostName, $port
    try {
        $resp = Invoke-WebRequest -UseBasicParsing $url -TimeoutSec 3
        if ($resp.StatusCode -eq 200 -and $resp.Content -match "ok") {
            return [pscustomobject]@{ State = "ok"; Url = $url }
        }
        return [pscustomobject]@{ State = "bad"; Url = $url }
    } catch {
        return [pscustomobject]@{ State = "down"; Url = $url }
    }
}

function Wait-ForHealthOk {
    param([int]$Retries = 8)
    for ($i = 0; $i -lt $Retries; $i++) {
        $health = Get-HealthInfo
        if ($health.State -eq "ok") {
            return $true
        }
        Start-Sleep -Seconds 1
    }
    return $false
}

function Wait-ForStop {
    param([int]$Retries = 8)
    for ($i = 0; $i -lt $Retries; $i++) {
        if (-not (Get-SafesightdProcess)) {
            return $true
        }
        Start-Sleep -Seconds 1
    }
    return $false
}

function Show-Health {
    $health = Get-HealthInfo
    switch ($health.State) {
        "ok" { Write-Info ("健康检查: ok ({0})" -f $health.Url) }
        "bad" { Write-Info ("健康检查: 响应异常 ({0})" -f $health.Url) }
        default { Write-Info ("健康检查: down ({0})" -f $health.Url) }
    }
}

function Invoke-Build {
    Write-Info "编译 safesightd.exe ..."
    Push-Location $rootDir
    try {
        & go build -o $exePath .\cmd\managerd
        if ($LASTEXITCODE -ne 0) {
            throw "go build failed with exit code $LASTEXITCODE"
        }
    } finally {
        Pop-Location
    }
    Write-Info "编译完成: $exePath"
}

function Invoke-Start {
    if (-not (Test-Path $exePath)) {
        throw "未找到 safesightd.exe，请先执行 build"
    }

    $proc = Get-SafesightdProcess
    if ($proc) {
        Write-Info ("已在运行，PID={0}" -f $proc.Id)
        Show-Health
        return
    }

    Write-Info "启动 safesightd.exe ..."
    Start-Process -FilePath $exePath `
        -ArgumentList $configPath `
        -WorkingDirectory $rootDir `
        -RedirectStandardOutput $logPath `
        -RedirectStandardError $errLogPath `
        -WindowStyle Hidden

    $null = Wait-ForHealthOk
    $proc = Get-SafesightdProcess
    if (-not $proc) {
        throw "进程未启动成功"
    }

    Write-Info ("已启动，PID={0}" -f $proc.Id)
    Show-Health
}

function Invoke-Stop {
    $proc = Get-SafesightdProcess
    if (-not $proc) {
        Write-Info "当前未运行"
        return
    }

    Write-Info ("停止 safesightd.exe，PID={0} ..." -f $proc.Id)
    Stop-Process -Id $proc.Id -Force
    if (-not (Wait-ForStop)) {
        throw "进程停止超时"
    }
    Write-Info "已停止"
}

function Invoke-Restart {
    Invoke-Stop
    Invoke-Start
}

function Show-Status {
    $proc = Get-SafesightdProcess
    if ($proc) {
        Write-Info ("进程状态: running (PID={0})" -f $proc.Id)
    } else {
        Write-Info "进程状态: stopped"
    }
    Show-Health
}

function Show-Usage {
    @(
        "用法:"
        "  managerd.bat build"
        "  managerd.bat start"
        "  managerd.bat stop"
        "  managerd.bat restart"
        "  managerd.bat status"
        "  managerd.bat help"
        ""
        "说明:"
        "  build   编译 .\cmd\managerd 到 safesightd.exe"
        "  start   启动现有 safesightd.exe，并做健康检查"
        "  stop    停止当前仓库对应的 safesightd.exe"
        "  restart 先 stop 再 start"
        "  status  查看进程状态与 /health"
        "  help    显示帮助"
    ) | ForEach-Object { Write-Host $_ }
}

try {
    switch ($Action.ToLowerInvariant()) {
        "build" { Invoke-Build }
        "start" { Invoke-Start }
        "stop" { Invoke-Stop }
        "restart" { Invoke-Restart }
        "status" { Show-Status }
        "help" { Show-Usage }
        default {
            Write-Host "未知动作: $Action"
            Show-Usage
            exit 1
        }
    }
} catch {
    Write-Error $_
    exit 1
}
