#---------------------------------------------------------------------------------------------
#  Copyright (c) Microsoft Corporation. All rights reserved.
#---------------------------------------------------------------------------------------------

# Windows GitHub Copilot CLI bootstrapper
#
# Responsibilities:
#   1. Locate the real Copilot CLI binary (avoid recursion if this file shadows it).
#   2. Offer to install if missing (npm -g @github/copilot).
#   3. Enforce minimum version (>= REQUIRED_VERSION) with interactive update.
#   4. Execute the real binary with original arguments and exit with its status.
#
# NOTE: This file intentionally keeps logic self‑contained (no external deps) so it can be dropped into PATH directly.

# Minimum required Copilot CLI version
$RequiredVersion = "0.0.394"
$PackageName = "@github/copilot"

function Invoke-NpmGlobalCommand {
    param(
        [Parameter(Mandatory = $true)][ValidateSet('install', 'update')][string]$Command,
        [Parameter(Mandatory = $true)][string]$Package
    )

    $npmArgs = @($Command, '-g', $Package)

    $npmCmd = Get-Command npm.cmd -ErrorAction SilentlyContinue
    if ($npmCmd) {
        & npm.cmd @npmArgs
    } else {
        & npm @npmArgs
    }
}

function Find-RealCopilot {
    # Find the real copilot binary, avoiding this script if it's in PATH
    $CurrentScript = $MyInvocation.PSCommandPath
    if (-not $CurrentScript) { $CurrentScript = $PSCommandPath }
    $CopilotPath = (Get-Command copilot -ErrorAction SilentlyContinue).Source

    # Check if the copilot command would point to this script
    $CurrentScriptResolved = if ($CurrentScript) { (Resolve-Path $CurrentScript -ErrorAction SilentlyContinue).Path } else { $null }
    $CopilotPathResolved = if ($CopilotPath) { (Resolve-Path $CopilotPath -ErrorAction SilentlyContinue).Path } else { $null }

    if ($CurrentScript -eq $CopilotPath -or (Split-Path $CurrentScript -Parent) -eq (Split-Path $CopilotPath -Parent) -or ($CurrentScriptResolved -and $CopilotPathResolved -and $CurrentScriptResolved -eq $CopilotPathResolved)) {
        # The copilot in PATH is this script, find the real one by temporarily removing this script's directory from PATH
        $ScriptDir = Split-Path $CurrentScript -Parent
        $OldPath = $env:PATH
        # Use appropriate path delimiter based on OS
        $PathDelimiter = if ($IsWindows -or $env:OS -eq "Windows_NT") { ';' } else { ':' }
        $env:PATH = ($env:PATH -split $PathDelimiter | Where-Object { $_ -ne $ScriptDir }) -join $PathDelimiter
        $RealCopilot = (Get-Command copilot -ErrorAction SilentlyContinue).Source
        $env:PATH = $OldPath

        if ($RealCopilot -and (Test-Path $RealCopilot)) {
            return $RealCopilot
        } else {
            return $null
        }
    } else {
        # The copilot in PATH is different from this script, use it
        if ($CopilotPath -and (Test-Path $CopilotPath)) {
            return $CopilotPath
        } else {
            return $null
        }
    }
}

function Test-VersionCompatibility {
    param([string]$Version)
    $cleanInstalled = $Version -replace '^v',''
    $cleanRequired = $RequiredVersion -replace '^v',''
    try {
        $installedVer = [version]$cleanInstalled
        $requiredVer = [version]$cleanRequired
    } catch {
        return $false
    }
    return ($installedVer -ge $requiredVer)
}

function Test-AndLaunchCopilot {
    param([string[]]$Arguments)

    # Check if real copilot command exists
    $realCopilot = Find-RealCopilot
    if (-not $realCopilot) {
        Write-Host "Cannot find GitHub Copilot CLI (https://docs.github.com/en/copilot/how-tos/set-up/install-copilot-cli)"
        $answer = Read-Host "Install GitHub Copilot CLI? (y/N)"
        if ($answer -eq "y" -or $answer -eq "Y") {
            try {
                Invoke-NpmGlobalCommand -Command 'install' -Package $PackageName
                if ($LASTEXITCODE -eq 0) {
                    Test-AndLaunchCopilot $Arguments
                    return
                } else {
                    Read-Host "Installation failed. Please check your npm configuration and try again (or run: npm install -g @github/copilot)."
                    return
                }
            } catch {
                Read-Host "Installation failed. Please check your npm configuration and try again (or run: npm install -g @github/copilot)."
                return
            }
        } else {
            exit 0
        }
    }

    # Check version compatibility
    $realCopilot = Find-RealCopilot
    if (-not $realCopilot) {
        Write-Host "Error: Unable to find copilot binary."
        $answer = Read-Host "Would you like to reinstall GitHub Copilot CLI? (y/N)"
        if ($answer -eq "y" -or $answer -eq "Y") {
            Write-Host "Reinstalling GitHub Copilot CLI..."
            try {
                Invoke-NpmGlobalCommand -Command 'install' -Package $PackageName
                if ($LASTEXITCODE -eq 0) {
                    Test-AndLaunchCopilot $Arguments
                    return
                } else {
                    Read-Host "Reinstallation failed. Please check your npm configuration and try again (or run: npm install -g @github/copilot)."
                    return
                }
            } catch {
                Read-Host "Reinstallation failed. Please check your npm configuration and try again (or run: npm install -g @github/copilot)."
                return
            }
        } else {
            exit 0
        }
    }

    try {
        $versionOutput = & $realCopilot --version 2>$null
        if ($LASTEXITCODE -ne 0) {
            throw "Command failed"
        }
    } catch {
        # Write-Host "Error: Unable to check copilot version."
        $answer = Read-Host "Would you like to reinstall GitHub Copilot CLI? (y/N)"
        if ($answer -eq "y" -or $answer -eq "Y") {
            try {
                Invoke-NpmGlobalCommand -Command 'install' -Package $PackageName
                if ($LASTEXITCODE -eq 0) {
                    Test-AndLaunchCopilot $Arguments
                    return
                } else {
                    Read-Host "Reinstallation failed. Please check your npm configuration and try again (or run: npm install -g @github/copilot)."
                    return
                }
            } catch {
                Read-Host "Reinstallation failed. Please check your npm configuration and try again (or run: npm install -g @github/copilot)."
                return
            }
        } else {
            exit 0
        }
    }

    # Extract version number from output (search through all lines)
    $version = $null
    if ($versionOutput) {
        foreach ($line in ($versionOutput -split "`n")) {
            $trimmedLine = $line.Trim()
            if ($trimmedLine -match '[0-9]+\.[0-9]+\.[0-9]+') {
                $version = $matches[0]
                break
            }
        }
    }

    # Command succeeded - assume CLI is installed even if we can't parse the version

    # Only check version compatibility if we have a valid version
    if ($version -and -not (Test-VersionCompatibility $version)) {
        Write-Host "GitHub Copilot CLI version $version is not compatible."
        Write-Host "Version $RequiredVersion or later is required."
        $answer = Read-Host "Update GitHub Copilot CLI? (y/N)"
        if ($answer -eq "y" -or $answer -eq "Y") {
            try {
                Invoke-NpmGlobalCommand -Command 'update' -Package $PackageName
                if ($LASTEXITCODE -eq 0) {
                    Test-AndLaunchCopilot $Arguments
                    return
                } else {
                    Read-Host "Update failed. Please check your npm configuration and try again (or run: npm update -g @github/copilot)."
                    return
                }
            } catch {
                Read-Host "Update failed. Please check your npm configuration and try again (or run: npm update -g @github/copilot)."
                return
            }
        } else {
            exit 0
        }
    }

    # All checks passed, execute the real copilot binary
    $realCopilot = Find-RealCopilot
    if ($realCopilot -and (Test-Path $realCopilot)) {
        & $realCopilot @Arguments
    } else {
        Write-Host "Error: Could not find the real GitHub Copilot CLI binary"
        Read-Host "Please ensure it's properly installed with: npm install -g @github/copilot"
        return
    }
}

# Start the check and launch process
$finalArgs = $args
# Handle --clear argument
if ($args.Length -gt 0 -and $args[0] -eq '--clear') {
    Clear-Host
    $finalArgs = $args[1..($args.Length - 1)]
}

Test-AndLaunchCopilot $finalArgs