internal/functions/schema/Resolve-SldgForeignKeyOrder.ps1

function Resolve-SldgForeignKeyOrder {
    <#
    .SYNOPSIS
        Determines the correct table insertion order based on foreign key dependencies.
    .DESCRIPTION
        Uses Kahn's topological sort algorithm. Tables with no dependencies come first.
        Self-referencing FKs are ignored. Circular dependencies are detected and appended at the end.
    #>

    [CmdletBinding()]
    param (
        [Parameter(Mandatory)]
        [object[]]$Tables
    )

    $tableMap = @{}
    $graph = @{}      # table -> list of dependents (tables that reference this one)
    $inDegree = @{}   # table -> number of tables it depends on

    # Initialize
    foreach ($table in $Tables) {
        $fullName = $table.FullName
        $tableMap[$fullName] = $table
        if (-not $graph.ContainsKey($fullName)) { $graph[$fullName] = [System.Collections.Generic.List[string]]::new() }
        if (-not $inDegree.ContainsKey($fullName)) { $inDegree[$fullName] = 0 }
    }

    # Build dependency graph
    foreach ($table in $Tables) {
        $fullName = $table.FullName
        $uniqueDeps = $table.ForeignKeys |
            Where-Object { "$($_.ReferencedSchema).$($_.ReferencedTable)" -ne $fullName } |
            ForEach-Object { "$($_.ReferencedSchema).$($_.ReferencedTable)" } |
            Select-Object -Unique

        foreach ($dep in $uniqueDeps) {
            if ($tableMap.ContainsKey($dep)) {
                # dep must come before fullName
                $graph[$dep].Add($fullName)
                $inDegree[$fullName]++
            }
        }
    }

    # Kahn's algorithm
    $queue = [System.Collections.Generic.Queue[string]]::new()
    foreach ($name in $inDegree.Keys) {
        if ($inDegree[$name] -eq 0) { $queue.Enqueue($name) }
    }

    $sorted = [System.Collections.Generic.List[object]]::new()
    while ($queue.Count -gt 0) {
        $current = $queue.Dequeue()
        $sorted.Add($tableMap[$current])

        foreach ($dependent in $graph[$current]) {
            $inDegree[$dependent]--
            if ($inDegree[$dependent] -eq 0) { $queue.Enqueue($dependent) }
        }
    }

    # Handle circular dependencies — flag tables so consumers can disable FK constraints
    if ($sorted.Count -lt $Tables.Count) {
        $remaining = $Tables | Where-Object { $_.FullName -notin @($sorted | ForEach-Object { $_.FullName }) }
        Write-PSFMessage -Level Warning -Message ($script:strings.'Generation.CyclicDependency' -f ($remaining.FullName -join ', '))
        foreach ($table in $remaining) {
            $table.HasCircularDependency = $true
            $sorted.Add($table)
        }
    }

    Write-PSFMessage -Level Verbose -Message ($script:strings.'Generation.TableOrder' -f ($sorted.FullName -join ' -> '))
    $sorted.ToArray()
}