Private/PathOptimizer.ps1

function Get-PathPriority {
    <#
    .SYNOPSIS
        Determines the priority category of a PATH entry.
    .DESCRIPTION
        Returns a numeric priority (lower = higher priority) based on path type.
    #>

    [CmdletBinding()]
    param(
        [Parameter(Mandatory)]
        [string]$Path
    )

    $normalizedPath = $Path.ToLowerInvariant().TrimEnd('\')

    # Priority 1: Windows System Critical
    if ($normalizedPath -match '^c:\\windows\\system32$' -or
        $normalizedPath -match '^c:\\windows\\system32\\wbem$' -or
        $normalizedPath -match '^c:\\windows\\system32\\openssh$' -or
        $normalizedPath -match '^c:\\windows\\system32\\windowspowershell') {
        return @{ Priority = 10; Category = 'System Critical' }
    }

    # Priority 2: Windows Core
    if ($normalizedPath -match '^c:\\windows$') {
        return @{ Priority = 20; Category = 'Windows Core' }
    }

    # Priority 3: PowerShell 7+
    if ($normalizedPath -match 'powershell\\7') {
        return @{ Priority = 30; Category = 'PowerShell 7' }
    }

    # Priority 4: Development Tools (Git, VS Code, etc.)
    if ($normalizedPath -match '\\git\\' -or
        $normalizedPath -match 'vs code' -or
        $normalizedPath -match 'visual studio' -or
        $normalizedPath -match '\\dotnet\\?' -or
        $normalizedPath -match 'github cli') {
        return @{ Priority = 40; Category = 'Development Tools' }
    }

    # Priority 5: Language Runtimes (user-preferred versions first)
    if ($normalizedPath -match 'python' -or
        $normalizedPath -match 'node' -or
        $normalizedPath -match '\\go\\' -or
        $normalizedPath -match 'java' -or
        $normalizedPath -match 'rust' -or
        $normalizedPath -match 'ruby' -or
        $normalizedPath -match '\\nvm' -or
        $normalizedPath -match 'cargo') {
        # User-local installations get higher priority than system-wide
        if ($normalizedPath -match 'appdata|users\\[^\\]+\\') {
            return @{ Priority = 50; Category = 'Language Runtime (User)' }
        }
        return @{ Priority = 55; Category = 'Language Runtime (System)' }
    }

    # Priority 6: Package Managers
    if ($normalizedPath -match 'chocolatey' -or
        $normalizedPath -match 'scoop' -or
        $normalizedPath -match 'winget' -or
        $normalizedPath -match 'npm' -or
        $normalizedPath -match 'yarn') {
        return @{ Priority = 60; Category = 'Package Manager' }
    }

    # Priority 7: SDK and Database Tools
    if ($normalizedPath -match 'sql server' -or
        $normalizedPath -match 'docker' -or
        $normalizedPath -match 'kubernetes' -or
        $normalizedPath -match 'azure' -or
        $normalizedPath -match 'aws') {
        return @{ Priority = 70; Category = 'SDK/Cloud Tools' }
    }

    # Priority 8: Security Tools
    if ($normalizedPath -match 'gpg' -or
        $normalizedPath -match 'gnupg' -or
        $normalizedPath -match 'openssh' -or
        $normalizedPath -match 'putty' -or
        $normalizedPath -match 'ssh') {
        return @{ Priority = 80; Category = 'Security Tools' }
    }

    # Priority 9: Application-specific (Program Files)
    if ($normalizedPath -match '^c:\\program files') {
        return @{ Priority = 90; Category = 'Application (System)' }
    }

    # Priority 10: User AppData applications
    if ($normalizedPath -match 'appdata') {
        return @{ Priority = 100; Category = 'Application (User)' }
    }

    # Priority 11: Other system paths
    if ($normalizedPath -match '^c:\\programdata') {
        return @{ Priority = 110; Category = 'ProgramData' }
    }

    # Priority 12: Everything else
    return @{ Priority = 999; Category = 'Other' }
}

function Get-OptimizedPathOrder {
    <#
    .SYNOPSIS
        Analyzes PATH entries and suggests an optimized order.
    .DESCRIPTION
        Returns PATH entries sorted by priority category, keeping relative
        order within categories to minimize disruption.
    #>

    [CmdletBinding()]
    param(
        [Parameter(Mandatory)]
        [string[]]$Paths,
        
        [switch]$ShowCategories
    )

    $categorizedPaths = @()
    $position = 0

    foreach ($path in $Paths) {
        $priority = Get-PathPriority -Path $path
        $categorizedPaths += [PSCustomObject]@{
            OriginalPosition = $position
            Path             = $path
            Priority         = $priority.Priority
            Category         = $priority.Category
        }
        $position++
    }

    # Sort by priority, then by original position within same priority
    $sorted = $categorizedPaths | Sort-Object Priority, OriginalPosition

    if ($ShowCategories) {
        return $sorted
    }

    return $sorted | Select-Object -ExpandProperty Path
}

function Compare-PathOrder {
    <#
    .SYNOPSIS
        Compares current PATH order with optimized order.
    #>

    [CmdletBinding()]
    param(
        [Parameter(Mandatory)]
        [string[]]$CurrentPaths,
        
        [Parameter(Mandatory)]
        [string[]]$OptimizedPaths
    )

    $changes = @()
    
    for ($i = 0; $i -lt $OptimizedPaths.Count; $i++) {
        $currentIndex = [array]::IndexOf($CurrentPaths, $OptimizedPaths[$i])
        if ($currentIndex -ne $i) {
            $changes += [PSCustomObject]@{
                Path            = $OptimizedPaths[$i]
                CurrentPosition = $currentIndex + 1
                NewPosition     = $i + 1
                Movement        = if ($currentIndex -gt $i) { '↑ Up' } else { '↓ Down' }
            }
        }
    }

    return $changes
}