$ErrorActionPreference = "Stop"

$root = Split-Path -Parent $MyInvocation.MyCommand.Path
$stateDir = Join-Path $root ".orchestration"
$pidFile = Join-Path $stateDir "pids.json"
$python = Join-Path $root ".venv\\Scripts\\python.exe"
$status = [ordered]@{}
$engineExternal = $env:ENGINE_EXTERNAL -and $env:ENGINE_EXTERNAL.ToLower() -in @("1", "true", "yes")

if (-not $env:DB_HOST) { $env:DB_HOST = "localhost" }
if (-not $env:DB_PORT) { $env:DB_PORT = "5432" }
if (-not $env:DB_NAME) { $env:DB_NAME = "trading_db" }
if (-not $env:DB_USER) { $env:DB_USER = "trader" }
if (-not $env:DB_PASSWORD) { $env:DB_PASSWORD = "traderpass" }
if (-not $env:PGHOST) { $env:PGHOST = $env:DB_HOST }
if (-not $env:PGPORT) { $env:PGPORT = $env:DB_PORT }
if (-not $env:PGDATABASE) { $env:PGDATABASE = $env:DB_NAME }
if (-not $env:PGUSER) { $env:PGUSER = $env:DB_USER }
if (-not $env:PGPASSWORD) { $env:PGPASSWORD = $env:DB_PASSWORD }

function Write-Status {
  param(
    [string]$Label,
    [bool]$Ok,
    [string]$Detail = ""
  )
  if ($Ok) {
    $status[$Label] = "OK"
    Write-Host ("[OK]  {0} {1}" -f $Label, $Detail) -ForegroundColor Green
  } else {
    $status[$Label] = "FAIL"
    Write-Host ("[FAIL] {0} {1}" -f $Label, $Detail) -ForegroundColor Red
  }
}

if (-not (Test-Path $python)) {
  Write-Status "Python venv" $false $python
  exit 1
}
Write-Status "Python venv" $true $python

New-Item -ItemType Directory -Force -Path $stateDir | Out-Null

if (Test-Path $pidFile) {
  try {
    $pids = Get-Content $pidFile | ConvertFrom-Json
    $running = $false
    foreach ($name in @("backend", "engine", "frontend")) {
      $pid = $pids.$name
      if ($pid) {
        $proc = Get-Process -Id $pid -ErrorAction SilentlyContinue
        if ($proc) { $running = $true }
      }
    }
    if ($running) {
      Write-Host "Services already running. Use .\\stop_all.ps1 to stop."
      exit 0
    }
  } catch {
    Remove-Item $pidFile -Force -ErrorAction SilentlyContinue
  }
}

Write-Host "Starting PostgreSQL (docker)..."
$pgRunning = ""
docker ps --filter "name=trading_postgres" --format "{{.ID}}" | ForEach-Object { $pgRunning = $_ }
if ($LASTEXITCODE -ne 0) {
  Write-Status "Docker" $false "not running"
  exit 1
}
Write-Status "Docker" $true "running"
if (-not $pgRunning) {
  docker compose up -d postgres
  if ($LASTEXITCODE -ne 0) {
    Write-Status "PostgreSQL" $false "failed to start"
    exit 1
  }
}
Write-Status "PostgreSQL" $true "container up"

Write-Host "Applying migrations..."
if (Test-Path (Join-Path $root "alembic.ini")) {
  & $python -m alembic upgrade head
} elseif (Test-Path (Join-Path $root "backend\\alembic.ini")) {
  & $python -m alembic -c (Join-Path $root "backend\\alembic.ini") upgrade head
}
& $python (Join-Path $root "backend\\scripts\\run_migrations.py")
if ($LASTEXITCODE -ne 0) {
  Write-Status "Migrations" $false "failed"
  exit 1
}
Write-Status "Migrations" $true "applied"

Write-Host "Starting backend..."
$backendCmd = "& { `$env:PYTHONPATH = '$root;$root\\backend'; cd '$root\\backend'; & '$python' -m uvicorn app.main:app --reload }"
$backendProc = Start-Process -FilePath "powershell" -ArgumentList @(
  "-NoExit",
  "-Command",
  $backendCmd
) -PassThru
Write-Status "Backend" $true "pid $($backendProc.Id)"

if ($engineExternal) {
  Write-Host "Starting engine runner..."
  $engineCmd = "& { `$env:PYTHONPATH = '$root;$root\\backend'; cd '$root'; & '$python' -m indian_paper_trading_strategy.engine.engine_runner }"
  $engineProc = Start-Process -FilePath "powershell" -ArgumentList @(
    "-NoExit",
    "-Command",
    $engineCmd
  ) -PassThru
  Write-Status "Engine" $true "pid $($engineProc.Id)"
} else {
  Write-Host "Engine runner skipped (ENGINE_EXTERNAL not set). Backend will run engine."
  Write-Status "Engine" $true "embedded"
}

Write-Host "Starting frontend..."
$frontendProc = Start-Process -FilePath "powershell" -ArgumentList @(
  "-NoExit",
  "-Command",
  "cd '$root\\frontend'; npm run dev"
) -PassThru
Write-Status "Frontend" $true "pid $($frontendProc.Id)"

@{
  backend = $backendProc.Id
  engine = if ($engineExternal) { $engineProc.Id } else { $null }
  frontend = $frontendProc.Id
  started_at = (Get-Date).ToString("o")
} | ConvertTo-Json | Set-Content -Encoding ascii $pidFile

Write-Host "Waiting for backend health..."
$healthUrl = "http://localhost:8000/health"
$deadline = [DateTime]::UtcNow.AddMinutes(2)
$healthy = $false
while ([DateTime]::UtcNow -lt $deadline) {
  try {
    $resp = Invoke-WebRequest -Uri $healthUrl -UseBasicParsing -TimeoutSec 2
    if ($resp.StatusCode -eq 200) {
      $healthy = $true
      break
    }
  } catch {
    Start-Sleep -Seconds 2
  }
}

if ($healthy) {
  Write-Status "Backend health" $true $healthUrl
  Write-Host ""
  Write-Host "System online at http://localhost:3000/admin"
  Start-Process "http://localhost:3000/admin"
} else {
  Write-Status "Backend health" $false $healthUrl
  Write-Host "Backend health check failed. Open http://localhost:3000/admin manually."
}

Write-Host ""
Write-Host "Summary:"
foreach ($entry in $status.GetEnumerator()) {
  $label = $entry.Key
  $value = $entry.Value
  if ($value -eq "OK") {
    Write-Host ("  [OK]   {0}" -f $label) -ForegroundColor Green
  } else {
    Write-Host ("  [FAIL] {0}" -f $label) -ForegroundColor Red
  }
}
