# Caddy Configuration Manager for Windows
# This script adds new service configurations to your Caddyfile

param(
    [string]$Config,
    [string]$Subdomain,
    [string]$CaddyfilePath = "C:\caddy\Caddyfile",
    [bool]$ReloadCaddy = $true
)

# Function to write JSON response
function Write-JsonResponse {
    param($Status, $Message, $Data = $null)
    
    $response = @{
        status = $Status
        message = $Message
        timestamp = (Get-Date).ToString("yyyy-MM-dd HH:mm:ss")
    }
    
    if ($Data) {
        $response.data = $Data
    }
    
    return $response | ConvertTo-Json
}

# Function to extract CA names from Caddyfile
function Get-CaddyfileCAs {
    param([string]$CaddyfilePath)
    
    try {
        Write-Host "DEBUG: Checking file path: $CaddyfilePath"
        
        if (-not (Test-Path $CaddyfilePath)) {
            Write-Host "DEBUG: File not found"
            return @()
        }

        $content = Get-Content $CaddyfilePath -Raw
        Write-Host "DEBUG: File content length: $($content.Length)"
        Write-Host "DEBUG: First 200 chars: $($content.Substring(0, [Math]::Min(200, $content.Length)))"
        
        $caNames = @()

        # Pattern 1: PKI block with CA definitions - pki { ca ca_name { name "Friendly Name" } }
        $pkiPattern = 'pki\s*\{[^}]*?ca\s+([^\s\{]+)\s*\{([^}]*?)\}'
        Write-Host "DEBUG: Searching for PKI pattern: $pkiPattern"
        
        $pkiMatches = [regex]::Matches($content, $pkiPattern, [System.Text.RegularExpressions.RegexOptions]::IgnoreCase -bor [System.Text.RegularExpressions.RegexOptions]::Singleline)
        Write-Host "DEBUG: PKI matches found: $($pkiMatches.Count)"
        
        foreach ($match in $pkiMatches) {
            $caId = $match.Groups[1].Value
            $caBlock = $match.Groups[2].Value
            Write-Host "DEBUG: Found CA ID: $caId"
            Write-Host "DEBUG: CA Block: $caBlock"
            
            # Try to extract the friendly name from within the CA block
            $nameMatch = [regex]::Match($caBlock, 'name\s+"([^"]+)"', [System.Text.RegularExpressions.RegexOptions]::IgnoreCase)
            if ($nameMatch.Success) {
                $friendlyName = $nameMatch.Groups[1].Value
                Write-Host "DEBUG: Found friendly name: $friendlyName"
                $caNames += "$caId ($friendlyName)"
            } else {
                Write-Host "DEBUG: No friendly name found, using ID only"
                $caNames += $caId
            }
        }

        # Pattern 2: tls { ca ca_name }
        $matches1 = [regex]::Matches($content, 'tls\s*\{\s*ca\s+([^\s\}]+)', [System.Text.RegularExpressions.RegexOptions]::IgnoreCase)
        Write-Host "DEBUG: TLS block matches: $($matches1.Count)"
        foreach ($match in $matches1) {
            $caNames += $match.Groups[1].Value
        }

        # Pattern 3: tls ca_name (direct)
        $matches2 = [regex]::Matches($content, 'tls\s+([^\s\{]+)', [System.Text.RegularExpressions.RegexOptions]::IgnoreCase)
        Write-Host "DEBUG: Direct TLS matches: $($matches2.Count)"
        foreach ($match in $matches2) {
            $caName = $match.Groups[1].Value
            if ($caName -ne "internal" -and $caName -ne "off") {
                $caNames += $caName
            }
        }

        Write-Host "DEBUG: Total CAs found: $($caNames.Count)"
        Write-Host "DEBUG: CA list: $($caNames -join ', ')"

        # Remove duplicates and return
        return $caNames | Sort-Object | Get-Unique
    }
    catch {
        Write-Host "DEBUG: Exception in Get-CaddyfileCAs: $($_.Exception.Message)"
        Write-Host "Error reading CAs from Caddyfile: $($_.Exception.Message)"
        return @()
    }
}

# Handle get-cas command
if ($args[0] -eq "get-cas") {
    $CaddyfilePath = if ($args[1]) { $args[1] } else { "C:\caddy\Caddyfile" }
    
    Write-Host "DEBUG: get-cas command received"
    Write-Host "DEBUG: Caddyfile path: $CaddyfilePath"
    Write-Host "DEBUG: File exists: $(Test-Path $CaddyfilePath)"
    
    try {
        $cas = Get-CaddyfileCAs -CaddyfilePath $CaddyfilePath
        
        Write-Host "DEBUG: CAs found: $($cas -join ', ')"
        
        $response = @{
            status = "success"
            message = "CAs retrieved successfully"
            data = @{
                cas = $cas
                count = $cas.Count
                caddyfilePath = $CaddyfilePath
            }
            timestamp = (Get-Date).ToString("yyyy-MM-dd HH:mm:ss")
        }
        
        Write-Output ($response | ConvertTo-Json)
        exit 0
    }
    catch {
        Write-Host "DEBUG: Error occurred: $($_.Exception.Message)"
        
        $response = @{
            status = "error"
            message = "Failed to retrieve CAs: $($_.Exception.Message)"
            timestamp = (Get-Date).ToString("yyyy-MM-dd HH:mm:ss")
        }
        
        Write-Output ($response | ConvertTo-Json)
        exit 1
    }
}

# Main configuration addition logic
try {
    # Validate required parameters for config addition
    if (-not $Config -or -not $Subdomain) {
        Write-Output (Write-JsonResponse "error" "Config and Subdomain parameters are required")
        exit 1
    }

    # Check if Caddyfile exists
    if (-not (Test-Path $CaddyfilePath)) {
        Write-Output (Write-JsonResponse "error" "Caddyfile not found at: $CaddyfilePath")
        exit 1
    }

    # Read existing Caddyfile
    $existingConfig = Get-Content $CaddyfilePath -Raw -ErrorAction Stop

    # Check if subdomain already exists
    if ($existingConfig -match "$Subdomain\.sami\s*\{") {
        Write-Output (Write-JsonResponse "error" "Subdomain '$Subdomain.sami' already exists in Caddyfile")
        exit 1
    }

    # Create backup
    $backupPath = "$CaddyfilePath.backup.$(Get-Date -Format 'yyyyMMdd-HHmmss')"
    Copy-Item $CaddyfilePath $backupPath -ErrorAction Stop
    Write-Host "Backup created: $backupPath"

    # Append new configuration
    $newContent = $existingConfig.TrimEnd() + "`n`n" + $Config.TrimEnd() + "`n"
    Set-Content -Path $CaddyfilePath -Value $newContent -NoNewline -ErrorAction Stop

    Write-Host "Configuration added successfully"

    # Reload Caddy if requested
    if ($ReloadCaddy) {
        Write-Host "Reloading Caddy..."
        
        # Try to reload Caddy
        $reloadResult = & caddy reload --config $CaddyfilePath 2>&1
        
        if ($LASTEXITCODE -eq 0) {
            Write-Host "Caddy reloaded successfully"
            Write-Output (Write-JsonResponse "success" "Configuration added and Caddy reloaded successfully" @{
                backup = $backupPath
                subdomain = "$Subdomain.sami"
            })
        } else {
            Write-Host "Caddy reload failed: $reloadResult"
            # Restore backup if reload failed
            Copy-Item $backupPath $CaddyfilePath -Force
            Write-Output (Write-JsonResponse "error" "Caddy reload failed. Configuration rolled back. Error: $reloadResult")
            exit 1
        }
    } else {
        Write-Output (Write-JsonResponse "success" "Configuration added successfully (Caddy not reloaded)" @{
            backup = $backupPath
            subdomain = "$Subdomain.sami"
        })
    }

} catch {
    Write-Output (Write-JsonResponse "error" "Error: $($_.Exception.Message)")
    exit 1
}