TerminalCanaryUpdater.psm1

# TerminalCanaryUpdater PowerShell Module
# Provides functions to update Windows Terminal Canary with automatic process management

# Get current Terminal Canary version and compare with latest
function Get-CanaryVersion {
    [CmdletBinding()]
    param(
        [switch]$CheckLatest
    )
    
    Write-Host "🔍 Checking Windows Terminal Canary..." -ForegroundColor Cyan
    
    # Check if installed
    $canaryPackage = Get-AppxPackage -Name "*WindowsTerminalCanary*" -ErrorAction SilentlyContinue
    if (-not $canaryPackage) {
        Write-Host "❌ Windows Terminal Canary not found" -ForegroundColor Red
        return $null
    }
    
    $installedVersion = $canaryPackage.Version
    Write-Host "✅ Installed version: $installedVersion" -ForegroundColor Green
    
    if ($CheckLatest) {
        try {
            Write-Host "🔄 Checking latest version..." -ForegroundColor Yellow
            $appInstallerUrl = "https://terminalbuilds-grbmacf3f6bsbma8.z01.azurefd.net/nightly/Microsoft.WindowsTerminalCanary.appinstaller"
            $tempFile = "$env:TEMP\canary-version-check.appinstaller"
            
            Invoke-WebRequest -Uri $appInstallerUrl -OutFile $tempFile -UseBasicParsing
            [xml]$appInstallerXml = Get-Content $tempFile
            $latestVersion = $appInstallerXml.AppInstaller.MainBundle.Version
            
            Write-Host " Latest version: $latestVersion" -ForegroundColor Gray
            
            # Compare versions
            $installedVer = [Version]$installedVersion
            $latestVer = [Version]$latestVersion
            
            if ($latestVer -gt $installedVer) {
                Write-Host "🆕 Update available! ($installedVersion → $latestVersion)" -ForegroundColor Yellow
            } elseif ($latestVer -eq $installedVer) {
                Write-Host "✅ You have the latest version!" -ForegroundColor Green
            } else {
                Write-Host "ℹ️ You have a newer version than latest release" -ForegroundColor Cyan
            }
            
            Remove-Item $tempFile -Force -ErrorAction SilentlyContinue
            
            return @{
                Installed = $installedVersion
                Latest = $latestVersion
                UpdateAvailable = ($latestVer -gt $installedVer)
            }
        } catch {
            Write-Host " Could not retrieve latest version info" -ForegroundColor Yellow
            return @{
                Installed = $installedVersion
                Latest = $null
                UpdateAvailable = $null
            }
        }
    }
    
    return @{
        Installed = $installedVersion
        Latest = $null
        UpdateAvailable = $null
    }
}

# Full-featured Terminal Canary updater with version checking
function Update-TerminalCanary {
    [CmdletBinding()]
    param(
        [switch]$Force
    )
    
    $installerUrl = "https://aka.ms/terminal-canary-installer"
    $tempPath = "$env:TEMP\Microsoft.WindowsTerminalCanary.appinstaller"
    
    Write-Host "🔍 Checking Windows Terminal Canary..." -ForegroundColor Cyan
    
    # Check if installed and get version
    $canaryPackage = Get-AppxPackage -Name "*WindowsTerminalCanary*" -ErrorAction SilentlyContinue
    if (-not $canaryPackage) {
        Write-Host "❌ Windows Terminal Canary not found" -ForegroundColor Red
        return
    }
    
    Write-Host "✅ Current version: $($canaryPackage.Version)" -ForegroundColor Green
    
    # Check for update (simplified - always allow update check)
    if (-not $Force) {
        $response = Read-Host "🔄 Check for update and install if available? (Y/n)"
        if ($response -eq 'n' -or $response -eq 'N') {
            Write-Host "❌ Update cancelled" -ForegroundColor Yellow
            return
        }
    }
    
    Write-Host "⬇️ Downloading installer..." -ForegroundColor Yellow
    
    try {
        # Download installer with better error handling
        $webClient = New-Object System.Net.WebClient
        $webClient.DownloadFile($installerUrl, $tempPath)
        $webClient.Dispose()
        
        if (-not (Test-Path $tempPath)) {
            Write-Host "❌ Download failed" -ForegroundColor Red
            return
        }
        
        # Verify file is not empty
        $fileInfo = Get-Item $tempPath
        if ($fileInfo.Length -eq 0) {
            Write-Host "❌ Downloaded file is empty" -ForegroundColor Red
            Remove-Item $tempPath -Force
            return
        }
        
        Write-Host "✅ Downloaded ($($fileInfo.Length) bytes)" -ForegroundColor Green
        
        # Close Canary processes FIRST
        Write-Host "🔄 Closing Terminal Canary processes..." -ForegroundColor Yellow
        
        $canaryProcesses = Get-Process | Where-Object { 
            $_.ProcessName -eq "WindowsTerminal" -and 
            $_.Path -like "*WindowsTerminalCanary*" 
        } -ErrorAction SilentlyContinue
        
        if ($canaryProcesses) {
            Write-Host " Found $($canaryProcesses.Count) Canary process(es)" -ForegroundColor Gray
            
            foreach ($process in $canaryProcesses) {
                try {
                    Write-Host " Closing PID $($process.Id)..." -ForegroundColor Gray
                    $process.CloseMainWindow() | Out-Null
                    Start-Sleep -Seconds 1
                    
                    # Force kill if still running
                    if (-not $process.HasExited) {
                        Write-Host " Force killing PID $($process.Id)..." -ForegroundColor Gray
                        Stop-Process -Id $process.Id -Force
                    }
                } catch {
                    Write-Host " Could not close PID $($process.Id): $($_.Exception.Message)" -ForegroundColor Yellow
                }
            }
            
            Write-Host "✅ Terminal Canary processes closed" -ForegroundColor Green
            Start-Sleep -Seconds 2
        }
        
        # Install using Add-AppxPackage (more reliable)
        Write-Host "🚀 Installing via Add-AppxPackage..." -ForegroundColor Cyan
        
        try {
            Add-AppxPackage -AppInstallerFile $tempPath -ForceApplicationShutdown
            Write-Host "✅ Installation completed successfully!" -ForegroundColor Green
            
            # Check new version
            Start-Sleep -Seconds 2
            $newPackage = Get-AppxPackage -Name "*WindowsTerminalCanary*" -ErrorAction SilentlyContinue
            if ($newPackage) {
                Write-Host " New version: $($newPackage.Version)" -ForegroundColor Green
            }
            
        } catch {
            Write-Host "⚠️ Add-AppxPackage failed: $($_.Exception.Message)" -ForegroundColor Yellow
            Write-Host "🔄 Trying alternative method..." -ForegroundColor Yellow
            
            # Fallback: Try launching the appinstaller file
            try {
                $installerProcess = Start-Process -FilePath $tempPath -PassThru -WindowStyle Normal -Wait
                
                if ($installerProcess.ExitCode -eq 0) {
                    Write-Host "✅ Installation completed via UI!" -ForegroundColor Green
                } else {
                    Write-Host "⚠️ Installer exited with code: $($installerProcess.ExitCode)" -ForegroundColor Yellow
                }
            } catch {
                Write-Host "❌ Both installation methods failed" -ForegroundColor Red
                Write-Host " You can try manually: $tempPath" -ForegroundColor Yellow
                return
            }
        }
        
        # Clean up
        if (Test-Path $tempPath) {
            Remove-Item $tempPath -Force -ErrorAction SilentlyContinue
            Write-Host " Installer file cleaned up" -ForegroundColor Gray
        }
        
    } catch {
        Write-Host "❌ Error: $($_.Exception.Message)" -ForegroundColor Red
        
        # Clean up on error
        if (Test-Path $tempPath) {
            Remove-Item $tempPath -Force -ErrorAction SilentlyContinue
        }
    }
}

# Simple one-command Terminal Canary installer
function Install-CanaryQuick {
    [CmdletBinding()]
    param()
    
    $temp = "$env:TEMP\canary.appinstaller"
    Write-Host "⬇️ Downloading installer..." -ForegroundColor Yellow
    Invoke-WebRequest -Uri "https://aka.ms/terminal-canary-installer" -OutFile $temp -UseBasicParsing
    
    Write-Host "🚀 Launching installer..." -ForegroundColor Cyan
    Start-Process $temp
    
    Write-Host "⏳ Waiting 3 seconds for installer to start..." -ForegroundColor Yellow
    Start-Sleep -Seconds 3
    
    Write-Host "🔄 Killing Terminal Canary processes..." -ForegroundColor Yellow
    Get-Process | Where-Object { 
        $_.ProcessName -eq "WindowsTerminal" -and 
        $_.Path -like "*WindowsTerminalCanary*" 
    } | ForEach-Object { 
        try { 
            Write-Host " Killing PID $($_.Id)" -ForegroundColor Gray
            Stop-Process -Id $_.Id -Force 
        } catch { }
    }
    
    Write-Host "✅ Installer launched and Canary processes killed!" -ForegroundColor Green
}

# Create aliases
New-Alias -Name "canary-update" -Value Update-TerminalCanary -Force
New-Alias -Name "canary-quick" -Value Install-CanaryQuick -Force
New-Alias -Name "canary-version" -Value Get-CanaryVersion -Force

# Export functions and aliases
Export-ModuleMember -Function Update-TerminalCanary, Install-CanaryQuick, Get-CanaryVersion
Export-ModuleMember -Alias "canary-update", "canary-quick", "canary-version"