# ts-native 增强型测试运行器
# 提供彩色输出、详细报告和错误追踪

$ErrorActionPreference = "Continue"

# 颜色定义
$RESET = "`e[0m"
$GREEN = "`e[32m"
$RED = "`e[31m"
$YELLOW = "`e[33m"
$BLUE = "`e[34m"
$CYAN = "`e[36m"
$BOLD = "`e[1m"

# 统计变量
$TotalTests = 0
$PassedTests = 0
$FailedTests = 0
$SkippedTests = 0
$TestResults = @()

# 编译器路径
$Compiler = "$PSScriptRoot\target\debug\ts-native.exe"

function Write-Header {
    param([string]$Text)
    Write-Host "`n$BOLD$CYAN=== $Text ===$RESET`n"
}

function Write-TestStart {
    param([string]$TestName)
    Write-Host "$BLUE  ▶ $TestName$RESET"
}

function Write-TestPass {
    param([string]$TestName, [string]$Duration)
    Write-Host "  $GREEN✓ $TestName ($Duration ms)$RESET"
}

function Write-TestFail {
    param([string]$TestName, [string]$Error, [string]$Expected, [string]$Actual)
    Write-Host "  $RED✗ $TestName$RESET"
    Write-Host "    $RED错误: $Error$RESET"
    if ($Expected) {
        Write-Host "    $YELLOW预期: $Expected$RESET"
    }
    if ($Actual) {
        Write-Host "    $YELLOW实际: $Actual$RESET"
    }
}

function Write-TestSkip {
    param([string]$TestName, [string]$Reason)
    Write-Host "  $YELLOW⊘ $TestName - $Reason$RESET"
}

function Run-CompileTest {
    param([string]$TestFile)
    
    $Stopwatch = [System.Diagnostics.Stopwatch]::StartNew()
    
    try {
        $CompileOutput = & $Compiler $TestFile 2>&1
        $Stopwatch.Stop()
        
        if ($LASTEXITCODE -eq 0) {
            return @{
                Success = $true
                Duration = $Stopwatch.ElapsedMilliseconds
                Output = $CompileOutput
            }
        } else {
            return @{
                Success = $false
                Duration = $Stopwatch.ElapsedMilliseconds
                Error = ($CompileOutput -join "`n")
            }
        }
    } catch {
        $Stopwatch.Stop()
        return @{
            Success = $false
            Duration = $Stopwatch.ElapsedMilliseconds
            Error = $_.Exception.Message
        }
    }
}

function Run-ExecuteTest {
    param([string]$ExeFile)
    
    $Stopwatch = [System.Diagnostics.Stopwatch]::StartNew()
    
    try {
        $Output = & $ExeFile 2>&1
        $Stopwatch.Stop()
        
        return @{
            Success = $true
            Duration = $Stopwatch.ElapsedMilliseconds
            Output = ($Output -join "`n").Trim()
        }
    } catch {
        $Stopwatch.Stop()
        return @{
            Success = $false
            Duration = $Stopwatch.ElapsedMilliseconds
            Error = $_.Exception.Message
        }
    }
}

function Run-Test {
    param(
        [string]$TestFile,
        [string]$ExpectedOutput = $null,
        [string]$Description = ""
    )
    
    $TotalTests++
    $TestName = if ($Description) { $Description } else { [System.IO.Path]::GetFileName($TestFile) }
    
    Write-TestStart -TestName $TestName
    
    # 编译阶段
    $CompileResult = Run-CompileTest -TestFile $TestFile
    
    if (-not $CompileResult.Success) {
        $FailedTests++
        Write-TestFail -TestName $TestName -Error "编译失败: $($CompileResult.Error)"
        $TestResults += @{
            Name = $TestName
            Status = "FAIL"
            Stage = "Compile"
            Error = $CompileResult.Error
            Duration = $CompileResult.Duration
        }
        return
    }
    
    # 执行阶段
    $ExeFile = $TestFile -replace '\.ts$', '.exe'
    if (-not (Test-Path $ExeFile)) {
        $ExeFile = $TestFile -replace '\.ts$', '.exe'
        $ExeFile = [System.IO.Path]::Combine([System.IO.Path]::GetDirectoryName($TestFile), 
                     [System.IO.Path]::GetFileNameWithoutExtension($TestFile) + ".exe")
    }
    
    $ExecResult = Run-ExecuteTest -ExeFile $ExeFile
    
    if (-not $ExecResult.Success) {
        $FailedTests++
        Write-TestFail -TestName $TestName -Error "执行失败: $($ExecResult.Error)"
        $TestResults += @{
            Name = $TestName
            Status = "FAIL"
            Stage = "Execute"
            Error = $ExecResult.Error
            Duration = $ExecResult.Duration
        }
        return
    }
    
    # 验证输出
    if ($ExpectedOutput) {
        if ($ExecResult.Output -eq $ExpectedOutput) {
            $PassedTests++
            Write-TestPass -TestName $TestName -Duration $ExecResult.Duration
            $TestResults += @{
                Name = $TestName
                Status = "PASS"
                Duration = $ExecResult.Duration
            }
        } else {
            $FailedTests++
            Write-TestFail -TestName $TestName `
                -Error "输出不匹配" `
                -Expected $ExpectedOutput `
                -Actual $ExecResult.Output
            $TestResults += @{
                Name = $TestName
                Status = "FAIL"
                Stage = "Output"
                Expected = $ExpectedOutput
                Actual = $ExecResult.Output
                Duration = $ExecResult.Duration
            }
        }
    } else {
        $PassedTests++
        Write-TestPass -TestName $TestName -Duration $ExecResult.Duration
        $TestResults += @{
            Name = $TestName
            Status = "PASS"
            Duration = $ExecResult.Duration
        }
    }
}

function Write-TestReport {
    Write-Header "测试报告"
    
    $TotalDuration = ($TestResults | Measure-Object -Property Duration -Sum).Sum
    
    Write-Host "$BOLD总计测试: $TotalTests$RESET"
    Write-Host "$GREEN✓ 通过: $PassedTests$RESET"
    Write-Host "$RED✗ 失败: $FailedTests$RESET"
    Write-Host "$YELLOW总耗时: $TotalDuration ms$RESET"
    Write-Host ""
    
    if ($FailedTests -gt 0) {
        Write-Host "$BOLD$RED失败的测试:$RESET`n"
        $FailedResults = $TestResults | Where-Object { $_.Status -eq "FAIL" }
        foreach ($result in $FailedResults) {
            Write-Host "  $RED✗ $($result.Name)$RESET"
            if ($result.Error) {
                Write-Host "    错误: $($result.Error)"
            }
            if ($result.Expected -and $result.Actual) {
                Write-Host "    预期: $($result.Expected)"
                Write-Host "    实际: $($result.Actual)"
            }
            Write-Host ""
        }
    }
    
    # 生成测试报告文件
    $ReportFile = "$PSScriptRoot\test-report.json"
    $ReportData = @{
        Total = $TotalTests
        Passed = $PassedTests
        Failed = $FailedTests
        Duration = $TotalDuration
        Results = $TestResults
    } | ConvertTo-Json -Depth 3
    
    $ReportData | Out-File -FilePath $ReportFile -Encoding utf8
    Write-Host "$CYAN详细报告已保存到: $ReportFile$RESET`n"
    
    if ($FailedTests -eq 0) {
        Write-Host "$BOLD$GREEN🎉 所有测试通过！$RESET`n"
        return 0
    } else {
        Write-Host "$BOLD$RED⚠️  有 $FailedTests 个测试失败$RESET`n"
        return 1
    }
}

# 主测试流程
Write-Header "ts-native 测试套件"

Write-Host "编译器: $Compiler"
Write-Host "测试目录: $PSScriptRoot\tests"
Write-Host ""

# 运行所有测试
$TestDir = "$PSScriptRoot\tests"
$TestFiles = Get-ChildItem -Path $TestDir -Filter "test_*.ts" | Sort-Object Name

foreach ($testFile in $TestFiles) {
    Run-Test -TestFile $testFile.FullName
}

# 生成报告
$ExitCode = Write-TestReport
exit $ExitCode
