<#
.SYNOPSIS
    ROA2WEB Backend Service Wrapper for NSSM

.DESCRIPTION
    This script is called by NSSM (Windows Service Manager) to start the backend.
    It ensures SSH tunnels are running before starting uvicorn.

    Flow:
    1. Start SSH tunnels via ssh-tunnel.ps1
    2. Wait for tunnel ports to be accessible (timeout 30s)
    3. Start uvicorn (blocking - NSSM monitors this process)

    This wrapper ensures the database connection is available before
    the FastAPI application tries to initialize the Oracle pool.

.NOTES
    Author: ROA2WEB Team
    Version: 1.0

    NSSM Configuration:
    - Application: powershell.exe
    - Arguments: -ExecutionPolicy Bypass -File "C:\path\to\start-backend-service.ps1"
    - AppDirectory: C:\inetpub\wwwroot\roa2web\backend
#>

$ErrorActionPreference = "Stop"

# =============================================================================
# CONFIGURATION
# =============================================================================

$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path

# Detect paths (can run from scripts dir or project root)
$PossibleRoots = @(
    (Join-Path $ScriptDir "..\..\.."),       # From deployment/windows/scripts
    $ScriptDir,                               # From project root
    "C:\inetpub\wwwroot\roa2web"             # Production path
)

$ProjectRoot = $null
foreach ($path in $PossibleRoots) {
    $resolved = [System.IO.Path]::GetFullPath($path)
    if (Test-Path (Join-Path $resolved "backend\main.py")) {
        $ProjectRoot = $resolved
        break
    }
}

if (-not $ProjectRoot) {
    Write-Host "[ERROR] Cannot find project root (looking for backend/main.py)" -ForegroundColor Red
    exit 1
}

$BackendDir = Join-Path $ProjectRoot "backend"
# SSH tunnel script - check production location first, then development
$TunnelsScript = Join-Path $ProjectRoot "scripts\ssh-tunnel.ps1"
if (-not (Test-Path $TunnelsScript)) {
    $TunnelsScript = Join-Path $ProjectRoot "deployment\windows\scripts\ssh-tunnel.ps1"
}
$TunnelsConfig = Join-Path $BackendDir "ssh-tunnels.json"
$VenvPath = "C:\inetpub\wwwroot\roa2web-venv"
$VenvPython = Join-Path $VenvPath "Scripts\python.exe"
$LogDir = Join-Path $ProjectRoot "logs"

# Fallback to local venv if production venv doesn't exist
if (-not (Test-Path $VenvPython)) {
    $VenvPath = Join-Path $BackendDir "venv"
    $VenvPython = Join-Path $VenvPath "Scripts\python.exe"
}

# =============================================================================
# HELPER FUNCTIONS
# =============================================================================

function Write-Log {
    param([string]$Message, [string]$Level = "INFO")
    $timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
    Write-Host "[$timestamp] [$Level] $Message"
}

function Test-PortOpen {
    param([int]$Port, [int]$Timeout = 3)
    try {
        $tcpClient = New-Object System.Net.Sockets.TcpClient
        $result = $tcpClient.BeginConnect("127.0.0.1", $Port, $null, $null)
        $success = $result.AsyncWaitHandle.WaitOne($Timeout * 1000)
        if ($success) {
            $tcpClient.EndConnect($result)
            $tcpClient.Close()
            return $true
        }
        return $false
    } catch {
        return $false
    }
}

function Get-TunnelPorts {
    # Read ports from ssh-tunnels.json
    if (-not (Test-Path $TunnelsConfig)) {
        Write-Log "No ssh-tunnels.json found, assuming no tunnels needed" "WARN"
        return @()
    }

    try {
        $tunnels = Get-Content $TunnelsConfig -Raw | ConvertFrom-Json
        $ports = @()
        foreach ($tunnel in $tunnels) {
            # Only include tunnels that have ssh_host configured
            if ($tunnel.ssh_host) {
                $ports += [int]$tunnel.local_port
            }
        }
        return $ports
    } catch {
        Write-Log "Failed to parse ssh-tunnels.json: $_" "ERROR"
        return @()
    }
}

# =============================================================================
# MAIN STARTUP SEQUENCE
# =============================================================================

Write-Log "=========================================="
Write-Log "ROA2WEB Backend Service Wrapper Starting"
Write-Log "=========================================="
Write-Log "Project Root: $ProjectRoot"
Write-Log "Backend Dir:  $BackendDir"
Write-Log "Venv Python:  $VenvPython"

# Ensure log directory exists
if (-not (Test-Path $LogDir)) {
    New-Item -ItemType Directory -Path $LogDir -Force | Out-Null
}

# -------------------------------------------------------------------------
# Step 1: Start SSH Tunnels
# -------------------------------------------------------------------------
Write-Log "Step 1: Starting SSH Tunnels..."

if (Test-Path $TunnelsScript) {
    try {
        & $TunnelsScript start
        Write-Log "SSH tunnel script executed"
    } catch {
        Write-Log "SSH tunnel script failed: $_" "ERROR"
        # Continue anyway - tunnels might already be running
    }
} else {
    Write-Log "SSH tunnel script not found at $TunnelsScript" "WARN"
}

# -------------------------------------------------------------------------
# Step 2: Wait for Tunnel Ports
# -------------------------------------------------------------------------
$tunnelPorts = Get-TunnelPorts

if ($tunnelPorts.Count -gt 0) {
    Write-Log "Step 2: Waiting for tunnel ports: $($tunnelPorts -join ', ')..."

    $timeout = 30
    $waited = 0
    $allReady = $false

    while ($waited -lt $timeout) {
        $allReady = $true
        foreach ($port in $tunnelPorts) {
            if (-not (Test-PortOpen $port)) {
                $allReady = $false
                break
            }
        }

        if ($allReady) {
            Write-Log "All tunnel ports are accessible"
            break
        }

        Start-Sleep -Seconds 1
        $waited++

        if ($waited % 5 -eq 0) {
            Write-Log "Still waiting for tunnel ports... ($waited/${timeout}s)"
        }
    }

    if (-not $allReady) {
        Write-Log "Tunnel ports not ready after ${timeout}s - continuing anyway" "WARN"
    }
} else {
    Write-Log "Step 2: No tunnel ports configured, skipping wait"
}

# -------------------------------------------------------------------------
# Step 3: Start uvicorn (blocking)
# -------------------------------------------------------------------------
Write-Log "Step 3: Starting uvicorn..."
Write-Log "Working Directory: $BackendDir"
Write-Log "Python: $VenvPython"

# Verify Python exists
if (-not (Test-Path $VenvPython)) {
    Write-Log "Python not found at $VenvPython" "ERROR"
    exit 1
}

# Set working directory
Set-Location $BackendDir

# Set PYTHONPATH for shared modules
$env:PYTHONPATH = "$ProjectRoot;$BackendDir"

# Start uvicorn (this blocks - NSSM monitors this process)
# NOTE: --workers 1 is required because Telegram bot uses polling (single instance only)
Write-Log "Executing: $VenvPython -m uvicorn main:app --host 127.0.0.1 --port 8000 --workers 1"

& $VenvPython -m uvicorn main:app --host 127.0.0.1 --port 8000 --workers 1

# If we get here, uvicorn has exited
$exitCode = $LASTEXITCODE
Write-Log "uvicorn exited with code: $exitCode" "WARN"
exit $exitCode
