#Requires -Version 7.4

function Get-vSEALPluginRegistry {
    <#
    .SYNOPSIS
        Discovers and registers plugins using folder-based discovery with TOML metadata.

    .DESCRIPTION
        Scans plugin roots for folders containing plugin.toml files. Each plugin folder
        must contain a plugin.toml file that defines the plugin's metadata.

        Discovery process:
        1. Scan each root (local -> shared -> built-in) for subdirectories
        2. Skip directories without plugin.toml
        3. Parse and validate plugin.toml via Import-vSEALPluginMetadata
        4. Evaluate requirements via Test-vSEALPluginRequirements
        5. Load optional plugin.ps1 script content
        6. Apply override resolution (local > shared > built-in)
        7. Detect same-root duplicates

        Status model (three-tier):
        - Valid: Plugin loaded and applicable
        - Skipped: Well-formed but requirements not met
        - Error: Malformed TOML, PS1 syntax error, or same-root duplicate

    .PARAMETER BuiltInPath
        Path to built-in plugins (required). Typically $ModuleBase/Plugins.

    .PARAMETER LocalPath
        Path to local plugins (optional). Higher priority than shared/built-in.

    .PARAMETER SharedPath
        Path to shared plugins (optional). Higher priority than built-in.

    .OUTPUTS
        [hashtable] Plugin registry keyed by plugin name. Each entry contains:
        - Name: Plugin name from TOML
        - Version: Plugin version from TOML
        - Category: Plugin category from TOML
        - Phases: Array of supported phases
        - Priority: Execution priority (lower = earlier)
        - Description: Plugin description
        - Critical: Whether plugin is critical
        - Status: Valid/Skipped/Error
        - Source: local/shared/built-in
        - PluginPath: Full path to plugin folder
        - SkipReason: Why skipped (when Status=Skipped)
        - ErrorMessage: Error details (when Status=Error)
        - ScriptContent: Content of plugin.ps1 (if exists)
        - HasScript: Boolean indicating if plugin.ps1 exists
        - Requires: Requirements hashtable from TOML

    .EXAMPLE
        $builtInPath = Join-Path $PSScriptRoot 'Plugins'
        $registry = Get-vSEALPluginRegistry -BuiltInPath $builtInPath

    .EXAMPLE
        $registry = Get-vSEALPluginRegistry -BuiltInPath $builtIn -LocalPath $local -SharedPath $shared
        $registry.Values | Where-Object { $_.Status -eq 'Valid' }

    .NOTES
        Part of Plugin Architecture v2 refactor.
        Override behavior: local plugin with same name as built-in replaces it entirely.
        Same-root duplicates: Two folders claiming same name in one root = Error on both.
    #>
    [CmdletBinding()]
    [OutputType([hashtable])]
    param(
        [Parameter(Mandatory)]
        [string]$BuiltInPath,

        [Parameter()]
        [string]$LocalPath,

        [Parameter()]
        [string]$SharedPath
    )

    $registry = @{}

    # Define search locations with source labels (order: local -> shared -> built-in for override priority)
    $locations = @(
        @{ Path = $LocalPath;   Source = 'local' }
        @{ Path = $SharedPath;  Source = 'shared' }
        @{ Path = $BuiltInPath; Source = 'built-in' }
    )

    foreach ($loc in $locations) {
        # Skip if path not provided
        if (-not $loc.Path) { continue }

        # Check if path exists
        if (-not (Test-Path -Path $loc.Path -PathType Container)) {
            Write-vSEALLog "Plugin path not found (skipping): $($loc.Path)" -Level 'DEBUG'
            continue
        }

        # Scan for plugin folders (direct subdirectories only)
        try {
            $pluginFolders = Get-ChildItem -Path $loc.Path -Directory -ErrorAction Stop
        }
        catch {
            Write-vSEALLog "Cannot access plugin path $($loc.Path): $_" -Level 'WARNING'
            continue
        }

        # Track names within this root for duplicate detection
        # Maps TOML name -> @(folder paths that claim this name)
        $rootNameTracker = @{}

        # First pass: discover all plugins in this root
        $rootPlugins = @{}

        foreach ($pluginFolder in $pluginFolders) {
            $tomlPath = Join-Path $pluginFolder.FullName 'plugin.toml'

            # Skip folders without plugin.toml (not a plugin)
            if (-not (Test-Path -Path $tomlPath -PathType Leaf)) {
                Write-vSEALLog "Skipping folder (no plugin.toml): $($pluginFolder.Name)" -Level 'DEBUG'
                continue
            }

            # Initialize plugin entry
            $status = 'Valid'
            $errorMsg = $null
            $skipReason = $null
            $scriptContent = $null
            $hasScript = $false
            $metadata = $null

            # Parse and validate TOML
            try {
                $metaResult = Import-vSEALPluginMetadata -Path $tomlPath -ValidateOnly -ExpectedFolderName $pluginFolder.Name
            }
            catch {
                # File system errors (not found, permission denied) - should not happen since we checked
                $status = 'Error'
                $errorMsg = "Failed to read plugin.toml: $($_.Exception.Message)"
                Write-vSEALLog "Plugin '$($pluginFolder.Name)' error: $errorMsg" -Level 'WARNING'

                $rootPlugins[$pluginFolder.Name] = @{
                    Name         = $pluginFolder.Name
                    Version      = $null
                    Category     = $null
                    Phases       = @()
                    Priority     = 999
                    Description  = $null
                    Critical     = $false
                    Status       = $status
                    Source       = $loc.Source
                    PluginPath   = $pluginFolder.FullName
                    SkipReason   = $null
                    ErrorMessage = $errorMsg
                    ScriptContent = $null
                    HasScript    = $false
                    Requires     = @{}
                }
                continue
            }

            # Check TOML validation result
            if (-not $metaResult.IsValid) {
                $status = 'Error'
                # Get first error message
                if ($metaResult.Errors -and $metaResult.Errors.Count -gt 0) {
                    $firstError = $metaResult.Errors[0]
                    if ($firstError -is [hashtable] -or $firstError -is [System.Collections.IDictionary]) {
                        $errorMsg = "$($firstError['Path']): $($firstError['Message'])"
                    }
                    else {
                        $errorMsg = [string]$firstError
                    }
                }
                elseif ($metaResult.Warnings -and $metaResult.Warnings.Count -gt 0) {
                    # TOML parse errors appear as warnings per CONTEXT.md
                    $errorMsg = $metaResult.Warnings[0]
                }
                else {
                    $errorMsg = "Unknown validation error"
                }

                Write-vSEALLog "Plugin '$($pluginFolder.Name)' error: $errorMsg" -Level 'WARNING'

                $rootPlugins[$pluginFolder.Name] = @{
                    Name         = $pluginFolder.Name
                    Version      = $null
                    Category     = $null
                    Phases       = @()
                    Priority     = 999
                    Description  = $null
                    Critical     = $false
                    Status       = $status
                    Source       = $loc.Source
                    PluginPath   = $pluginFolder.FullName
                    SkipReason   = $null
                    ErrorMessage = $errorMsg
                    ScriptContent = $null
                    HasScript    = $false
                    Requires     = @{}
                }
                continue
            }

            $metadata = $metaResult.Metadata
            $pluginName = $metadata.Name

            # Track name for duplicate detection within this root
            if (-not $rootNameTracker.ContainsKey($pluginName)) {
                $rootNameTracker[$pluginName] = @()
            }
            $rootNameTracker[$pluginName] += $pluginFolder.Name

            # Evaluate requirements if TOML is valid
            if ($status -eq 'Valid' -and $metadata.Requires) {
                $reqResult = Test-vSEALPluginRequirements -Requires $metadata.Requires -PluginName $pluginName

                if (-not $reqResult.Pass) {
                    $status = 'Skipped'
                    $skipReason = $reqResult.Reason
                    Write-vSEALLog "Plugin '$pluginName' skipped: $skipReason" -Level 'INFO'
                }
            }

            # Load plugin.ps1 if exists
            $ps1Path = Join-Path $pluginFolder.FullName 'plugin.ps1'
            if (Test-Path -Path $ps1Path -PathType Leaf) {
                $hasScript = $true
                try {
                    $scriptContent = Get-Content -Path $ps1Path -Raw -ErrorAction Stop

                    # Validate PS1 syntax
                    try {
                        $null = [scriptblock]::Create($scriptContent)
                    }
                    catch {
                        $status = 'Error'
                        $errorMsg = "Script syntax error: $($_.Exception.Message)"
                        $scriptContent = $null
                        Write-vSEALLog "Plugin '$pluginName' error: $errorMsg" -Level 'WARNING'
                    }
                }
                catch {
                    $status = 'Error'
                    $errorMsg = "Failed to read plugin.ps1: $($_.Exception.Message)"
                    Write-vSEALLog "Plugin '$pluginName' error: $errorMsg" -Level 'WARNING'
                }
            }

            # Build registry entry
            $rootPlugins[$pluginFolder.Name] = @{
                Name         = $pluginName
                Version      = $metadata.Version
                Category     = $metadata.Category
                Phases       = $metadata.Phases
                Priority     = $metadata.Priority
                Description  = $metadata.Description
                Critical     = $metadata.Critical
                Status       = $status
                Source       = $loc.Source
                PluginPath   = $pluginFolder.FullName
                SkipReason   = $skipReason
                ErrorMessage = $errorMsg
                ScriptContent = $scriptContent
                HasScript    = $hasScript
                Requires     = $metadata.Requires
            }

            Write-vSEALLog "Discovered plugin: $pluginName [$($loc.Source)]" -Level 'DEBUG'
        }

        # Second pass: detect same-root duplicates
        foreach ($nameEntry in $rootNameTracker.GetEnumerator()) {
            if ($nameEntry.Value.Count -gt 1) {
                # Multiple folders claim the same TOML name - mark all as Error
                $folders = $nameEntry.Value -join '/, '
                $duplicateError = "Duplicate plugin ID '$($nameEntry.Key)' in same root: $folders/"

                foreach ($folderName in $nameEntry.Value) {
                    if ($rootPlugins.ContainsKey($folderName)) {
                        $rootPlugins[$folderName].Status = 'Error'
                        $rootPlugins[$folderName].ErrorMessage = $duplicateError
                        Write-vSEALLog "Plugin '$folderName' error: $duplicateError" -Level 'WARNING'
                    }
                }
            }
        }

        # Third pass: apply to main registry with override resolution
        foreach ($entry in $rootPlugins.Values) {
            $pluginName = $entry.Name

            # Check for override (plugin already registered from higher-priority source)
            if ($registry.ContainsKey($pluginName)) {
                $existingSource = $registry[$pluginName].Source
                Write-vSEALLog "Plugin '$pluginName' from $existingSource overrides $($loc.Source)" -Level 'INFO'
                continue  # Skip - higher priority source already registered
            }

            # Register plugin
            $registry[$pluginName] = $entry
            Write-vSEALLog "Registered plugin: $pluginName [$($loc.Source)]" -Level 'DEBUG'
        }
    }

    return $registry
}
