#Requires -Version 7.4

# Script-scoped baseline context for entry accumulation during Seal execution
$script:vSEALBaselineContext = $null

function Add-vSEALBaselineEntry {
    <#
    .SYNOPSIS
        Adds a baseline entry for tracking changes during Seal execution.

    .DESCRIPTION
        Accumulates baseline entries in a script-scoped collection during Seal phase.
        Each entry records the original and applied values for a system resource,
        enabling rollback during Engage phase.

        Entries are keyed by PluginId (e.g., "defender") and include type,
        target, values, and optional metadata.

    .PARAMETER PluginId
        The plugin identifier (folder name, e.g., "defender").

    .PARAMETER Type
        The type of resource being modified: Registry, Service, Task, Command, or Custom.

    .PARAMETER Target
        The resource identifier (e.g., registry path, service name, task path).

    .PARAMETER OriginalValue
        The value before modification. Can be $null if resource didn't exist.

    .PARAMETER AppliedValue
        The value after modification.

    .PARAMETER DidNotExist
        Switch indicating the resource didn't exist before this operation.

    .PARAMETER Metadata
        Optional hashtable with additional fields (e.g., ValueType for registry).

    .EXAMPLE
        Add-vSEALBaselineEntry -PluginId 'defender' -Type Service -Target 'WinDefend' `
            -OriginalValue @{ StartMode = 'Automatic'; Status = 'Running' } `
            -AppliedValue @{ StartMode = 'Disabled'; Status = 'Stopped' }

        Records a service modification for rollback.

    .EXAMPLE
        Add-vSEALBaselineEntry -PluginId 'pagefile' -Type Registry `
            -Target 'HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management\PagingFiles' `
            -OriginalValue $null -AppliedValue @() -DidNotExist `
            -Metadata @{ ValueType = 'MultiString' }

        Records a registry creation with metadata.

    .OUTPUTS
        [void]
    #>
    [CmdletBinding()]
    [OutputType([void])]
    param(
        [Parameter(Mandatory)]
        [ValidateNotNullOrEmpty()]
        [string]$PluginId,

        [Parameter(Mandatory)]
        [ValidateSet('Registry', 'Service', 'Task', 'Command', 'Custom')]
        [string]$Type,

        [Parameter(Mandatory)]
        [ValidateNotNullOrEmpty()]
        [string]$Target,

        [Parameter()]
        $OriginalValue,

        [Parameter()]
        $AppliedValue,

        [Parameter()]
        [switch]$DidNotExist,

        [Parameter()]
        [hashtable]$Metadata
    )

    # Check for active context
    if ($null -eq $script:vSEALBaselineContext) {
        throw "No active baseline context. This function must be called during Seal phase execution."
    }

    # Type-specific field validation
    $missingFields = [System.Collections.Generic.List[string]]::new()

    switch ($Type) {
        'Service' {
            if ($null -eq $OriginalValue -or $OriginalValue -isnot [hashtable]) {
                $missingFields.Add('OriginalValue (must be hashtable)')
            } else {
                if ([string]::IsNullOrWhiteSpace($OriginalValue.StartMode)) {
                    $missingFields.Add('OriginalValue.StartMode')
                }
            }
        }
        'Command' {
            if ($null -eq $OriginalValue -or $OriginalValue -isnot [hashtable]) {
                $missingFields.Add('OriginalValue (must be hashtable)')
            }
            # RollbackCommand is optional — many commands are one-way operations
        }
        'Task' {
            if ($null -eq $OriginalValue -or $OriginalValue -isnot [hashtable]) {
                $missingFields.Add('OriginalValue (must be hashtable)')
            } else {
                if ([string]::IsNullOrWhiteSpace($OriginalValue.State)) {
                    $missingFields.Add('OriginalValue.State')
                }
            }
        }
        'Registry' {
            if (-not $DidNotExist.IsPresent) {
                if ($null -eq $OriginalValue -or $OriginalValue -isnot [hashtable]) {
                    $missingFields.Add('OriginalValue (must be hashtable)')
                }
            }
        }
        # Custom: no validation -- intentional catch-all type
    }

    if ($missingFields.Count -gt 0) {
        $msg = "Add-vSEALBaselineEntry: $Type entry '$Target' missing required fields: $($missingFields -join ', ')"
        Write-vSEALLog $msg -Level WARNING
        throw $msg
    }

    # Build the entry
    $entry = @{
        Type          = $Type
        Target        = $Target
        OriginalValue = $OriginalValue
        AppliedValue  = $AppliedValue
        DidNotExist   = $DidNotExist.IsPresent
        Timestamp     = (Get-Date).ToUniversalTime().ToString('o')
    }

    # Merge metadata if provided
    if ($null -ne $Metadata) {
        foreach ($key in $Metadata.Keys) {
            $entry[$key] = $Metadata[$key]
        }
    }

    # Initialize plugin array if needed
    if (-not $script:vSEALBaselineContext.ContainsKey($PluginId)) {
        $script:vSEALBaselineContext[$PluginId] = @()
    }

    # Append entry (use += to handle array append correctly)
    $script:vSEALBaselineContext[$PluginId] += $entry

    Write-vSEALLog "Baseline entry added: $PluginId - $Type - $Target" -Level DEBUG
}
