# Enhanced Host Monitoring (Phase 1: Job 893 Execution)
# Purpose: Comprehensive health checks during 50-90+ day execution
# Governance: AGENTS.md v16.0 (Evidence-based, Traceability)
# Update Interval: 30 minutes (detailed) + 5 minutes (quick health check)

param(
    [int]$DetailedIntervalMinutes = 30,
    [int]$QuickIntervalMinutes = 5,
    [string]$LogFile = "logs/host-monitoring.log",
    [string]$MetricsFile = "logs/monitoring-metrics.csv"
)

$ErrorActionPreference = "SilentlyContinue"

function Write-Log {
    param([string]$Message, [string]$Level = "INFO")

    $timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
    $logEntry = "[$timestamp] [$Level] $Message"

    Write-Host $logEntry -ForegroundColor $(
        if ($Level -eq "ERROR") { "Red" }
        elseif ($Level -eq "WARN") { "Yellow" }
        else { "Green" }
    )

    Add-Content -Path $LogFile -Value $logEntry
}

function Test-HostHealth {
    # Quick health check (5-min interval)
    $status = @{
        Timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
        HostRunning = $false
        PortOpen = $false
        ResponseTime = $null
        LastCheck = Get-Date
    }

    try {
        $tcp = New-Object System.Net.Sockets.TcpClient
        $stopwatch = [System.Diagnostics.Stopwatch]::StartNew()
        $tcp.Connect("127.0.0.1", 5002)
        $stopwatch.Stop()

        if ($tcp.Connected) {
            $status.HostRunning = $true
            $status.PortOpen = $true
            $status.ResponseTime = $stopwatch.ElapsedMilliseconds
            $tcp.Close()
        }
    } catch {
        $status.HostRunning = $false
        $status.PortOpen = $false
    }

    return $status
}

function Get-DetailedMetrics {
    # Detailed checks (30-min interval)
    $metrics = @{
        Timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
        ProcessHealth = @{}
        DatabaseHealth = @{}
        JobStatus = @{}
        Errors = @()
    }

    # Process Health
    $proc = Get-Process -Name "KArtSell.Host" -ErrorAction SilentlyContinue
    if ($proc) {
        $metrics.ProcessHealth = @{
            ProcessId = $proc.Id
            MemoryMB = [Math]::Round($proc.WorkingSet / 1MB)
            CpuPercent = $proc.CPU  # Requires performance counter setup
            ThreadCount = $proc.Threads.Count
            HandleCount = $proc.HandleCount
            Uptime = $(if ($proc.StartTime) { ((Get-Date) - $proc.StartTime).TotalHours } else { 0 })
        }
        Write-Log "Process health: PID=$($proc.Id), Memory=$($metrics.ProcessHealth.MemoryMB)MB, Threads=$($metrics.ProcessHealth.ThreadCount)" "INFO"
    } else {
        $metrics.Errors += "Host process not found"
        Write-Log "ERROR: Host process not running" "ERROR"
    }

    # Database Health (via SSH query)
    try {
        $dbCheck = ssh kjh2064@178.104.200.7 "PGPASSWORD='kartsell4321@!' psql -h localhost -p 5432 -U kartsell -d kartselldb -c 'SELECT COUNT(*) as job_count FROM hangfire.job;'" 2>$null

        if ($dbCheck -match "(\d+)") {
            $jobCount = [int]$matches[1]
            $metrics.DatabaseHealth = @{
                ConnectionStatus = "OK"
                JobCount = $jobCount
                LastQueryTime = Get-Date -Format "HH:mm:ss"
            }
            Write-Log "Database health: $jobCount Hangfire jobs" "INFO"
        } else {
            $metrics.DatabaseHealth = @{
                ConnectionStatus = "FAILED"
                JobCount = 0
                Error = "Query returned no results"
            }
            Write-Log "Database query inconclusive" "WARN"
        }
    } catch {
        $metrics.Errors += "Database health check failed: $_"
        Write-Log "Database connection failed" "ERROR"
    }

    # Job 893 Status
    try {
        $jobStatus = ssh kjh2064@178.104.200.7 "PGPASSWORD='kartsell4321@!' psql -h localhost -p 5432 -U kartsell -d kartselldb -c \"SELECT State, CreatedAt FROM hangfire.job WHERE Id = 893;\" 2>/dev/null"

        if ($jobStatus) {
            $metrics.JobStatus = @{
                JobId = 893
                Status = "Queried"
                Details = $jobStatus -split "`n" | Where-Object { $_ -match "^\|" } | Select-Object -First 1
            }
            Write-Log "Job 893 status: $($metrics.JobStatus.Details)" "INFO"
        }
    } catch {
        Write-Log "Job 893 status query failed" "WARN"
    }

    return $metrics
}

function Export-Metrics {
    param($metrics, $filePath)

    $csv = "$($metrics.Timestamp),$($metrics.ProcessHealth.ProcessId),$($metrics.ProcessHealth.MemoryMB),$($metrics.ProcessHealth.ThreadCount),$($metrics.DatabaseHealth.JobCount)"

    # Create header if file doesn't exist
    if (-not (Test-Path $filePath)) {
        $header = "Timestamp,ProcessId,MemoryMB,ThreadCount,JobCount"
        Add-Content -Path $filePath -Value $header
    }

    Add-Content -Path $filePath -Value $csv
}

function Invoke-AlertCheck {
    param($metrics, $status)

    # Alert thresholds
    $alerts = @()

    # Memory threshold: 500MB
    if ($metrics.ProcessHealth.MemoryMB -gt 500) {
        $alerts += "WARN: High memory usage ($($metrics.ProcessHealth.MemoryMB)MB > 500MB)"
    }

    # Connection failure
    if (-not $status.PortOpen) {
        $alerts += "ERROR: Host not responding on port 5002"
    }

    # Database connection failure
    if ($metrics.DatabaseHealth.ConnectionStatus -eq "FAILED") {
        $alerts += "ERROR: Database connection failed"
    }

    # No job progress (same job count for 6 consecutive checks)
    # TODO: Implement with state tracking

    foreach ($alert in $alerts) {
        Write-Log $alert $(if ($alert -like "ERROR*") { "ERROR" } else { "WARN" })
    }

    return $alerts.Count -eq 0  # Return $true if no alerts
}

# ============================================================================
# MAIN LOOP
# ============================================================================

Write-Log "=== HOST MONITORING STARTED ===" "INFO"
Write-Log "Detail interval: $DetailedIntervalMinutes min, Quick interval: $QuickIntervalMinutes min" "INFO"

$detailedCounter = 0
$lastDetailedCheck = (Get-Date).AddMinutes(-$DetailedIntervalMinutes)

while ($true) {
    # Quick health check (every 5 minutes)
    $status = Test-HostHealth

    if ($status.HostRunning) {
        Write-Log "✓ Host healthy (Response: $($status.ResponseTime)ms)" "INFO"
    } else {
        Write-Log "✗ Host UNHEALTHY - Not responding" "ERROR"
    }

    # Detailed check (every 30 minutes)
    $now = Get-Date
    if (($now - $lastDetailedCheck).TotalMinutes -ge $DetailedIntervalMinutes) {
        Write-Log "--- DETAILED METRICS COLLECTION ---" "INFO"

        $metrics = Get-DetailedMetrics
        Export-Metrics $metrics $MetricsFile

        $alertStatus = Invoke-AlertCheck $metrics $status
        if ($alertStatus) {
            Write-Log "All health checks passed" "INFO"
        } else {
            Write-Log "Health alerts detected - review logs" "WARN"
        }

        $lastDetailedCheck = $now
    }

    # Wait for next check
    Start-Sleep -Seconds ($QuickIntervalMinutes * 60)
}
