scripts/modules/wsl/initialize-wsl.ps1

# strangeloop Setup - WSL Management Module
# Version: 1.0.0


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

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

function Test-WSLAvailable {
    <#
    .SYNOPSIS
    Tests if WSL (Windows Subsystem for Linux) is available and enabled
    
    .DESCRIPTION
    Checks if WSL is installed and enabled on the Windows system
    
        
    .OUTPUTS
    Boolean indicating WSL availability
    #>

    param(
        
    )
    
    try {
        {
            Write-Info "Checking WSL availability..."
        }
        
        # Check if wsl.exe exists and is accessible
        $wslCommand = Get-Command wsl.exe -ErrorAction SilentlyContinue
        if (-not $wslCommand) {
            {
                Write-Warning "WSL command not found"
            }
            return $false
        }
        
        # Test WSL is working
        $wslTest = & wsl.exe --status 2>&1
        if ($LASTEXITCODE -ne 0) {
            {
                Write-Warning "WSL is not properly configured: $wslTest"
            }
            return $false
        }
        
        {
            Write-Success "WSL is available and working"
        }
        return $true
        
    } catch {
        {
            Write-Warning "Error checking WSL: $($_.Exception.Message)"
        }
        return $false
    }
}

function Get-WSLDistributions {
    <#
    .SYNOPSIS
    Gets list of installed WSL distributions
    
    .DESCRIPTION
    Returns information about all installed WSL distributions
    
        
    .OUTPUTS
    Array of PSCustomObject with distribution information
    #>

    param(
        
    )
    
    try {
        {
            Write-Info "Getting WSL distributions..."
        }
        
        # Use wsl --list for simpler, more reliable parsing
        $wslList = & wsl.exe --list 2>&1
        if ($LASTEXITCODE -ne 0) {
            {
                Write-Warning "Failed to get WSL distributions: $wslList"
            }
            return @()
        }
        
        # Also get detailed status with --list --verbose for state information
        $wslListVerbose = & wsl.exe --list --verbose 2>&1 | Out-String
        
        $distributions = @()
        $lines = $wslList -split "`r?`n" | Where-Object { $_.Trim() -ne '' }
        
        # Process each line that contains distribution names
        foreach ($line in $lines) {
            $trimmedLine = $line.Trim()
            
            # Skip header line
            if ($trimmedLine -match '^Windows Subsystem for Linux Distributions:') {
                continue
            }
            
            # Handle distribution format: "Ubuntu-24.04 (Default)" or just "Ubuntu"
            if ($trimmedLine -match '^([^\s]+(?:-[^\s]+)*)\s*(\(Default\))?') {
                $distroName = $matches[1]
                $isDefault = $null -ne $matches[2]
                
                # Try to get state from verbose output
                $state = "Unknown"
                $version = "2"  # Default to version 2
                
                if ($wslListVerbose -match "$distroName\s+(Running|Stopped)\s+(\d+)") {
                    $state = $matches[1]
                    $version = $matches[2]
                }
                
                $distributions += [PSCustomObject]@{
                    Name = $distroName
                    State = $state
                    Version = $version
                    IsDefault = $isDefault
                }
            }
        }
        
        {
            Write-Info "Found $($distributions.Count) WSL distributions"
        }
        
        return $distributions
        
    } catch {
        {
            Write-Warning "Error getting WSL distributions: $($_.Exception.Message)"
        }
        return @()
    }
}

function Install-WSLDistribution {
    <#
    .SYNOPSIS
    Installs a WSL distribution
    
    .DESCRIPTION
    Installs the specified WSL distribution from the Microsoft Store
    
    .PARAMETER DistributionName
    Name of the distribution to install (e.g., 'Ubuntu', 'Ubuntu-20.04')
    
    .PARAMETER what-if
    Shows what would be done without actually performing the actions
    
    .OUTPUTS
    Boolean indicating success
    #>

    param(
        [Parameter(Mandatory)]
        [string]$DistributionName,
        [switch]${what-if}
    )
    
    try {
        if (${what-if}) {
            Write-Host "what if: Would check if WSL distribution '$DistributionName' already exists" -ForegroundColor Yellow
            Write-Host "what if: Would install WSL distribution '$DistributionName' using 'wsl --install -d $DistributionName'" -ForegroundColor Yellow
            return $true
        }
        {
            Write-Info "Installing WSL distribution: $DistributionName"
        }
        
        # Check if distribution already exists
        $existingDistros = Get-WSLDistributions
        $existing = $existingDistros | Where-Object { $_.Name -eq $DistributionName }
        
        if ($existing) {
            {
                Write-Info "Distribution '$DistributionName' already exists"
            }
            return $true
        }
        
        # Install distribution
        {
            Write-Progress "Installing $DistributionName via WSL..."
        }
        
        $installResult = & wsl.exe --install -d $DistributionName 2>&1
        if ($LASTEXITCODE -ne 0) {
            {
                Write-Warning "Failed to install $DistributionName`: $installResult"
            }
            return $false
        }
        
        {
            Write-Success "$DistributionName installed successfully"
        }
        return $true
        
    } catch {
        {
            Write-Warning "Error installing WSL distribution: $($_.Exception.Message)"
        }
        return $false
    }
}

function Enable-WSL {
    <#
    .SYNOPSIS
    Enables WSL feature on Windows
    
    .DESCRIPTION
    Enables the Windows Subsystem for Linux feature and Virtual Machine Platform
    
        
    .OUTPUTS
    Boolean indicating success
    #>

    param()
    
    try {
        {
            Write-Info "Enabling WSL feature..."
        }
        
        # Check if already enabled
        $wslAvailable = Test-WSLAvailable:$true
        if ($wslAvailable) {
            {
                Write-Info "WSL is already enabled"
            }
            return $true
        }
        
        # Check if running as administrator
        $isAdmin = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")
        if (-not $isAdmin) {
            {
                Write-Error "Administrator privileges required to enable WSL"
            }
            return $false
        }
        
        {
            Write-Progress "Enabling Windows Subsystem for Linux..."
        }
        
        # Enable WSL feature
        $result1 = Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux -All -NoRestart
        if (-not $result1.RestartNeeded) {
            {
                Write-Warning "Failed to enable WSL feature"
            }
            return $false
        }
        
        # Enable Virtual Machine Platform
        {
            Write-Progress "Enabling Virtual Machine Platform..."
        }
        
        $result2 = Enable-WindowsOptionalFeature -Online -FeatureName VirtualMachinePlatform -All -NoRestart
        
        $restartRequired = $result1.RestartNeeded -or $result2.RestartNeeded
        
        if ($restartRequired) {
            {
                Write-Warning "System restart required to complete WSL installation"
                Write-Info "Please restart your computer and run the setup again"
            }
            return $false
        }
        
        {
            Write-Success "WSL enabled successfully"
        }
        return $true
        
    } catch {
        {
            Write-Warning "Error enabling WSL: $($_.Exception.Message)"
        }
        return $false
    }
}

function Set-WSLDefaultVersion {
    <#
    .SYNOPSIS
    Sets the default WSL version
    
    .DESCRIPTION
    Sets the default version for new WSL distributions (1 or 2)
    
    .PARAMETER Version
    WSL version to set as default (1 or 2)
    
        
    .OUTPUTS
    Boolean indicating success
    #>

    param(
        [Parameter(Mandatory)]
        [ValidateSet("1", "2")]
        [string]$Version
    )
    
    try {
        {
            Write-Info "Setting WSL default version to $Version"
        }
        
        $result = & wsl.exe --set-default-version $Version 2>&1
        if ($LASTEXITCODE -ne 0) {
            {
                Write-Warning "Failed to set WSL default version: $result"
            }
            return $false
        }
        
        {
            Write-Success "WSL default version set to $Version"
        }
        return $true
        
    } catch {
        {
            Write-Warning "Error setting WSL default version: $($_.Exception.Message)"
        }
        return $false
    }
}

function Initialize-WSLEnvironment {
    <#
    .SYNOPSIS
    Initializes WSL environment for strangeloop development
    
    .DESCRIPTION
    Sets up WSL with recommended settings and installs a Ubuntu distribution
    
    .PARAMETER DistributionName
    Name of the Ubuntu distribution to install (default: Ubuntu)
    
    .PARAMETER test-only
    Only test current setup without making changes
    
    .PARAMETER what-if
    Shows what would be done without actually performing the actions
    
    .OUTPUTS
    Boolean indicating success
    #>

    param(
        [string]$DistributionName = "Ubuntu",
        [switch]${test-only},
        [switch]${what-if}
    )
    
    try {
        {
            Write-Step "Initializing WSL Environment..."
        }
        
        if (${what-if}) {
            Write-Host "what if: Would test if WSL is available" -ForegroundColor Yellow
            Write-Host "what if: Would enable WSL if not available" -ForegroundColor Yellow
            Write-Host "what if: Would set WSL default version to 2" -ForegroundColor Yellow
            Write-Host "what if: Would check for existing WSL distributions" -ForegroundColor Yellow
            Write-Host "what if: Would install Ubuntu distribution '$DistributionName' if not present" -ForegroundColor Yellow
            Write-Host "what if: Would set '$DistributionName' as default WSL distribution" -ForegroundColor Yellow
            return $true
        }
        
        # Test if WSL is available
        $wslAvailable = Test-WSLAvailable
        
        if (-not $wslAvailable -and ${test-only}) {
            {
                Write-Warning "WSL is not available"
            }
            return $false
        }
        
        # Enable WSL if not available
        if (-not $wslAvailable -and -not ${test-only}) {
            $enableResult = Enable-WSL
            if (-not $enableResult) {
                return $false
            }
        }
        
        # Set default version to 2
        if (-not ${test-only}) {
            $versionResult = Set-WSLDefaultVersion -Version "2"
            if (-not $versionResult) {
                {
                    Write-Warning "Failed to set WSL default version, continuing..."
                }
            }
        }
        
        # Check for existing distributions
        $distributions = Get-WSLDistributions
        $targetDistro = $distributions | Where-Object { $_.Name -eq $DistributionName }
        
        # Also check for any Ubuntu-like distribution if we're looking for Ubuntu
        if (-not $targetDistro -and $DistributionName -eq "Ubuntu") {
            $ubuntuDistro = $distributions | Where-Object { $_.Name -like "Ubuntu*" }
            if ($ubuntuDistro) {
                {
                    Write-Info "Found existing Ubuntu distribution: $($ubuntuDistro[0].Name)"
                }
                $targetDistro = $ubuntuDistro[0]
            }
        }
        
        if (-not $targetDistro -and -not ${test-only}) {
            # Install Ubuntu distribution
            $installResult = Install-WSLDistribution -DistributionName $DistributionName -what-if:${what-if}
            if (-not $installResult) {
                return $false
            }
            
            # Set the newly installed distribution as default
            if (${what-if}) {
                Write-Host "what if: Would set '$DistributionName' as default WSL distribution" -ForegroundColor Yellow
            } else {
                {
                    Write-Progress "Setting $DistributionName as default WSL distribution..."
                }
                try {
                    $setDefaultResult = & wsl.exe --set-default $DistributionName 2>&1
                    if ($LASTEXITCODE -eq 0) {
                        {
                            Write-Success "$DistributionName set as default WSL distribution"
                        }
                    } else {
                        {
                            Write-Warning "Failed to set $DistributionName as default: $setDefaultResult"
                        }
                    }
                } catch {
                    {
                        Write-Warning "Error setting default WSL distribution: $($_.Exception.Message)"
                    }
                }
            }
        } elseif ($targetDistro) {
            Write-Success "WSL distribution '$($targetDistro.Name)' is already available"
            
            # Check if it's already the default, if not offer to set it
            $currentDefault = & wsl.exe --status | Select-String "Default Distribution" | ForEach-Object { $_.ToString().Split(':')[1].Trim() }
            if ($currentDefault -and $currentDefault -ne $targetDistro.Name) {
                {
                    Write-Info "Current default WSL distribution: $currentDefault"
                    Write-Info "Available distribution: $($targetDistro.Name)"
                }
                
                if (-not ${test-only}) {
                    if (${what-if}) {
                        Write-Host "what if: Would set '$($targetDistro.Name)' as default WSL distribution" -ForegroundColor Yellow
                    } else {
                        {
                            Write-Progress "Setting $($targetDistro.Name) as default WSL distribution..."
                        }
                        try {
                            $setDefaultResult = & wsl.exe --set-default $targetDistro.Name 2>&1
                            if ($LASTEXITCODE -eq 0) {
                                {
                                    Write-Success "$($targetDistro.Name) set as default WSL distribution"
                                }
                            } else {
                                {
                                    Write-Warning "Failed to set $($targetDistro.Name) as default: $setDefaultResult"
                                }
                            }
                        } catch {
                            {
                                Write-Warning "Error setting default WSL distribution: $($_.Exception.Message)"
                            }
                        }
                    }
                }
            } elseif ($currentDefault -eq $targetDistro.Name) {
                {
                    Write-Success "$($targetDistro.Name) is already the default WSL distribution"
                }
            }
        }
        
        {
            if (${test-only}) {
                Write-Success "WSL environment test completed"
            } else {
                Write-Success "WSL environment initialized successfully"
            }
        }
        
        return $true
        
    } catch {
        {
            Write-Warning "Error initializing WSL environment: $($_.Exception.Message)"
        }
        return $false
    }
}

# Main execution
if ($MyInvocation.InvocationName -ne '.') {
    $result = Initialize-WSLEnvironment -test-only:${test-only} -what-if:${what-if}
    
    if ($result) {
        Write-Success "WSL setup completed successfully"
        return @{ Success = $true; Phase = "WSL"; Message = "WSL setup completed successfully" }
    } else {
        Write-Error "WSL setup failed"
        return @{ Success = $false; Phase = "WSL"; Message = "WSL setup failed" }
    }
}

# Note: Functions are available when this file is dot-sourced