# aijianzhan one-click start (Docker Compose by default; auto-starts Docker Desktop)
param(
    [switch]$Rebuild,
    [switch]$UseHost,
    [switch]$NoBrowser,
    [switch]$ShowConsole,  # native mode only: show service console windows
    [int]$DockerWaitSec = 120
)

$ErrorActionPreference = "Stop"
$Root = $PSScriptRoot
Set-Location -LiteralPath $Root

function Write-Step([string]$msg) { Write-Host ""; Write-Host "==> $msg" -ForegroundColor Cyan }
function Write-Ok([string]$msg) { Write-Host "  OK  $msg" -ForegroundColor Green }
function Write-Warn([string]$msg) { Write-Host "  !!  $msg" -ForegroundColor Yellow }

function Test-DockerCli {
    try {
        $null = Get-Command docker -ErrorAction Stop
        return $true
    } catch {
        return $false
    }
}

function Test-DockerReady {
    if (-not (Test-DockerCli)) { return $false }
    try {
        $old = $ErrorActionPreference
        $ErrorActionPreference = "Continue"
        $null = & docker info 2>&1
        $ok = ($LASTEXITCODE -eq 0)
        $ErrorActionPreference = $old
        return $ok
    } catch {
        return $false
    }
}

function Get-DockerDesktopPath {
    $pf86 = [Environment]::GetEnvironmentVariable("ProgramFiles(x86)")
    $candidates = @(
        (Join-Path $env:ProgramFiles "Docker\Docker\Docker Desktop.exe"),
        $(if ($pf86) { Join-Path $pf86 "Docker\Docker\Docker Desktop.exe" } else { $null }),
        (Join-Path $env:LOCALAPPDATA "Docker\Docker Desktop.exe")
    )
    foreach ($p in $candidates) {
        if ($p -and (Test-Path -LiteralPath $p)) { return $p }
    }
    return $null
}

function Start-DockerDesktopIfNeeded {
    if (Test-DockerReady) { return $true }

    if (-not (Test-DockerCli)) {
        Write-Warn "docker CLI not found; install Docker Desktop first"
        return $false
    }

    $exe = Get-DockerDesktopPath
    $proc = Get-Process -Name "Docker Desktop","com.docker.backend","com.docker.service" -ErrorAction SilentlyContinue
    if (-not $proc) {
        if (-not $exe) {
            Write-Warn "Docker Desktop.exe not found"
            return $false
        }
        Write-Step "Starting Docker Desktop"
        Start-Process -FilePath $exe | Out-Null
        Write-Ok "Docker Desktop launched; waiting for engine..."
    } else {
        Write-Step "Docker Desktop process found; waiting for engine..."
    }

    $started = Get-Date
    $deadline = $started.AddSeconds([Math]::Max(30, $DockerWaitSec))
    $n = 0
    while ((Get-Date) -lt $deadline) {
        if (Test-DockerReady) {
            Write-Ok "Docker engine ready"
            return $true
        }
        $n++
        if ($n % 5 -eq 0) {
            $elapsed = [int]((Get-Date) - $started).TotalSeconds
            Write-Host ("  ...waiting Docker ({0}s / {1}s)" -f $elapsed, $DockerWaitSec) -ForegroundColor DarkGray
        }
        Start-Sleep -Seconds 2
    }
    Write-Warn ("Docker wait timeout ({0}s)" -f $DockerWaitSec)
    return $false
}

function Start-NativeFallback([string]$reason) {
    Write-Warn $reason
    Write-Step "Fallback to native mode (start-host.ps1)"
    & (Join-Path $Root "start-host.ps1") -Rebuild:$Rebuild -NoBrowser:$NoBrowser -ShowConsole:$ShowConsole
    exit $LASTEXITCODE
}

if ($UseHost) {
    Start-NativeFallback "UseHost specified"
}

$dockerReady = Start-DockerDesktopIfNeeded
if (-not $dockerReady) {
    Start-NativeFallback "Docker not ready; fallback native. Fix Docker then rerun .\start.ps1"
}

Write-Step "Apply China Docker registry mirrors"
& (Join-Path $Root "scripts\Apply-DockerMirrors.ps1") -NoRestartHint

New-Item -ItemType Directory -Force -Path (Join-Path $Root ".runtime\pgdata") | Out-Null
New-Item -ItemType Directory -Force -Path (Join-Path $Root ".runtime\uploads") | Out-Null
New-Item -ItemType Directory -Force -Path (Join-Path $Root ".runtime\logs") | Out-Null

# Wipe native leftovers so Docker and host never fight over the same ports
Write-Step "Pre-clean ports / native leftovers"
& (Join-Path $Root "scripts\Stop-Stack.ps1") -Quiet

Write-Step "Build web dist (auto, includes /#/preview)"
& (Join-Path $Root "scripts\Ensure-Web.ps1") -BuildDist
if (-not $?) {
    Start-NativeFallback "web dist build failed; fallback native (vite)."
}

# Prefer DaoCloud-prefixed library images (see docker-compose.yml / Dockerfiles)
if (-not $env:DOCKER_BASE_REGISTRY) {
    $env:DOCKER_BASE_REGISTRY = "docker.m.daocloud.io/library"
}

Write-Step "Docker Compose up (data -> .runtime)"
# Prefer reuse of local images; --build only when -Rebuild (Hub often fails in CN)
$composeArgs = @("compose", "up", "-d")
if ($Rebuild) { $composeArgs += "--build" }
& docker @composeArgs
if ($LASTEXITCODE -ne 0) {
    Write-Warn "compose up failed; retry once with --build"
    & docker compose up -d --build
}
if ($LASTEXITCODE -ne 0) {
    # Hub / network failures are common in CN; keep the stack usable via native mode
    Start-NativeFallback "docker compose failed (Docker Hub/network). Auto fallback to native mode."
}

Write-Step "Waiting for gateway / web"
$ok = $false
for ($i = 0; $i -lt 60; $i++) {
    try {
        $h = Invoke-WebRequest -Uri "http://127.0.0.1:8180/gateway/health" -UseBasicParsing -TimeoutSec 2
        $w = Invoke-WebRequest -Uri "http://127.0.0.1:5173/" -UseBasicParsing -TimeoutSec 2
        if ($h.StatusCode -lt 500 -and $w.StatusCode -lt 500) { $ok = $true; break }
    } catch {
        # retry
    }
    Start-Sleep -Seconds 2
}
if ($ok) { Write-Ok "services ready" } else { Write-Warn "health check timeout, see: docker compose logs" }

$sql = 'ALTER USER platform CREATEDB;'
& docker compose exec -T postgres psql -U platform -d platform -c $sql 2>&1 | Out-Null

Write-Host ""
Write-Host "========================================" -ForegroundColor Green
Write-Host "  Web      http://127.0.0.1:5173"
Write-Host "  Gateway  http://127.0.0.1:8180"
Write-Host "  Account  demo / demo123"
Write-Host "  Data     $Root\.runtime"
Write-Host "  Stop     .\stop.ps1"
Write-Host "========================================" -ForegroundColor Green

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