#Requires -Version 7.4
# ============================================================================
# Example Hybrid Plugin - TOML template with custom PowerShell logic
# ============================================================================
#
# This plugin demonstrates the HYBRID pattern:
#   - Seal/Engage phases: Use TOML template via Invoke-vSEALActionGroup
#   - Rollback phase: Custom PowerShell with validation + core rollback
#
# WHEN TO USE HYBRID PATTERN:
#   - Seal/Engage actions are standard (registry, service, command)
#   - Rollback needs validation (safety checks before restoring)
#   - You want template simplicity but need customization points
#
# KEY CONCEPTS:
#   1. Import-vSEALTemplate loads the TOML template
#   2. Invoke-vSEALActionGroup processes groups with conditions
#   3. Custom Invoke-Rollback wraps Invoke-vSEALCoreRollback with validation
#
# DOMAIN: Security Configuration (mock settings)
# ============================================================================

#region Helper Functions

# ----------------------------------------------------------------------------
# HELPER: Check if a mock setting is safe to rollback
# ----------------------------------------------------------------------------
# In a real plugin, this would check:
#   - Is the change reversible?
#   - Does the user have permission?
#   - Is the system in a state where rollback is safe?
#   - Are there dependencies that need to be rolled back first?
# ----------------------------------------------------------------------------
function Test-SafeToRollback {
    param(
        [Parameter(Mandatory)]
        $Entry
    )

    # Mock validation logic - in real plugin, would check actual conditions
    # For demo purposes, we'll consider all entries safe
    # A real plugin might check:
    #   - Registry paths in system-critical locations
    #   - Services that other services depend on
    #   - Tasks with running instances

    Write-vSEALLog "Validating rollback safety: $($Entry.Target) ($($Entry.Type))" -Level VERBOSE

    # Example of a validation check (always passes in mock):
    # Reject if target contains "Critical" (demonstrates validation pattern)
    if ($Entry.Target -match 'Critical') {
        Write-vSEALLog "MOCK: Would reject critical path: $($Entry.Target)" -Level DEBUG
        # In demo, we still return true - real plugin would return false
    }

    return $true
}

# ----------------------------------------------------------------------------
# HELPER: Read current security settings (mock implementation)
# ----------------------------------------------------------------------------
# In a real plugin, this would query actual system state:
#   - Read registry values
#   - Check service configurations
#   - Query scheduled task states
# For mock, we simulate expected vs current mismatches.
# ----------------------------------------------------------------------------
function Get-CurrentSecuritySettings {
    param(
        [Parameter()]
        [hashtable]$ExpectedSettings
    )

    # Mock current state - in real plugin, would read actual system values
    # We simulate some settings matching and some needing changes

    $mockCurrent = @(
        @{
            Setting  = 'HKLM:\SOFTWARE\vSEAL\Mock\Security\TelemetryEnabled'
            Current  = 1        # Mock: Currently enabled
            Expected = 0        # Template expects: Disabled
            Action   = 'Set'
            NeedsChange = $true
        }
        @{
            Setting  = 'HKLM:\SOFTWARE\vSEAL\Mock\Security\FirewallProfile'
            Current  = 'Public'    # Mock: Currently Public
            Expected = 'Domain'    # Template expects: Domain
            Action   = 'Set'
            NeedsChange = $true
        }
        @{
            Setting  = 'HKLM:\SOFTWARE\vSEAL\Mock\Security\AuditLevel'
            Current  = 3           # Mock: Already at expected value
            Expected = 3           # Template expects: Same
            Action   = 'None'
            NeedsChange = $false
        }
        @{
            Setting  = 'MockSecurityService'
            Type     = 'Service'
            Current  = 'Automatic' # Mock: Currently Automatic
            Expected = 'Disabled'  # Template expects: Disabled
            Action   = 'SetStartMode'
            NeedsChange = $true
        }
    )

    return $mockCurrent
}

# ----------------------------------------------------------------------------
# HELPER: Summarize analysis results
# ----------------------------------------------------------------------------
function Get-AnalysisSummary {
    param(
        [Parameter(Mandatory)]
        [array]$Details
    )

    $needsChange = ($Details | Where-Object { $_.NeedsChange -eq $true }).Count
    $compliant = ($Details | Where-Object { $_.NeedsChange -eq $false }).Count
    $total = $Details.Count

    if ($needsChange -eq 0) {
        return "All $total settings compliant"
    } else {
        return "$needsChange of $total settings need changes"
    }
}

#endregion

#region Plugin Contract Functions

# ============================================================================
# CONFIG SCHEMA: Declares expected configuration options
# ============================================================================
function Get-PluginConfigSchema {
    @{
        enable_strict_validation = @{
            Type        = 'bool'
            Default     = $false
            Required    = $false
            Description = 'Enable strict validation in rollback (reject critical paths)'
        }
        analysis_detail_level = @{
            Type        = 'string'
            Default     = 'standard'
            Required    = $false
            Description = 'Analysis detail level: minimal, standard, verbose'
        }
    }
}

# ============================================================================
# APPLICABILITY: Check if plugin should run
# ============================================================================
function Test-Applicable {
    param($Globals)

    # Mock: Always applicable for demonstration
    # Real plugin would check for specific OS features, installed components, etc.

    return @{ Applicable = $true; Reason = $null }
}

# ============================================================================
# PLANNED ACTIONS: Preview what the plugin will do
# ============================================================================
function Get-PlannedActions {
    param($Config, $Globals, $Phase)

    $actions = @()

    switch ($Phase) {
        'Seal' {
            $actions += 'Disable mock telemetry (registry)'
            $actions += 'Configure mock firewall profile (registry)'
            $actions += 'Set mock audit level (registry)'
            $actions += 'Disable mock security service'
        }
        'Engage' {
            $actions += 'Enable mock telemetry (registry)'
            $actions += 'Start mock security service'
        }
    }

    return $actions
}

# ============================================================================
# INVOKE-SEAL: Uses TOML template for standard declarative execution
# ============================================================================
# This is the hybrid pattern in action:
#   1. Load TOML template using Import-vSEALTemplate
#   2. Execute each group using Invoke-vSEALActionGroup
#   3. Template handles condition evaluation, baseline capture, etc.
#
# WHY USE TEMPLATE FOR SEAL:
#   - Registry/service actions are standard and well-defined
#   - TOML is more maintainable than PowerShell for configuration lists
#   - Automatic baseline capture via group processor
#   - Condition evaluation handled declaratively
# ============================================================================
function Invoke-Seal {
    param($Config, $Globals)

    Write-vSEALLog "Starting hybrid plugin Seal phase (TOML template)"

    # Get the template path (same directory as this script)
    # Use $script:PluginScriptRoot which is set by the orchestrator (ThreadJob doesn't set $PSScriptRoot)
    $templatePath = Join-Path $script:PluginScriptRoot 'hybrid.toml'

    # Load and validate the template
    Write-vSEALLog "Loading template: $templatePath" -Level DEBUG
    $template = Import-vSEALTemplate -Path $templatePath

    if (-not $template.IsValid) {
        Write-vSEALLog "Template validation failed" -Level ERROR
        foreach ($error in $template.Errors) {
            Write-vSEALLog "  $($error.Message)" -Level ERROR
        }
        throw "Template validation failed for example-hybrid"
    }

    Write-vSEALLog "Template loaded: $($template.Metadata.Name) v$($template.Metadata.Version)"

    # Execute each group using the group processor
    # The group processor handles:
    #   - Condition evaluation (skip groups that don't apply)
    #   - Action dispatch to appropriate executors
    #   - Baseline capture for successful actions
    #   - Error handling per on_error strategy
    foreach ($group in $template.Groups) {
        Write-vSEALLog "Processing group: $($group.name)"

        $result = Invoke-vSEALActionGroup -Group $group -Phase 'Seal' `
            -PluginId 'example-hybrid' -Globals $Globals

        # Log group results
        Write-vSEALLog "  Status: $($result.Status), Succeeded: $($result.Succeeded), Failed: $($result.Failed), Skipped: $($result.Skipped)" -Level DEBUG
    }

    Write-vSEALLog "Seal phase complete"
}

# ============================================================================
# INVOKE-ENGAGE: Uses TOML template for engage phase
# ============================================================================
# Note: In this example, we don't have engage-specific groups in the template.
# The template is designed for Seal actions. For Engage, we could:
#   1. Have separate [[groups]] with phase conditions
#   2. Use the same template but filter by group name
#   3. Log that no engage actions are needed
#
# This demonstrates that hybrid plugins can be flexible about which phases
# use templates vs custom logic.
# ============================================================================
function Invoke-Engage {
    param($Config, $Globals)

    Write-vSEALLog "Starting hybrid plugin Engage phase"

    # For this example, we don't have engage-specific template groups
    # A real plugin might:
    #   - Have [[groups]] with conditions that only pass during Engage
    #   - Use a separate engage.toml template
    #   - Have custom Engage logic like the imperative pattern

    Write-vSEALLog "No template-based engage actions defined for this example"
    Write-vSEALLog "In production, plugin would have engage groups or custom logic"

    # Demonstrate that we could still use vARC executors directly if needed
    Write-vSEALLog "Mock: Would restore security settings here"
}

# ============================================================================
# INVOKE-ROLLBACK: Custom rollback with validation
# ============================================================================
# This is WHERE HYBRID SHINES:
#   - Receive baseline entries from orchestrator
#   - VALIDATE each entry before rollback (safety checks)
#   - Use Invoke-vSEALCoreRollback for safe entries
#   - Skip with warning for unsafe entries
#
# PARAMETERS:
#   $Entries  - Array of baseline entries (Type, Target, OriginalValue)
#   $PluginId - Plugin identifier for logging (e.g., "example-hybrid")
#
# WHY CUSTOM ROLLBACK:
#   - Add validation before restoring (e.g., check dependencies)
#   - Filter out entries that shouldn't be rolled back
#   - Add custom logging or user confirmation
#   - Handle special cases that core rollback can't
#
# CORE ROLLBACK FUNCTION:
#   Invoke-vSEALCoreRollback handles the actual restoration:
#   - Registry: Restores original value or deletes if didn't exist
#   - Service: Restores original start mode
#   - Task: Restores original enabled/disabled state
#   - Command: Executes rollback_command if specified
# ============================================================================
function Invoke-Rollback {
    param(
        [Parameter(Mandatory)]
        [AllowEmptyCollection()]
        [array]$Entries,

        [Parameter(Mandatory)]
        [string]$PluginId
    )

    Write-vSEALLog "Starting hybrid plugin Rollback phase (custom validation)"
    Write-vSEALLog "Received $($Entries.Count) entries to rollback" -Level DEBUG

    if ($Entries.Count -eq 0) {
        Write-vSEALLog "No entries to rollback"
        return @{
            Total    = 0
            Restored = 0
            Failed   = 0
            Skipped  = 0
            Errors   = @()
        }
    }

    # Track safe and unsafe entries
    $safeEntries = @()
    $unsafeEntries = @()

    # STEP 1: Validate each entry before rollback
    Write-vSEALLog "Validating $($Entries.Count) entries for rollback safety..."

    foreach ($entry in $Entries) {
        if (Test-SafeToRollback -Entry $entry) {
            $safeEntries += $entry
            Write-vSEALLog "  [SAFE] $($entry.Target)" -Level VERBOSE
        } else {
            $unsafeEntries += $entry
            Write-vSEALLog "  [UNSAFE] $($entry.Target) - will skip" -Level WARNING
        }
    }

    Write-vSEALLog "Validation complete: $($safeEntries.Count) safe, $($unsafeEntries.Count) unsafe"

    # STEP 2: Report unsafe entries (don't rollback them)
    foreach ($unsafe in $unsafeEntries) {
        Write-vSEALLog "Skipping unsafe entry: $($unsafe.Target)" -Level WARNING
    }

    # STEP 3: Delegate safe entries to core rollback
    # Invoke-vSEALCoreRollback handles:
    #   - LIFO order (last applied = first rolled back)
    #   - Type-specific rollback (registry, service, task, command)
    #   - Error handling with best-effort semantics
    #   - Result aggregation
    if ($safeEntries.Count -gt 0) {
        Write-vSEALLog "Delegating $($safeEntries.Count) safe entries to core rollback"
        $coreResult = Invoke-vSEALCoreRollback -Entries $safeEntries -PluginId $PluginId

        Write-vSEALLog "Core rollback complete: Restored=$($coreResult.Restored), Failed=$($coreResult.Failed)"

        # Combine results
        return @{
            Total    = $Entries.Count
            Restored = $coreResult.Restored
            Failed   = $coreResult.Failed
            Skipped  = $unsafeEntries.Count + $coreResult.Skipped
            Errors   = $coreResult.Errors
        }
    } else {
        Write-vSEALLog "No safe entries to rollback"
        return @{
            Total    = $Entries.Count
            Restored = 0
            Failed   = 0
            Skipped  = $unsafeEntries.Count
            Errors   = @()
        }
    }
}

#endregion

# ============================================================================
# SUMMARY: Hybrid Plugin Pattern
# ============================================================================
# Files:
#   - plugin.ps1 (this file) - Custom logic for Rollback
#   - hybrid.toml - TOML template for Seal phase actions
#
# Pattern benefits:
#   - TOML template: Maintainable, declarative, auto-baseline
#   - Custom Rollback: Safety validation, filtered restoration
#
# When to use:
#   - Standard actions (registry, service, task) for Seal/Engage
#   - Need validation/filtering for Rollback
#   - Want best of both worlds: template simplicity + custom power
# ============================================================================
