# Start PostgreSQL with data directory = project/data/postgres (no Docker required)
param([string]$Root = '')

. "$PSScriptRoot\db-local.ps1"

function Start-PostgresWithWait {
  param(
    [string]$PgBin,
    [string]$PgData,
    [int]$Port,
    [int]$TimeoutSec = 120
  )

  $postgres = Join-Path $PgBin 'postgres.exe'
  if (-not (Test-Path $postgres)) {
    Write-Host '  [ERROR] postgres.exe not found'
    return $false
  }

  Write-Host '  Launching postgres...'
  [Console]::Out.Flush()

  # pg_ctl stdout/stderr를 PowerShell 파이프·캡처하면 Windows에서 영구 블로킹될 수 있음 → postgres 직접 기동
  Start-Process -FilePath $postgres -ArgumentList @('-D', $PgData, '-p', "$Port") -WindowStyle Hidden | Out-Null

  for ($i = 1; $i -le $TimeoutSec; $i++) {
    if (Test-DbPortOpen -Port $Port) {
      Write-Host "  PostgreSQL ready (${i}s)"
      return $true
    }
    if ($i -eq 1 -or $i % 5 -eq 0) {
      Write-Host "  ... waiting for port $Port ($i/${TimeoutSec}s)"
      [Console]::Out.Flush()
    }
    Start-Sleep -Seconds 1
  }
  return $false
}

if (-not $Root) { $Root = Get-ProjectRoot -FromScript $PSScriptRoot }

$pgBin = Find-PgBin
if (-not $pgBin) {
  Write-Host '[ERROR] PostgreSQL not found. Install PostgreSQL 16 or Docker Desktop.'
  return 1
}

$pgData = Get-PgDataDir -Root $Root
New-Item -ItemType Directory -Force -Path $pgData | Out-Null

$initdb = Join-Path $pgBin 'initdb.exe'
$pgCtl = Join-Path $pgBin 'pg_ctl.exe'
$logFile = Get-PgCtlLogPath -Root $Root
$hasData = Test-Path (Join-Path $pgData 'PG_VERSION')

if ($hasData) {
  Write-Host '  Existing DB found: data\postgres (keeping your data)'
} else {
  Write-Host '  No DB yet - will create data\postgres'
}

Ensure-BackendEnv -Root $Root
Set-PostgresPort -PgData $pgData -Port $LocalDbPort
Clear-StalePostmasterLock -PgData $pgData

if (Test-DbPortOpen -Port $LocalDbPort) {
  Write-Host "  PostgreSQL already running on port $LocalDbPort"
  return 0
}

# pid file only, process dead -> stop cleanly before restart
if (Test-Path (Join-Path $pgData 'postmaster.pid')) {
  Write-Host '  Cleaning up previous postgres instance...'
  [Console]::Out.Flush()
  $stopArgs = @('-D', $pgData, 'stop', '-m', 'fast', '-W', '-t', '5')
  $null = Start-Process -FilePath $pgCtl -ArgumentList $stopArgs -WindowStyle Hidden -Wait
  Start-Sleep -Seconds 1
  Clear-StalePostmasterLock -PgData $pgData
}

if (-not $hasData) {
  Write-Host '  Local DB init (data\postgres)...'
  $migrated = $false
  try {
    $migrated = & "$PSScriptRoot\migrate-legacy-db.ps1" -Root $Root -PgBin $pgBin -PgData $pgData -Port $LocalDbPort
  } catch {
    Write-Warning $_.Exception.Message
    if (Test-Path $pgData) {
      Get-ChildItem $pgData -Force -ErrorAction SilentlyContinue | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue
    }
    New-Item -ItemType Directory -Force -Path $pgData | Out-Null
  }

  if (-not $migrated) {
    & $initdb -D $pgData -U $LocalDbUser -E UTF8 --locale=C -A trust
    if ($LASTEXITCODE -ne 0) {
      Write-Host '[ERROR] initdb failed'
      return 1
    }
    Set-PostgresPort -PgData $pgData -Port $LocalDbPort
    Clear-StalePostmasterLock -PgData $pgData

    Write-Host '  Starting PostgreSQL (new database)...'
    if (-not (Start-PostgresWithWait -PgBin $pgBin -PgData $pgData -Port $LocalDbPort)) {
      Write-Host '[ERROR] PostgreSQL did not start — see data\pg_ctl.log'
      return 1
    }

    try {
      Invoke-Psql -PgBin $pgBin -Port $LocalDbPort -Sql "ALTER USER $LocalDbUser WITH PASSWORD '$LocalDbPassword';"
      Invoke-Psql -PgBin $pgBin -Port $LocalDbPort -Sql "CREATE DATABASE $LocalDbName OWNER $LocalDbUser;"
    } catch {
      Write-Host "[ERROR] $($_.Exception.Message)"
      return 1
    }
    return 0
  }
}

Write-Host '  Starting PostgreSQL (recovery after move may take 1-2 min)...'
if (-not (Start-PostgresWithWait -PgBin $pgBin -PgData $pgData -Port $LocalDbPort)) {
  Write-Host '[ERROR] PostgreSQL did not start — see data\pg_ctl.log'
  Write-Host '        1) 서버종료.bat db  2) 5초 대기  3) 서버시작.bat'
  Write-Host '        PC 종료 전 서버종료.bat db 로 DB 정상 종료 권장'
  Write-Host '        OneDrive/백신에서 data\postgres 제외'
  return 1
}

return 0
