scripts/modules/prerequisites/python/install-python.ps1

# strangeloop Setup - Python Installation Module
# Version: 1.0.0


param(
    [switch]$WSLMode,
    [switch]${test-only},
    [switch]${what-if}
)

# Import shared modules
$SharedPath = Split-Path (Split-Path $PSScriptRoot -Parent) -Parent | Join-Path -ChildPath "shared"
. "$SharedPath\write-functions.ps1"
. "$SharedPath\test-functions.ps1"

function Test-PythonWindows {
    param(
        
    )
    
    try {
        {
            Write-Info "Testing Python installation (Windows)..."
        }
        
        # Check if Python is installed
        if (-not (Test-Command "python")) {
            {
                Write-Warning "Python command not found"
            }
            return $false
        }
        
        # Check Python version
        $pythonVersion = python --version 2>$null
        if (-not $pythonVersion -or -not ($pythonVersion -match "Python 3\.")) {
            {
                Write-Warning "Python 3 not found or invalid version: $pythonVersion"
            }
            return $false
        }
        
        # Check pip
        if (-not (Test-Command "pip")) {
            {
                Write-Warning "pip not found"
            }
            return $false
        }
        
        {
            Write-Success "Python is properly installed: $pythonVersion"
        }
        return $true
        
    } catch {
        {
            Write-Warning "Error testing Python: $($_.Exception.Message)"
        }
        return $false
    }
}

function Test-PythonWSL {
    param(
        
    )
    
    try {
        {
            Write-Info "Testing Python installation (WSL)..."
        }
        
        # Check if WSL is available
        if (-not (Test-Command "wsl")) {
            {
                Write-Warning "WSL not available"
            }
            return $false
        }
        
        # Check Python in WSL
        $wslPythonTest = wsl python3 --version 2>$null
        if (-not $wslPythonTest -or -not ($wslPythonTest -match "Python 3\.")) {
            {
                Write-Warning "Python 3 not found in WSL"
            }
            return $false
        }
        
        # Check pip in WSL
        $wslPipTest = wsl python3 -m pip --version 2>$null
        if (-not $wslPipTest) {
            {
                Write-Warning "pip not found in WSL"
            }
            return $false
        }
        
        {
            Write-Success "Python is properly installed in WSL: $wslPythonTest"
        }
        return $true
        
    } catch {
        {
            Write-Warning "Error testing Python in WSL: $($_.Exception.Message)"
        }
        return $false
    }
}

function Install-Python {
    param(
        [switch]$WSLMode,
        [switch]${test-only},
        [switch]${what-if}
    )
    
    # If test-only mode, just test current installation
    if (${test-only}) {
        if ($WSLMode) {
            return Test-PythonWSL
        } else {
            return Test-PythonWindows
        }
    }
    
    # If what-if mode, show what would be done
    if (${what-if}) {
        if ($WSLMode) {
            Write-Host "what if: Would install Python in WSL environment" -ForegroundColor Yellow
            Write-Host "what if: Would update package lists with 'apt update'" -ForegroundColor Yellow
            Write-Host "what if: Would install Python 3 and pip via 'apt install python3 python3-pip'" -ForegroundColor Yellow
        } else {
            Write-Host "what if: Would install Python on Windows" -ForegroundColor Yellow
            Write-Host "what if: Would download Python installer from python.org" -ForegroundColor Yellow
            Write-Host "what if: Would install Python with silent installation and add to PATH" -ForegroundColor Yellow
            Write-Host "what if: Would verify Python and pip installation" -ForegroundColor Yellow
        }
        return $true
    }
    
    if ($WSLMode) {
        Install-PythonWSL
    } else {
        Install-PythonWindows
    }
}

function Install-PythonWindows {
    param(
    )
    
    Write-Step "Installing Python (Windows)..."
    
    try {
        # Check if Python is already installed
        if (Test-Command "python") {
            $pythonVersion = python --version 2>$null
            if ($pythonVersion -and $pythonVersion -match "Python 3\.") {
                Write-Success "Python is already installed: $pythonVersion"
                return Install-PipWindows
            }
        }
        
        $installChoice = Read-UserPrompt -Prompt "Python not found. Install Python 3?" -ValidValues @("y","n")
        if (-not (Test-YesResponse $installChoice)) {
            Write-Warning "Skipping Python installation"
            return $false
        }
        
        Write-Progress "Installing Python 3..."
        
        # Try different installation methods
        $installSuccess = $false
        
        # Method 1: Try winget (recommended)
        if (Test-Command "winget") {
            try {
                Write-Info "Installing Python via winget..."
                winget install Python.Python.3.12 --accept-package-agreements --accept-source-agreements --silent
                if ($LASTEXITCODE -eq 0) {
                    $installSuccess = $true
                    Write-Success "Python installed via winget"
                }
            } catch {
                Write-Warning "winget installation failed: $($_.Exception.Message)"
            }
        }
        
        # Method 2: Try chocolatey if winget failed
        if (-not $installSuccess -and (Test-Command "choco")) {
            try {
                Write-Info "Installing Python via chocolatey..."
                choco install python3 -y
                if ($LASTEXITCODE -eq 0) {
                    $installSuccess = $true
                    Write-Success "Python installed via chocolatey"
                }
            } catch {
                Write-Warning "Chocolatey installation failed: $($_.Exception.Message)"
            }
        }
        
        # Method 3: Microsoft Store version (fallback)
        if (-not $installSuccess) {
            Write-Info "Please install Python from the Microsoft Store or python.org"
            Write-Info "Microsoft Store: ms-windows-store://pdp/?productid=9NCVDN91XZQP"
            Write-Info "Python.org: https://www.python.org/downloads/"
            return $false
        }
        
        if ($installSuccess) {
            # Refresh PATH
            $env:PATH = [System.Environment]::GetEnvironmentVariable("PATH", "Machine") + ";" + [System.Environment]::GetEnvironmentVariable("PATH", "User")
            
            # Install pip if needed
            return Install-PipWindows
        }
        
        return $false
        
    } catch {
        Write-Error "Python installation failed: $($_.Exception.Message)"
        return $false
    }
}

function Install-PythonWSL {
    param(
    )
    
    Write-Step "Installing Python (WSL)..."
    
    try {
        # Check for WSL
        if (-not (Test-Command "wsl")) {
            Write-Error "WSL is not available. Please install WSL first."
            return $false
        }
        
        # Get default WSL distribution
        $defaultDistro = wsl -l -q | Select-Object -First 1
        if (-not $defaultDistro) {
            Write-Error "No WSL distribution found"
            return $false
        }
        
        Write-Info "Installing Python in WSL distribution: $defaultDistro"
        
        # Update package lists
        Write-Progress "Updating package lists..."
        wsl -d $defaultDistro -- sudo apt update -qq
        
        # Install Python and pip
        Write-Progress "Installing Python 3 and pip..."
        wsl -d $defaultDistro -- sudo apt install -y python3 python3-pip python3-venv python3-dev
        
        # Verify installation
        $pythonVersion = wsl -d $defaultDistro -- python3 --version 2>$null
        if ($pythonVersion) {
            Write-Success "Python installed in WSL: $pythonVersion"
            
            # Install pipx
            Write-Progress "Installing pipx..."
            wsl -d $defaultDistro -- python3 -m pip install --user pipx
            wsl -d $defaultDistro -- pipx ensurepath
            
            Write-Success "Python and pipx installation completed in WSL"
            return $true
        } else {
            Write-Error "Python installation verification failed in WSL"
            return $false
        }
        
    } catch {
        Write-Error "Python WSL installation failed: $($_.Exception.Message)"
        return $false
    }
}

function Install-PipWindows {
    param(
    )
    
    Write-Step "Installing pip and pipx (Windows)..."
    
    try {
        # Check if pip is available
        if (Test-Command "pip") {
            Write-Success "pip is already available"
        } else {
            Write-Info "Installing pip..."
            python -m ensurepip --upgrade
        }
        
        # Check if pipx is available
        if (Test-Command "pipx") {
            Write-Success "pipx is already available"
        } else {
            Write-Info "Installing pipx..."
            python -m pip install --user pipx
            python -m pipx ensurepath
        }
        
        # Refresh PATH
        $env:PATH = [System.Environment]::GetEnvironmentVariable("PATH", "Machine") + ";" + [System.Environment]::GetEnvironmentVariable("PATH", "User")
        
        Write-Success "pip and pipx installation completed"
        return $true
        
    } catch {
        Write-Error "pip/pipx installation failed: $($_.Exception.Message)"
        return $false
    }
}

# Main execution
if ($MyInvocation.InvocationName -ne '.') {
    $result = Install-Python -WSLMode:$WSLMode -test-only:${test-only} -what-if:${what-if}
    
    if ($result) {
        if (${test-only}) {
            Write-Success "Python test completed successfully"
        } else {
            Write-Success "Python installation completed successfully"
        }
        exit 0
    } else {
        if (${test-only}) {
            Write-Error "Python test failed"
        } else {
            Write-Error "Python installation failed"
        }
        exit 1
    }
}

# Export functions for module usage
if ($MyInvocation.MyCommand.ModuleName) {
    Export-ModuleMember -Function @(
        'Install-Python',
        'Install-PythonWindows',
        'Install-PythonWSL',
        'Install-PipWindows'
    )
}