#Requires -Version 7.4

function Test-FrameworkSchema {
    <#
    .SYNOPSIS
    Validates framework configuration sections against expected schema.

    .DESCRIPTION
    Validates the [vseal], [logging], and [storage] sections of the configuration
    against expected types and allowed values. Collects all validation errors and
    throws a single exception with all failures listed.

    .PARAMETER Config
    The configuration object (OrderedDictionary) returned from Import-vSEALConfiguration.

    .EXAMPLE
    Test-FrameworkSchema -Config $config

    .NOTES
    - PSToml returns OrderedDictionary, not Hashtable
    - TOML integers are Int64 (long), not Int32 (int) - check both types
    - Use Contains() for field presence checks (works for both OrderedDictionary and Hashtable)
    - Error messages include full field path (e.g., "logging.console_level")
    #>
    [CmdletBinding()]
    param(
        [Parameter(Mandatory)]
        [System.Collections.Specialized.OrderedDictionary]$Config
    )

    $errors = @()
    $validLevels = @('DEBUG', 'VERBOSE', 'INFO', 'SUCCESS', 'WARNING', 'ERROR', 'FATAL')

    # Validate [vseal] section
    if ($Config.Contains('vseal') -and $null -ne $Config.vseal) {
        # default_plugin_timeout must be integer >= 0
        if ($Config.vseal.Contains('default_plugin_timeout') -and $null -ne $Config.vseal.default_plugin_timeout) {
            $value = $Config.vseal.default_plugin_timeout
            if ($value -isnot [int] -and $value -isnot [long]) {
                $errors += "vseal.default_plugin_timeout: expected integer >= 0, got $($value.GetType().Name) ($value)"
            }
            elseif ($value -lt 0) {
                $errors += "vseal.default_plugin_timeout: must be >= 0, got $value"
            }
        }
    }

    # Validate [logging] section
    if ($Config.Contains('logging') -and $null -ne $Config.logging) {
        # console_level must be valid log level
        if ($Config.logging.Contains('console_level') -and $null -ne $Config.logging.console_level) {
            $value = $Config.logging.console_level
            if ($value -notin $validLevels) {
                $errors += "logging.console_level: expected one of [$($validLevels -join ', ')], got '$value'"
            }
        }

        # file_level must be valid log level
        if ($Config.logging.Contains('file_level') -and $null -ne $Config.logging.file_level) {
            $value = $Config.logging.file_level
            if ($value -notin $validLevels) {
                $errors += "logging.file_level: expected one of [$($validLevels -join ', ')], got '$value'"
            }
        }

        # console_context must be valid option
        if ($Config.logging.Contains('console_context') -and $null -ne $Config.logging.console_context) {
            $value = $Config.logging.console_context
            $validOptions = @('auto', 'always', 'never')
            if ($value -notin $validOptions) {
                $errors += "logging.console_context: expected one of [$($validOptions -join ', ')], got '$value'"
            }
        }

        # log_path must be string (if present)
        if ($Config.logging.Contains('log_path') -and $null -ne $Config.logging.log_path) {
            $value = $Config.logging.log_path
            if ($value -isnot [string]) {
                $errors += "logging.log_path: expected string, got $($value.GetType().Name) ($value)"
            }
        }
    }

    # Validate [storage] section
    if ($Config.Contains('storage') -and $null -ne $Config.storage) {
        # persistent_disk must be string (if present)
        if ($Config.storage.Contains('persistent_disk') -and $null -ne $Config.storage.persistent_disk) {
            $value = $Config.storage.persistent_disk
            if ($value -isnot [string]) {
                $errors += "storage.persistent_disk: expected string, got $($value.GetType().Name) ($value)"
            }
        }
    }

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