#Requires -Version 7.4

function Test-PluginSchema {
    <#
    .SYNOPSIS
    Validates a plugin's configuration section against its declared schema.

    .DESCRIPTION
    Validates that all required fields are present and that field types match
    the expected types from the plugin's Get-PluginConfigSchema. Collects all
    validation errors and throws a single exception with all failures listed.

    .PARAMETER PluginConfig
    The plugin's configuration section (hashtable).

    .PARAMETER Schema
    The schema returned by the plugin's Get-PluginConfigSchema (hashtable with
    Type, Default, Required, Description per field).

    .PARAMETER PluginPath
    The full path to the plugin for error messages (e.g., "defender").

    .EXAMPLE
    Test-PluginSchema -PluginConfig $config -Schema $schema -PluginPath "defender"

    .NOTES
    - PluginConfig is hashtable (converted from OrderedDictionary subsection)
    - TOML integers are Int64 (long), not Int32 (int) - check both types
    - Use Contains() for field presence checks (works for both OrderedDictionary and Hashtable)
    - Skip 'enabled' field (framework handles this, not plugin schema)
    - Error messages include full field path (e.g., "defender.timeout")
    #>
    [CmdletBinding()]
    param(
        [Parameter(Mandatory)]
        [hashtable]$PluginConfig,

        [Parameter(Mandatory)]
        [hashtable]$Schema,

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

    $errors = @()

    # Validate each field in the schema
    foreach ($fieldName in $Schema.Keys) {
        $fieldSchema = $Schema[$fieldName]

        # Skip 'enabled' - framework handles this
        if ($fieldName -eq 'enabled') {
            continue
        }

        # Check if required field is missing
        if ($fieldSchema.Required -and -not $PluginConfig.Contains($fieldName)) {
            $errors += "${PluginPath}.${fieldName}: required field missing"
            continue
        }

        # If field not present and not required, skip validation
        if (-not $PluginConfig.Contains($fieldName)) {
            continue
        }

        $actualValue = $PluginConfig[$fieldName]

        # Validate type
        $expectedType = $fieldSchema.Type
        $isValid = switch ($expectedType) {
            'string'   { $actualValue -is [string] }
            'int'      { $actualValue -is [int] -or $actualValue -is [long] }
            'bool'     { $actualValue -is [bool] }
            'string[]' {
                $actualValue -is [array] -and ($actualValue | ForEach-Object { $_ -is [string] }) -notcontains $false
            }
            default    { $true }  # Unknown type, skip validation
        }

        if (-not $isValid) {
            $actualType = if ($actualValue -is [array]) {
                if ($actualValue.Count -gt 0) {
                    "array of $($actualValue[0].GetType().Name)"
                } else {
                    "empty array"
                }
            } else {
                $actualValue.GetType().Name
            }
            $errors += "${PluginPath}.${fieldName}: expected $expectedType, got $actualType ($actualValue)"
        }
    }

    if ($errors.Count -gt 0) {
        $errorMessage = "Plugin configuration validation failed:`n" + ($errors -join "`n")
        throw $errorMessage
    }
}
