borg.ps1

# borg.ps1 — Safe launcher, compatible with Windows PowerShell 5.1
function _InvokeBorgEntry {
    # Parse raw tokens (no named params on purpose)
    [string]$module = $null
    [string]$command = $null
    [string[]]$extraArgs = @()

    if ($args.Count -ge 1) { $module = $args[0] }
    if ($args.Count -ge 2) { $command = $args[1] }
    if ($args.Count -ge 3) { $extraArgs = $args[2..($args.Count - 1)] }

    # --- Runtime prerequisite checks (early exit on legacy PS) ---
    if ($PSVersionTable.PSVersion.Major -lt 7) {
        Write-Warning "BORG requires PowerShell 7.5.1 or later."

        Write-Host ""
        Write-Host "You are currently running: PowerShell $($PSVersionTable.PSVersion)"
        Write-Host ""
        Write-Host "To use BORG properly, please do one of the following:"
        Write-Host " • Type 'pwsh' in this terminal to switch to PowerShell 7"
        Write-Host " • OR configure your terminal to launch PowerShell 7 by default"
        Write-Host ""
        Write-Host "If PowerShell 7 is not yet installed, you can run this command:"
        Write-Host " winget install --id Microsoft.PowerShell -e"
        Write-Host ""
        Write-Host "After installing, start a new terminal or type 'pwsh' to re-enter."
        exit 1
    }

    if (-not (Get-Command fzf -ErrorAction SilentlyContinue)) {
        Write-Warning "`fzf` is not installed. Run 'winget install fzf'."
        exit 1
    }

    if (-not (Get-Command micro -ErrorAction SilentlyContinue)) {
        Write-Warning "`micro` editor is missing. Run 'winget install micro'."
        exit 1
    }

    if (-not (Get-Command docker -ErrorAction SilentlyContinue)) {
        Write-Warning "Docker is not installed or not in PATH. Visit https://www.docker.com/products/docker-desktop to install it."
        exit 1
    }

    try {
        docker info --format '{{.ServerVersion}}' | Out-Null
    }
    catch {
        Write-Warning "Docker daemon does not appear to be running. Start Docker Desktop and try again."
        exit 1
    }

    # --- Self version info ---
    if ($args -contains '--version' -or $args -contains '-v') {
        $moduleName = 'Borg'
        $installed = (Get-Module $moduleName -ListAvailable | Sort-Object Version -Descending | Select-Object -First 1).Version
        $latest = (Find-Module $moduleName -ErrorAction SilentlyContinue).Version

        Write-Host "`n BORG Version Info" -ForegroundColor Cyan
        Write-Host " • Installed: v$installed"
        if ($latest -and $latest -ne $installed) {
            Write-Host " • Latest: v$latest " -ForegroundColor Yellow
            Write-Host "`nRun 'borg update' to get the latest version."
        }
        else {
            Write-Host " • Latest: v$latest "
        }
        exit
    }

    # --- Self update shortcut ---
    if ($args.Count -eq 1 -and $args[0] -eq 'update') {
        Write-Host "`n Updating BORG module from PowerShell Gallery..." -ForegroundColor Cyan
        try {
            Update-Module -Name Borg -Force -Scope CurrentUser -ErrorAction Stop
            Write-Host " Update complete. Please restart your terminal to use the new version." -ForegroundColor Green
        }
        catch {
            Write-Host " Update failed: $_" -ForegroundColor Red
        }
        exit
    }

    # ===== Alias resolver (fixed) =====
    function Resolve-BorgAlias {
        param([Parameter(Mandatory)][string[]]$Tokens)

        $map = @{
            # Two-word combos FIRST (highest precedence)
            "b gl" = "git log"
            "b gs" = "git status"
            "b b"  = "bookmark"   # legacy muscle-memory: `b b` == `bookmark`
            
            # One-word aliases
            "b"     = "bookmark"
            "db"    = "docker bash"
            "dr"    = "docker restore"
            "dq"    = "docker query"
            "dc"    = "docker clean"
            "dl"    = "docker download"
            "du"    = "docker upload"
            "ds"    = "docker switch"
            "dsnap" = "docker snapshot"
            "ne"     = "network"
            "js"    = "jump store"
            "iofc"  = "io folder-clean"
            "ssd"   = "sys shutdown"
            "sr"    = "sys restart"
            "gs"    = "git status"
            "gl"    = "git log"
            "n"     = "note"
        }

        # Normalize (trim & drop empties)
        $Tokens = @($Tokens | Where-Object { $_ -ne $null } | ForEach-Object { $_.ToString().Trim() }) 
        if ($Tokens.Count -eq 0) { return @() }

        $twoKey = if ($Tokens.Count -ge 2) { ("{0} {1}" -f $Tokens[0], $Tokens[1]).ToLower() } else { "" }
        $oneKey = $Tokens[0].ToLower()

        # Remainders
        $rest2  = if ($Tokens.Count -gt 2) { $Tokens[2..($Tokens.Count-1)] } else { @() }
        $rest1  = if ($Tokens.Count -gt 1) { $Tokens[1..($Tokens.Count-1)] } else { @() }

        if ($twoKey -and $map.ContainsKey($twoKey)) {
            $repl = $map[$twoKey] -split ' '
            return $repl + $rest2
        }
        if ($map.ContainsKey($oneKey)) {
            $repl = $map[$oneKey] -split ' '
            return $repl + $rest1
        }
        return $Tokens
    }

    # Build full token list from what the user typed
    $tokens = @()
    if ($module)    { $tokens += $module }
    if ($command)   { $tokens += $command }
    if ($extraArgs) { $tokens += $extraArgs }

    # Resolve aliases
    $resolved = Resolve-BorgAlias -Tokens $tokens
    # Re-trim in case a mapping produced spaces (paranoia)
    $resolved = @($resolved | ForEach-Object { $_.ToString().Trim() } | Where-Object { $_ -ne "" })

    # Re-split into module / command / extraArgs
    $module    = if ($resolved.Count -ge 1) { $resolved[0] } else { $null }
    $command   = if ($resolved.Count -ge 2) { $resolved[1] } else { $null }
    $extraArgs = if ($resolved.Count -gt 2) { $resolved[2..($resolved.Count - 1)] } else { @() }

    # Hand off to main entry
    . "$PSScriptRoot\entry.ps1" -module $module -command $command -extraArgs $extraArgs
}

# Invoke with the original raw args
_InvokeBorgEntry @args