#Requires -Version 7.4

function Invoke-vSEALPrerequisiteChecks {
    <#
    .SYNOPSIS
        Orchestrates all vSEAL prerequisite checks.

    .DESCRIPTION
        Auto-discovers and executes all Test-*Prerequisite.ps1 files in the Prerequisites
        directory. Collects results and throws a consolidated error if any checks fail.

    .EXAMPLE
        Invoke-vSEALPrerequisiteChecks

        Runs all prerequisite checks. Throws if any fail.

    .OUTPUTS
        None on success. Throws [System.InvalidOperationException] on failure.
    #>
    [CmdletBinding()]
    [OutputType([void])]
    param()

    # Determine the Prerequisites directory path relative to this script
    $prerequisitesPath = Join-Path -Path $PSScriptRoot -ChildPath 'Prerequisites'

    if (-not (Test-Path -Path $prerequisitesPath -PathType Container)) {
        throw [System.IO.DirectoryNotFoundException]::new(
            "Prerequisites directory not found at: $prerequisitesPath"
        )
    }

    # Auto-discover all Test-*Prerequisite.ps1 files
    $prerequisiteFiles = Get-ChildItem -Path $prerequisitesPath -Filter 'Test-*Prerequisite.ps1' -File -ErrorAction Stop

    if ($prerequisiteFiles.Count -eq 0) {
        Write-vSEALLog 'No prerequisite check files found in Prerequisites directory.' -Level 'WARNING'
        return
    }

    # Collection for results
    $results = [System.Collections.Generic.List[PSCustomObject]]::new()
    $failedChecks = [System.Collections.Generic.List[PSCustomObject]]::new()

    foreach ($file in $prerequisiteFiles) {
        try {
            # Dot-source the prerequisite file to load its function
            . $file.FullName

            # Extract function name from filename (Test-PSVersionPrerequisite.ps1 -> Test-PSVersionPrerequisite)
            $functionName = [System.IO.Path]::GetFileNameWithoutExtension($file.Name)

            # Verify the function exists after dot-sourcing
            if (-not (Get-Command -Name $functionName -ErrorAction SilentlyContinue)) {
                throw "Function '$functionName' not found after loading '$($file.Name)'"
            }

            # Execute the prerequisite check
            $result = & $functionName

            # Validate result structure
            if ($null -eq $result) {
                throw "Prerequisite check '$functionName' returned null"
            }

            # Ensure result has required properties
            $requiredProperties = @('Name', 'Passed', 'Message', 'Required', 'Current')
            foreach ($prop in $requiredProperties) {
                if (-not ($result.PSObject.Properties.Name -contains $prop)) {
                    throw "Prerequisite check '$functionName' result missing required property: $prop"
                }
            }

            $results.Add($result)

            if (-not $result.Passed) {
                $failedChecks.Add($result)
            }
        }
        catch {
            # Create a failure result for checks that error during execution
            $errorResult = [PSCustomObject]@{
                Name     = $file.BaseName
                Passed   = $false
                Message  = "Check failed with error: $($_.Exception.Message)"
                Required = 'Check must execute without errors'
                Current  = 'Error during execution'
                HelpUrl  = $null
            }
            $results.Add($errorResult)
            $failedChecks.Add($errorResult)
        }
    }

    # If any checks failed, build and throw consolidated error
    if ($failedChecks.Count -gt 0) {
        $errorMessages = [System.Collections.Generic.List[string]]::new()

        foreach ($failed in $failedChecks) {
            $errorLine = "[$($failed.Name)] $($failed.Message)"

            # Add help URL if available
            if (-not [string]::IsNullOrWhiteSpace($failed.HelpUrl)) {
                $errorLine += " See: $($failed.HelpUrl)"
            }

            $errorMessages.Add($errorLine)
        }

        $consolidatedMessage = $errorMessages -join [System.Environment]::NewLine

        throw [System.InvalidOperationException]::new($consolidatedMessage)
    }

    # All checks passed - output verbose confirmation
    Write-vSEALLog "All $($results.Count) prerequisite checks passed." -Level 'VERBOSE'
}
