# Deploy SOLUTION_ERP all-in-one on VPS Windows Server.
# Runs 4 steps: SQL -> IIS -> SSL -> Runner. Idempotent. Stops on first step fail.
#
# Usage:
#   .\deploy-all.ps1 `
#       -SaPassword '<SA pw>' `
#       -JwtSecret '<64-char hex>' `
#       -VrappPassword '<vrapp pw>' `
#       -RunnerToken '<gitea runner registration token>' `
#       -AdminEmail 'admin@huypham.vn'
#
# Prereq (pre-check will verify):
#   - Windows Server + Admin PowerShell
#   - IIS + URL Rewrite installed
#   - SQL Server with login 'sa' + 'vrapp' exists
#   - .NET 10 Hosting Bundle installed
#   - Port 80+443 firewall open
#   - DNS api/admin/eoffice.solutions.com.vn pointing to VPS

[CmdletBinding()]
param(
    [Parameter(Mandatory=$true)] [string]$SaPassword,
    [Parameter(Mandatory=$true)] [string]$JwtSecret,
    [Parameter(Mandatory=$true)] [string]$VrappPassword,
    [Parameter(Mandatory=$true)] [string]$RunnerToken,
    [string]$AdminEmail = "admin@huypham.vn",
    [switch]$SkipSsl,
    [switch]$SkipRunner
)

$ErrorActionPreference = 'Stop'
$ScriptRoot = $PSScriptRoot
$StartTime = Get-Date

function Write-Banner($text) {
    Write-Host ""
    Write-Host ("=" * 70) -ForegroundColor Cyan
    Write-Host " $text" -ForegroundColor Cyan
    Write-Host ("=" * 70) -ForegroundColor Cyan
}

function Test-Prereq {
    $issues = @()

    if (-not ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
        $issues += "Not running with Admin privilege"
    }

    if (-not (Get-Module -ListAvailable -Name SqlServer)) {
        if (-not (Get-Command sqlcmd -ErrorAction SilentlyContinue)) {
            $issues += "Neither SqlServer PS module nor sqlcmd.exe available. Install-Module SqlServer -Scope AllUsers -Force"
        }
    }

    if (-not (Get-Module -ListAvailable -Name WebAdministration)) {
        $issues += "IIS WebAdministration module not installed (Install-WindowsFeature Web-Server,Web-Scripting-Tools)"
    }

    $dotnet10 = & dotnet --list-runtimes 2>$null | Select-String "Microsoft.AspNetCore.App 10"
    if (-not $dotnet10) {
        $issues += ".NET 10 Hosting Bundle not installed (https://dotnet.microsoft.com/download/dotnet/10.0)"
    }

    return $issues
}

Write-Banner "Pre-check prerequisites"
$issues = Test-Prereq
if ($issues.Count -gt 0) {
    Write-Host "[FAIL] Issues:" -ForegroundColor Red
    $issues | ForEach-Object { Write-Host "  - $_" -ForegroundColor Red }
    Write-Host ""
    Write-Host "Fix the above then re-run." -ForegroundColor Yellow
    exit 1
}
Write-Host "[OK] All prerequisites present"

# ===================== Step 1: SQL DB =====================
Write-Banner "Step 1/4: SQL Database setup"
try {
    & "$ScriptRoot\setup-sql-db.ps1" -SaPassword $SaPassword
    if ($LASTEXITCODE -ne 0) { throw "setup-sql-db.ps1 exit $LASTEXITCODE" }
} catch {
    Write-Host "[FAIL] Step 1: $_" -ForegroundColor Red
    exit 1
}

# ===================== Step 2: IIS sites =====================
Write-Banner "Step 2/4: IIS sites + app pool"
try {
    & "$ScriptRoot\setup-iis-sites.ps1"
    if ($LASTEXITCODE -ne 0) { throw "setup-iis-sites.ps1 exit $LASTEXITCODE" }
} catch {
    Write-Host "[FAIL] Step 2: $_" -ForegroundColor Red
    exit 1
}

# ===================== Step 3: appsettings.Production.json =====================
Write-Banner "Step 3/4: Write appsettings.Production.json"
$apiPath = "C:\inetpub\solution-erp\api"
$example = "$apiPath\appsettings.Production.json.example"
$prod = "$apiPath\appsettings.Production.json"

if (Test-Path $example) {
    $content = (Get-Content $example -Raw) `
        -replace [regex]::Escape('__SET_VIA_SECRETS__'), $VrappPassword `
        -replace [regex]::Escape('__SET_VIA_USER_SECRETS_OR_ENV__minimum_64_chars_random'), $JwtSecret
    Set-Content -Path $prod -Value $content -Encoding UTF8
    Write-Host "[OK] Wrote $prod"
    # ACL: only Administrators + app pool identity can read
    icacls $prod /inheritance:r | Out-Null
    icacls $prod /grant:r 'Administrators:(R,W)' 'IIS AppPool\SolutionErp-Api:(R)' | Out-Null
    Write-Host "  ACL restricted (Admins RW + AppPool R only)"
} else {
    Write-Warning "Template not found at $example - skip (deploy may not have run yet; need Gitea Actions deploy first)"
    Write-Warning "After CI deploy, re-run this step or copy manually."
}

# ===================== Step 4: SSL =====================
if (-not $SkipSsl) {
    Write-Banner "Step 4/4 (SSL): win-acme Let's Encrypt"
    Write-Host "WARNING: Port 80 must be reachable from Internet (Let's Encrypt HTTP-01)"
    Write-Host "   Test from outside: curl http://api.solutions.com.vn"
    $confirm = Read-Host "Continue? (y/N)"
    if ($confirm -eq 'y') {
        try {
            & "$ScriptRoot\setup-ssl.ps1"
        } catch {
            Write-Warning "SSL fail: $_ - can fix later + re-run setup-ssl.ps1"
        }
    } else {
        Write-Host "Skip SSL - run setup-ssl.ps1 manually later"
    }
} else {
    Write-Host "Skip SSL (-SkipSsl flag)"
}

# ===================== Step 5: Runner =====================
if (-not $SkipRunner -and $RunnerToken -ne "SKIP") {
    Write-Banner "Step 5 (Runner): Gitea Actions runner"
    try {
        & "$ScriptRoot\setup-gitea-runner.ps1" -RegistrationToken $RunnerToken
    } catch {
        Write-Warning "Runner setup fail: $_ - run setup-gitea-runner.ps1 manually later"
    }
}

# ===================== Summary =====================
$duration = (Get-Date) - $StartTime
Write-Banner "[OK] DEPLOY ALL DONE - $([int]$duration.TotalMinutes)m $([int]($duration.TotalSeconds % 60))s"
Write-Host ""
Write-Host "Next:"
Write-Host "  1. Verify 3 domains:"
Write-Host "       curl https://api.solutions.com.vn/health/live"
Write-Host "       curl -I https://admin.solutions.com.vn"
Write-Host "       curl -I https://eoffice.solutions.com.vn"
Write-Host ""
Write-Host "  2. Set remaining 2 Gitea secrets (if not done):"
Write-Host "       https://git.baocaogiaoduc.vn/vietreport-admin/solution-erp/settings/actions/secrets"
Write-Host "       - JWT_SECRET (update with 64-char)"
Write-Host "       - IIS_PASSWORD (Windows admin password)"
Write-Host ""
Write-Host "  3. Trigger deploy: push main commit -> Gitea Actions pick up -> workflow runs"
Write-Host ""
Write-Host "  4. Change default admin password after login (security-checklist.md)"
