# Setup IIS sites + app pools for SOLUTION_ERP on VPS Windows Server.
# Shared with VIETREPORT - naming isolation: SolutionErp-* prefix to avoid conflict.
# Run on VPS with admin privilege. Idempotent.
#
# Usage:
#   .\setup-iis-sites.ps1
#
# Prereq:
#   - IIS installed + features: Application Initialization, URL Rewrite, ARR (optional)
#   - .NET 10 Hosting Bundle installed
#   - Port 80/443 firewall open

$ErrorActionPreference = 'Stop'
Import-Module WebAdministration

# ===================== Config =====================
$Root          = "C:\inetpub\solution-erp"
$PathApi       = "$Root\api"
$PathAdmin     = "$Root\fe-admin"
$PathUser      = "$Root\fe-user"
$PathLogs      = "$Root\logs"
$PathUploads   = "$Root\uploads"
$PathTemplates = "$Root\api\wwwroot\templates"

$AppPoolApi = "SolutionErp-Api"

$DomainApi   = "api.solutions.com.vn"
$DomainAdmin = "admin.solutions.com.vn"
$DomainUser  = "eoffice.solutions.com.vn"

$SiteApi     = "SolutionErp-Api"
$SiteAdmin   = "SolutionErp-Admin"
$SiteUser    = "SolutionErp-User"

function Write-Step($msg) { Write-Host "==> $msg" -ForegroundColor Cyan }

# ===================== 1. Directories =====================
Write-Step "Create directories under $Root"
foreach ($p in @($Root, $PathApi, $PathAdmin, $PathUser, $PathLogs, $PathUploads, $PathTemplates)) {
    if (-not (Test-Path $p)) {
        New-Item -ItemType Directory -Force -Path $p | Out-Null
        Write-Host "  Created $p"
    } else {
        Write-Host "  Exists  $p"
    }
}

# Grant app pool identity write permission
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule(
    "IIS AppPool\$AppPoolApi", "Modify", "ContainerInherit,ObjectInherit", "None", "Allow")
try {
    $acl = Get-Acl $Root
    $acl.SetAccessRule($rule)
    Set-Acl -Path $Root -AclObject $acl
} catch {
    Write-Warning "  ACL set may fail if app pool does not exist yet - will retry"
}

# ===================== 2. App pool (Api only, FE is static) =====================
Write-Step "App pool: $AppPoolApi"
if (-not (Test-Path "IIS:\AppPools\$AppPoolApi")) {
    New-WebAppPool -Name $AppPoolApi | Out-Null
    Write-Host "  Created"
}
Set-ItemProperty "IIS:\AppPools\$AppPoolApi" -Name managedRuntimeVersion -Value ""
Set-ItemProperty "IIS:\AppPools\$AppPoolApi" -Name startMode -Value "AlwaysRunning"
Set-ItemProperty "IIS:\AppPools\$AppPoolApi" -Name processModel.identityType -Value "ApplicationPoolIdentity"
Set-ItemProperty "IIS:\AppPools\$AppPoolApi" -Name processModel.idleTimeout -Value "00:00:00"
Set-ItemProperty "IIS:\AppPools\$AppPoolApi" -Name recycling.periodicRestart.time -Value "00:00:00"
Write-Host "  Configured (NoManagedCode + AlwaysRunning + no idle timeout + no daily recycle)"

# Re-grant ACL after pool created (identity must exist)
try {
    $acl = Get-Acl $Root
    $acl.SetAccessRule($rule)
    Set-Acl -Path $Root -AclObject $acl
    Write-Host "  ACL granted Modify to IIS AppPool\$AppPoolApi"
} catch {
    Write-Warning "  ACL fail: $_"
}

# ===================== 3. Sites =====================
function Ensure-Site {
    param(
        [string]$Name, [string]$HostName, [string]$PhysicalPath, [string]$AppPool
    )
    Write-Step "Site: $Name ($HostName)"
    if (-not (Test-Path "IIS:\Sites\$Name")) {
        # Port 80 HTTP - SSL added later via win-acme
        $params = @{
            Name            = $Name
            HostHeader      = $HostName
            PhysicalPath    = $PhysicalPath
            Port            = 80
        }
        if ($AppPool) { $params.ApplicationPool = $AppPool }
        New-WebSite @params | Out-Null
        Write-Host "  Created"
    } else {
        Write-Host "  Exists"
        Set-ItemProperty "IIS:\Sites\$Name" -Name physicalPath -Value $PhysicalPath
        if ($AppPool) {
            Set-ItemProperty "IIS:\Sites\$Name" -Name applicationPool -Value $AppPool
        }
    }
}

Ensure-Site -Name $SiteApi   -HostName $DomainApi   -PhysicalPath $PathApi   -AppPool $AppPoolApi
Ensure-Site -Name $SiteAdmin -HostName $DomainAdmin -PhysicalPath $PathAdmin -AppPool ""
Ensure-Site -Name $SiteUser  -HostName $DomainUser  -PhysicalPath $PathUser  -AppPool ""

# ===================== 4. Placeholder index.html for FE (temporary until first real deploy) =====================
Write-Step "Placeholder index.html (pre-deploy)"
foreach ($fePath in @($PathAdmin, $PathUser)) {
    $idx = Join-Path $fePath "index.html"
    if (-not (Test-Path $idx)) {
        @"
<!DOCTYPE html><html><head><meta charset="utf-8"><title>SOLUTION ERP</title></head>
<body style="font:14px sans-serif;padding:40px;text-align:center;color:#555">
  <h1>SOLUTION ERP</h1>
  <p>Site created, waiting for first deploy via Gitea CI/CD.</p>
</body></html>
"@ | Set-Content -Path $idx -Encoding UTF8
        Write-Host "  Wrote $idx"
    } else {
        Write-Host "  Exists $idx"
    }
}

# ===================== 5. web.config for FE SPA routing =====================
Write-Step "web.config for FE SPA fallback"
$spaWebConfig = @'
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <system.webServer>
    <rewrite>
      <rules>
        <rule name="HTTP to HTTPS" stopProcessing="true">
          <match url="(.*)" />
          <conditions>
            <add input="{HTTPS}" pattern="^OFF$" />
          </conditions>
          <action type="Redirect" url="https://{HTTP_HOST}/{R:1}" redirectType="Permanent" />
        </rule>
        <rule name="SPA Routes" stopProcessing="true">
          <match url=".*" />
          <conditions logicalGrouping="MatchAll">
            <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
            <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
            <add input="{REQUEST_URI}" pattern="^/api" negate="true" />
          </conditions>
          <action type="Rewrite" url="/" />
        </rule>
      </rules>
    </rewrite>
    <staticContent>
      <remove fileExtension=".webmanifest" />
      <mimeMap fileExtension=".webmanifest" mimeType="application/manifest+json" />
    </staticContent>
    <httpProtocol>
      <customHeaders>
        <add name="X-Content-Type-Options" value="nosniff" />
        <add name="X-Frame-Options" value="DENY" />
        <add name="Referrer-Policy" value="strict-origin-when-cross-origin" />
      </customHeaders>
    </httpProtocol>
  </system.webServer>
</configuration>
'@

foreach ($fePath in @($PathAdmin, $PathUser)) {
    Set-Content -Path (Join-Path $fePath "web.config") -Value $spaWebConfig -Encoding UTF8
}
Write-Host "  Wrote SPA web.config for admin + user"

# ===================== 6. Firewall =====================
Write-Step "Firewall port 80/443"
$fwExists = Get-NetFirewallRule -DisplayName "HTTP In (SolutionErp)" -ErrorAction SilentlyContinue
if (-not $fwExists) {
    New-NetFirewallRule -DisplayName "HTTP In (SolutionErp)"  -Direction Inbound -LocalPort 80  -Protocol TCP -Action Allow | Out-Null
    New-NetFirewallRule -DisplayName "HTTPS In (SolutionErp)" -Direction Inbound -LocalPort 443 -Protocol TCP -Action Allow | Out-Null
    Write-Host "  Created 2 rules"
} else {
    Write-Host "  Exists"
}

# ===================== 7. Recap =====================
Write-Host ""
Write-Host "[OK] IIS setup DONE" -ForegroundColor Green
Write-Host "   3 sites:"
Write-Host "     - $SiteApi    -> $DomainApi   -> $PathApi     (app pool $AppPoolApi)"
Write-Host "     - $SiteAdmin  -> $DomainAdmin -> $PathAdmin   (no app pool - static)"
Write-Host "     - $SiteUser   -> $DomainUser  -> $PathUser    (no app pool - static)"
Write-Host ""
Write-Host "   Next:"
Write-Host "     1. Run .\setup-ssl.ps1 to install HTTPS cert for 3 domains"
Write-Host "     2. Deploy first build via Gitea Actions (push main to trigger workflow)"
Write-Host "     3. Verify https://$DomainApi/health/ready -> 200"
