scripts/modules/shared/test-functions.ps1

# strangeloop Setup - Shared Test Functions
# Version: 1.0.0

# Testing and validation functions for system requirements and tool availability

function Test-Command {
    param([string]$Command)
    
    try {
        $null = Get-Command $Command -ErrorAction Stop
        return $true
    } catch {
        return $false
    }
}

function Test-AdminPrivileges {
    try {
        $currentUser = [Security.Principal.WindowsIdentity]::GetCurrent()
        $principal = New-Object Security.Principal.WindowsPrincipal($currentUser)
        return $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
    } catch {
        return $false
    }
}

function Test-InternetConnection {
    param(
        [string]$TestUrl = "https://www.bing.com",
        [int]$TimeoutSeconds = 10
    )
    
    try {
        $response = Invoke-WebRequest -Uri $TestUrl -UseBasicParsing -TimeoutSec $TimeoutSeconds -ErrorAction Stop
        return $response.StatusCode -eq 200
    } catch {
        return $false
    }
}

function Test-WindowsVersion {
    param([string]$MinimumVersion = "10.0")
    
    try {
        $osVersion = [System.Environment]::OSVersion.Version
        $requiredVersion = [Version]$MinimumVersion
        return $osVersion -ge $requiredVersion
    } catch {
        return $false
    }
}

function Test-PowerShellVersion {
    param([string]$MinimumVersion = "5.1")
    
    try {
        $psVersion = $PSVersionTable.PSVersion
        $requiredVersion = [Version]$MinimumVersion
        return $psVersion -ge $requiredVersion
    } catch {
        return $false
    }
}

function Test-DiskSpace {
    param(
        [string]$Path = "C:\",
        [int]$RequiredGB = 5
    )
    
    try {
        $drive = Get-PSDrive -Name $Path.Substring(0,1) -ErrorAction Stop
        $freeSpaceGB = [math]::Round($drive.Free / 1GB, 2)
        return $freeSpaceGB -ge $RequiredGB
    } catch {
        return $false
    }
}

function Get-ToolVersion {
    param([string]$Tool)
    
    try {
        switch ($Tool.ToLower()) {
            "git" {
                $output = git --version 2>$null
                if ($output -match "git version ([0-9]+\.[0-9]+\.[0-9]+)") {
                    return $matches[1]
                }
            }
            "az" {
                $output = az version --output json 2>$null | ConvertFrom-Json
                return $output.'azure-cli'
            }
            "git-lfs" {
                $output = git lfs version 2>$null
                if ($output -match "git-lfs/([0-9]+\.[0-9]+\.[0-9]+)") {
                    return $matches[1]
                }
            }
            "docker" {
                $output = docker --version 2>$null
                if ($output -match "Docker version ([0-9]+\.[0-9]+\.[0-9]+)") {
                    return $matches[1]
                }
            }
            "strangeloop" {
                $output = strangeloop version 2>$null
                $outputString = $output -join "`n"
                if ($outputString -match "\[INFO\] strangeloop ([0-9]+\.[0-9]+\.[0-9]+(?:-[a-zA-Z0-9]+)?)") {
                    return $matches[1]
                }
            }
            "python" {
                $output = python --version 2>$null
                if ($output -match "Python ([0-9]+\.[0-9]+\.[0-9]+)") {
                    return $matches[1]
                }
            }
            "pip" {
                $output = pip --version 2>$null
                if ($output -match "pip ([0-9]+\.[0-9]+\.[0-9]+)") {
                    return $matches[1]
                }
            }
            "poetry" {
                $output = poetry --version 2>$null
                if ($output -match "Poetry \(version ([0-9]+\.[0-9]+\.[0-9]+)\)") {
                    return $matches[1]
                }
            }
        }
    } catch {
        return $null
    }
    
    return $null
}

function Invoke-CommandWithTimeout {
    param(
        [scriptblock]$ScriptBlock,
        [int]$TimeoutSeconds = 300,
        [string]$Description = "Command"
    )
    
    try {
        $job = Start-Job -ScriptBlock $ScriptBlock
        $result = Wait-Job $job -Timeout $TimeoutSeconds
        
        if ($result) {
            $output = Receive-Job $job
            Remove-Job $job
            return @{
                Success = $true
                Output = $output
                Error = $null
            }
        } else {
            Stop-Job $job
            Remove-Job $job
            return @{
                Success = $false
                Output = $null
                Error = "Command timed out after $TimeoutSeconds seconds"
            }
        }
    } catch {
        return @{
            Success = $false
            Output = $null
            Error = $_.Exception.Message
        }
    }
}

function Test-SystemRequirements {
    param([switch]$Detailed)
    
    $results = @{
        WindowsVersion = Test-WindowsVersion
        PowerShellVersion = Test-PowerShellVersion  
        DiskSpace = Test-DiskSpace -RequiredGB 5
        InternetConnection = Test-InternetConnection
        AdminPrivileges = Test-AdminPrivileges
    }
    
    $overallSuccess = $true
    foreach ($result in $results.Values) {
        if (-not $result) {
            $overallSuccess = $false
            break
        }
    }
    
    if ($Detailed) {
        foreach ($requirement in $results.GetEnumerator()) {
            if ($requirement.Value) {
                Write-Success "$($requirement.Key): Passed"
            } else {
                Write-Error "$($requirement.Key): Failed"
            }
        }
    }
    
    return @{
        Success = $overallSuccess
        Results = $results
    }
}

function Test-DirectoryWritable {
    param([string]$Path)
    
    try {
        $testFile = Join-Path $Path "test_write_$(Get-Random).tmp"
        $null = New-Item -Path $testFile -ItemType File -Force
        Remove-Item $testFile -Force
        return $true
    } catch {
        return $false
    }
}

# Export functions for module usage only
if ($MyInvocation.MyCommand.ModuleName) {
    Export-ModuleMember -Function @(
        'Test-Command',
        'Test-AdminPrivileges',
        'Test-InternetConnection', 
        'Test-WindowsVersion',
        'Test-PowerShellVersion',
        'Test-DiskSpace',
        'Get-ToolVersion',
        'Invoke-CommandWithTimeout',
        'Test-SystemRequirements',
        'Test-DirectoryWritable'
    )
}