<#
.SYNOPSIS
  Deploy the Lean 101 Clients app to a Digital Ocean droplet over SSH.

.DESCRIPTION
  Tars the local source tree, uploads it to the droplet, and runs
  docker compose up --build. No git required on the server.

  The same script handles first-time setup and subsequent updates.

.PARAMETER RemoteHost
  Hostname or IP of the Digital Ocean droplet. Required.

.PARAMETER RemoteUser
  SSH user. Defaults to 'root'.

.PARAMETER RemotePath
  Absolute path on the droplet. Defaults to '/srv/lean101-clients'.

.PARAMETER EnvFile
  Local path to the production env file. Defaults to '.env.production'.

.PARAMETER SshKey
  Optional path to an SSH private key.

.PARAMETER ComposeFile
  Compose file name on the remote host. Defaults to 'docker-compose.production.yml'.

.PARAMETER Seed
  Run 'python -m app.seed' inside the backend container after the stack is up.

.PARAMETER Logs
  Tail logs for ~60 lines after deploy to verify the stack came up.

.PARAMETER SkipBuild
  Pass --no-build to docker compose (use when only env changed).

.EXAMPLE
  ./deploy/Deploy.ps1 -RemoteHost 209.38.24.231

.EXAMPLE
  ./deploy/Deploy.ps1 -RemoteHost 209.38.24.231 -Seed -Logs
#>

[CmdletBinding()]
param(
  [Parameter(Mandatory = $true)] [string] $RemoteHost,
  [string] $RemoteUser     = "root",
  [string] $RemotePath     = "/srv/lean101-clients",
  [string] $EnvFile        = ".env.production",
  [string] $SshKey,
  [string] $ComposeFile    = "docker-compose.production.yml",
  [switch] $Seed,
  [switch] $Logs,
  [switch] $SkipBuild
)

$ErrorActionPreference = "Stop"
Set-StrictMode -Version Latest

# ── Helpers ───────────────────────────────────────────────────────────────────
function Write-Step($msg) { Write-Host "==> $msg" -ForegroundColor Cyan }
function Write-Warn($msg) { Write-Host "!!  $msg" -ForegroundColor Yellow }

function Get-RepoRoot {
  $dir = Split-Path -Parent $PSScriptRoot
  if (-not $dir) { $dir = (Get-Location).Path }
  return $dir
}

$RepoRoot   = Get-RepoRoot
$SshTarget  = "$RemoteUser@$RemoteHost"
$SshOpts    = @("-o", "StrictHostKeyChecking=accept-new", "-o", "BatchMode=no")
if ($SshKey) { $SshOpts += @("-i", $SshKey) }

function Invoke-Ssh([string] $cmd) {
  & ssh @SshOpts $SshTarget $cmd
  if ($LASTEXITCODE -ne 0) { throw "Remote command failed (exit $LASTEXITCODE): $cmd" }
}

function Invoke-Scp([string] $local, [string] $remote) {
  & scp @SshOpts $local "${SshTarget}:${remote}"
  if ($LASTEXITCODE -ne 0) { throw "scp failed: $local -> $remote" }
}

# ── Resolve paths ─────────────────────────────────────────────────────────────
Push-Location $RepoRoot
try {
  $EnvPath = if ([System.IO.Path]::IsPathRooted($EnvFile)) { $EnvFile } else { Join-Path $RepoRoot $EnvFile }
  if (-not (Test-Path $EnvPath)) {
    throw "Env file not found at '$EnvPath'. Copy .env.production.example and fill in secrets."
  }

  # ── Connectivity check ──────────────────────────────────────────────────────
  Write-Step "Checking SSH connectivity to $SshTarget"
  Invoke-Ssh "echo connected as `$(whoami) on `$(hostname)"

  # ── Package source files ────────────────────────────────────────────────────
  Write-Step "Packaging source files (excluding node_modules, caches, etc.)"

  $TarFile = Join-Path $env:TEMP "lean101-deploy-$(Get-Date -Format 'yyyyMMdd-HHmmss').tar.gz"

  $excludes = @(
    "--exclude=./node_modules",
    "--exclude=./frontend/node_modules",
    "--exclude=./frontend/.svelte-kit",
    "--exclude=./frontend/build",
    "--exclude=./.git",
    "--exclude=./__pycache__",
    "--exclude=./backend/__pycache__",
    "--exclude=./backend/app/__pycache__",
    "--exclude=./**/__pycache__",
    "--exclude=./*.pyc",
    "--exclude=./.env",
    "--exclude=./.env.production",
    "--exclude=./.env.alpha",
    "--exclude=./data_entry_app.db",
    "--exclude=./*.db"
  )

  & tar -czf $TarFile @excludes -C $RepoRoot .
  if ($LASTEXITCODE -ne 0) { throw "tar failed" }

  $TarSize = [math]::Round((Get-Item $TarFile).Length / 1MB, 1)
  Write-Host "    Archive: $TarFile ($TarSize MB)"

  # ── Upload env file ─────────────────────────────────────────────────────────
  Write-Step "Uploading env file"
  Invoke-Scp $EnvPath "$RemotePath/.env.production"
  Invoke-Ssh "chmod 600 '$RemotePath/.env.production'"

  # ── Upload and extract source ────────────────────────────────────────────────
  Write-Step "Uploading source archive"
  Invoke-Scp $TarFile "/tmp/lean101-deploy.tar.gz"
  Remove-Item $TarFile -Force

  Write-Step "Extracting on server"
  Invoke-Ssh "mkdir -p '$RemotePath' && tar -xzf /tmp/lean101-deploy.tar.gz -C '$RemotePath' && rm /tmp/lean101-deploy.tar.gz"

  # ── Docker compose up ───────────────────────────────────────────────────────
  $ComposeArgs = "--env-file .env.production -f $ComposeFile"
  $BuildFlag   = if ($SkipBuild) { "--no-build" } else { "--build" }

  Write-Step "Bringing stack up (build=$(-not $SkipBuild))"
  Invoke-Ssh "cd '$RemotePath' && docker compose $ComposeArgs up -d $BuildFlag --remove-orphans"

  # ── Health check ────────────────────────────────────────────────────────────
  Write-Step "Waiting for backend health check"
  $healthScript = @"
set -e
cd '$RemotePath'
for i in `$(seq 1 30); do
  status=`$(docker inspect --format='{{if .State.Health}}{{.State.Health.Status}}{{else}}{{.State.Status}}{{end}}' lean101-clients-backend 2>/dev/null || echo missing)
  case "`$status" in
    healthy|running) echo "backend is `$status"; exit 0 ;;
    *) printf '.'; sleep 4 ;;
  esac
done
echo; echo 'backend did not become healthy in time' >&2; exit 1
"@
  Invoke-Ssh $healthScript

  # ── Optional seed ───────────────────────────────────────────────────────────
  if ($Seed) {
    Write-Step "Seeding reference data"
    Invoke-Ssh "cd '$RemotePath' && docker compose $ComposeArgs exec -T backend python -m app.seed"
  }

  # ── Final status ────────────────────────────────────────────────────────────
  Write-Step "Stack status"
  Invoke-Ssh "cd '$RemotePath' && docker compose $ComposeArgs ps"

  if ($Logs) {
    Write-Step "Recent logs (last 60 lines)"
    Invoke-Ssh "cd '$RemotePath' && docker compose $ComposeArgs logs --tail=60"
  }

  Write-Host ""
  Write-Host "Deployment complete -> https://clients.lean-101.com.au" -ForegroundColor Green
}
finally {
  Pop-Location
}
