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

# strangeloop Setup - Git Installation Module
# Version: 1.0.0


param(
    [string]$Version = "latest",
    [switch]$WSLMode,
    [switch]${test-only},
    [switch]$Detailed,
    [switch]${what-if}
)

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

function Test-Git {
    param(
        
    )
    
    try {
        Write-Info "Testing Git installation..."
        
        # Check if Git command is available
        if (-not (Test-Command "git")) {
            Write-Warning "Git command 'git' not found"
            return $false
        }
        
        # Check Git version
        $gitVersion = Get-ToolVersion "git"
        if (-not $gitVersion) {
            Write-Warning "Could not get Git version"
            return $false
        }
        
        # Test basic functionality
        $versionOutput = git --version 2>$null
        if (-not $versionOutput) {
            Write-Warning "Git functionality test failed"
            return $false
        }
        
        Write-Success "Git is properly installed: $gitVersion"
        return $true
        
    } catch {
        Write-Warning "Error testing Git: $($_.Exception.Message)"
        return $false
    }
}

function Install-Git {
    param(
        [string]$Version = "latest",
        [string]$InstallPath = $null,
        [switch]${test-only},
        [switch]${what-if}
    )
    
    # If test-only mode, just test current installation
    if (${test-only}) {
        return Test-Git
    }
    
    # If what-if mode, show what would be done
    if (${what-if}) {
        Write-Host "what if: Would test if Git is already installed" -ForegroundColor Yellow
        Write-Host "what if: Would check internet connection" -ForegroundColor Yellow
        Write-Host "what if: Would determine Git download URL for version '$Version'" -ForegroundColor Yellow
        Write-Host "what if: Would download Git installer to temporary directory" -ForegroundColor Yellow
        Write-Host "what if: Would install Git with silent installation arguments" -ForegroundColor Yellow
        Write-Host "what if: Would configure Git with safe defaults" -ForegroundColor Yellow
        return $true
    }
    
    Write-Step "Installing Git..."
    
    try {
        # Check if Git is already installed
        if (Test-Command "git") {
            $currentVersion = Get-ToolVersion "git"
            if ($currentVersion) {
                Write-Info "Git $currentVersion is already installed"
                if ($Version -eq "latest") {
                    Write-Success "Git installation confirmed"
                    return $true
                }
            }
        }
        
        # Check internet connection
        if (-not (Test-InternetConnection)) {
            Write-Error "Internet connection required for Git installation"
            return $false
        }
        
        Write-Progress "Determining Git download URL..."
        
        # Get latest Git version if not specified
        $downloadUrl = $null
        if ($Version -eq "latest") {
            try {
                $releasesUrl = "https://api.github.com/repos/git-for-windows/git/releases/latest"
                $releaseInfo = Invoke-RestMethod -Uri $releasesUrl -UseBasicParsing
                $asset = $releaseInfo.assets | Where-Object { $_.name -like "*64-bit.exe" } | Select-Object -First 1
                if ($asset) {
                    $downloadUrl = $asset.browser_download_url
                    $Version = $releaseInfo.tag_name -replace '^v', ''
                }
            } catch {
                Write-Warning "Could not get latest Git version from GitHub API, using fallback URL"
                $downloadUrl = "https://github.com/git-for-windows/git/releases/latest/download/Git-2.42.0.2-64-bit.exe"
            }
        } else {
            $downloadUrl = "https://github.com/git-for-windows/git/releases/download/v$Version.windows.1/Git-$Version-64-bit.exe"
        }
        
        if (-not $downloadUrl) {
            Write-Error "Could not determine Git download URL"
            return $false
        }
        
        Write-Progress "Downloading Git installer..."
        
        # Download Git installer
        $tempDir = Join-Path $env:TEMP "Git-$(Get-Random)"
        New-Item -ItemType Directory -Path $tempDir -Force | Out-Null
        if (-not (Test-Path $tempDir)) {
            Write-Error "Could not create temporary directory"
            return $false
        }
        
        $installerPath = Join-Path $tempDir "git-installer.exe"
        
        try {
            Invoke-WebRequest -Uri $downloadUrl -OutFile $installerPath -UseBasicParsing
            Write-Success "Git installer downloaded successfully"
        } catch {
            Write-Error "Failed to download Git installer: $($_.Exception.Message)"
            Remove-Item -Path $tempDir -Recurse -Force -ErrorAction SilentlyContinue
            return $false
        }
        
        # Verify download
        if (-not (Test-Path $installerPath)) {
            Write-Error "Git installer not found after download"
            Remove-Item -Path $tempDir -Recurse -Force -ErrorAction SilentlyContinue
            return $false
        }
        
        Write-Progress "Installing Git..."
        
        # Prepare installation arguments
        $installArgs = @(
            "/VERYSILENT",
            "/NORESTART",
            "/NOCANCEL",
            "/SP-",
            "/CLOSEAPPLICATIONS",
            "/RESTARTAPPLICATIONS",
            "/COMPONENTS=icons,ext\reg\shellhere,assoc,assoc_sh"
        )
        
        if ($InstallPath) {
            $installArgs += "/DIR=`"$InstallPath`""
        }
        
        # Install Git
        $installResult = Invoke-CommandWithTimeout -ScriptBlock {
            Start-Process -FilePath $installerPath -ArgumentList $installArgs -Wait -NoNewWindow -PassThru
        } -TimeoutSeconds 600 -Description "Git installation"
        
        # Clean up installer
        Remove-Item -Path $tempDir -Recurse -Force -ErrorAction SilentlyContinue
        
        if (-not $installResult.Success) {
            Write-Error "Git installation failed: $($installResult.Error)"
            return $false
        }
        
        $exitCode = $installResult.Output.ExitCode
        if ($exitCode -ne 0) {
            Write-Error "Git installation failed with exit code: $exitCode"
            return $false
        }
        
        Write-Success "Git installed successfully"
        
        # Update PATH and verify installation
        Write-Progress "Verifying Git installation..."
        
        # Refresh environment variables
        $env:PATH = [Environment]::GetEnvironmentVariable("PATH", "Machine") + 
                   ";" + [Environment]::GetEnvironmentVariable("PATH", "User")
        
        # Wait a moment for installation to complete
        Start-Sleep -Seconds 3
        
        # Verify installation
        if (Test-Command "git") {
            $installedVersion = Get-ToolVersion "git"
            if ($installedVersion) {
                Write-Success "Git $installedVersion verified and ready"
                
                # Configure Git with safe defaults if not already configured
                Write-Progress "Configuring Git defaults..."
                Set-GitDefaults
                
                return $true
            } else {
                Write-Warning "Git installed but version detection failed"
                return $true  # Still consider it successful
            }
        } else {
            Write-Error "Git installation completed but 'git' command not found"
            Write-Info "You may need to restart your terminal or reboot your system"
            return $false
        }
        
    } catch {
        Write-Error "Git installation failed: $($_.Exception.Message)"
        return $false
    }
}

function Set-GitDefaults {
    Write-Step "Configuring Git defaults..."
    
    try {
        # Check if global user.name is set
        $userName = git config --global user.name 2>$null
        if (-not $userName) {
            $userName = Read-Host "Enter your Git user.name (required)"
            while ([string]::IsNullOrWhiteSpace($userName)) {
                $userName = Read-Host "Git user.name cannot be empty. Please enter your name:"
            }
            git config --global user.name "$userName"
            Write-Info "Set Git user.name to '$userName'"
        }

        # Check if global user.email is set
        $userEmail = git config --global user.email 2>$null
        if (-not $userEmail) {
            $userEmail = Read-Host "Enter your Git user.email (required)"
            while ([string]::IsNullOrWhiteSpace($userEmail)) {
                $userEmail = Read-Host "Git user.email cannot be empty. Please enter your email:"
            }
            git config --global user.email "$userEmail"
            Write-Info "Set Git user.email to '$userEmail'"
        }

        # Set safe directory configuration for WSL compatibility
        git config --global --add safe.directory '*'
        Write-Info "Configured Git safe.directory for WSL compatibility"

        # Set default branch name
        git config --global init.defaultBranch main
        Write-Info "Set default branch name to 'main'"

        # Set pull behavior
        git config --global pull.rebase false
        Write-Info "Set Git pull behavior to merge"

        # Set core autocrlf for Windows
        git config --global core.autocrlf true
        Write-Info "Set Git core.autocrlf to true for Windows"

        Write-Success "Git default configuration completed"

    } catch {
        Write-Warning "Could not configure Git defaults: $($_.Exception.Message)"
    }
}

# Main execution
if ($MyInvocation.InvocationName -ne '.') {
    $result = Install-Git -Version $Version -InstallPath $InstallPath -test-only:${test-only} -what-if:${what-if}
    
    if ($result) {
        if (${test-only}) {
            Write-Success "Git test completed successfully"
        } else {
            Write-CompletionSummary @{
                'Git Installation' = 'Completed Successfully'
                'Version' = (Get-ToolVersion "git")
                'Command Available' = if (Test-Command "git") { "Yes" } else { "No" }
            } -Title "Git Installation Summary"
        }
        exit 0
    } else {
        if (${test-only}) {
            Write-Error "Git test failed"
        } else {
            Write-Error "Git installation failed"
        }
        exit 1
    }
}

# Export functions for module usage
Export-ModuleMember -Function @(
    'Install-Git',
    'Set-GitDefaults'
)