# CE-005: 并发登录压测 & 速率限制验证
# 验证：高并发下速率限制（Rate Limiting）是否正常工作

param(
    [string]$BaseURL = "http://localhost:8080",
    [int]$Concurrency = 20,
    [int]$Duration = 15,
    [switch]$Verbose
)

$ErrorActionPreference = "Continue"

Write-Host "=== CE-005: 并发登录压测 & 速率限制验证 ===" -ForegroundColor Magenta
Write-Host "目标服务: $BaseURL"
Write-Host "并发协程: $Concurrency"
Write-Host "持续时间: ${Duration}s"
Write-Host ""

# 前置检查
Write-Host "[前置检查] 服务健康状态..." -ForegroundColor Cyan
try {
    $health = Invoke-RestMethod -Uri "$BaseURL/health/ready" -TimeoutSec 5
    if ($health.status -ne "UP") {
        Write-Host "❌ 服务不健康，终止实验" -ForegroundColor Red
        exit 1
    }
    Write-Host "  ✅ 服务状态: UP" -ForegroundColor Green
} catch {
    Write-Host "  ❌ 无法连接到服务: $($_.Exception.Message)" -ForegroundColor Red
    exit 1
}

# 并发压测
Write-Host "`n[压测中] 启动 $Concurrency 个并发协程，持续 ${Duration}s..." -ForegroundColor Cyan

$startTime = Get-Date
$jobs = 1..$Concurrency | ForEach-Object {
    $workerID = $_
    Start-Job -ScriptBlock {
        param($BaseURL, $Duration, $workerID)
        
        $end = (Get-Date).AddSeconds($Duration)
        $results = @{
            total = 0
            http_200 = 0
            http_400 = 0
            http_401 = 0
            http_429 = 0
            http_500 = 0
            other = 0
            errors = 0
        }
        
        while ((Get-Date) -lt $end) {
            try {
                $body = @{
                    account  = "chaos_test_user_$workerID"
                    password = "wrong_password_chaos_test"
                } | ConvertTo-Json
                
                $resp = Invoke-WebRequest `
                    -Uri "$BaseURL/api/v1/auth/login" `
                    -Method POST `
                    -Body $body `
                    -ContentType "application/json" `
                    -ErrorAction SilentlyContinue `
                    -TimeoutSec 5
                
                $results.total++
                switch ($resp.StatusCode) {
                    200 { $results.http_200++ }
                    400 { $results.http_400++ }
                    401 { $results.http_401++ }
                    429 { $results.http_429++ }
                    500 { $results.http_500++ }
                    default { $results.other++ }
                }
            } catch {
                $results.total++
                $results.errors++
            }
            
            Start-Sleep -Milliseconds 50
        }
        
        return $results
    } -ArgumentList $BaseURL, $Duration, $workerID
}

Write-Host "  ⏳ 等待实验完成..." -ForegroundColor Yellow
$jobs | Wait-Job | Out-Null

$elapsed = (Get-Date) - $startTime
Write-Host "  ✅ 实验完成，耗时: $([math]::Round($elapsed.TotalSeconds, 1))s" -ForegroundColor Green

# 汇总结果
$totals = @{
    total = 0; http_200 = 0; http_400 = 0; http_401 = 0
    http_429 = 0; http_500 = 0; other = 0; errors = 0
}

$jobs | Receive-Job | ForEach-Object {
    $r = $_
    $totals.total    += $r.total
    $totals.http_200 += $r.http_200
    $totals.http_400 += $r.http_400
    $totals.http_401 += $r.http_401
    $totals.http_429 += $r.http_429
    $totals.http_500 += $r.http_500
    $totals.other    += $r.other
    $totals.errors   += $r.errors
}
$jobs | Remove-Job

# 显示结果
$rateTotal = [math]::Max($totals.total, 1)
Write-Host "`n=== 压测结果 ===" -ForegroundColor Magenta
Write-Host "总请求数:      $($totals.total)"
Write-Host "吞吐量:        $([math]::Round($totals.total / $elapsed.TotalSeconds, 1)) req/s"
Write-Host ""
Write-Host "HTTP 响应分布:"
Write-Host "  200 成功:    $($totals.http_200) ($([math]::Round($totals.http_200 / $rateTotal * 100, 1))%)"
Write-Host "  400 请求错误: $($totals.http_400) ($([math]::Round($totals.http_400 / $rateTotal * 100, 1))%)"
Write-Host "  401 认证失败: $($totals.http_401) ($([math]::Round($totals.http_401 / $rateTotal * 100, 1))%)"
Write-Host "  429 速率限制: $($totals.http_429) ($([math]::Round($totals.http_429 / $rateTotal * 100, 1))%)" -ForegroundColor Yellow
Write-Host "  500 服务错误: $($totals.http_500) ($([math]::Round($totals.http_500 / $rateTotal * 100, 1))%)" -ForegroundColor $(if ($totals.http_500 -gt 0) {"Red"} else {"White"})
Write-Host "  其他/错误:    $($totals.other + $totals.errors)"

# 验证
Write-Host "`n=== 验证 ===" -ForegroundColor Cyan

$passed = 0; $failed = 0

# 验证1：速率限制触发
if ($totals.http_429 -gt 0) {
    Write-Host "  ✅ 速率限制已触发 ($($totals.http_429) 次 429 响应)" -ForegroundColor Green
    $passed++
} else {
    Write-Host "  ❌ 速率限制未触发（0 次 429），请检查 config.yaml ratelimit 配置" -ForegroundColor Red
    $failed++
}

# 验证2：无服务器错误（500 不应出现）
if ($totals.http_500 -eq 0) {
    Write-Host "  ✅ 无 5xx 错误，服务稳定" -ForegroundColor Green
    $passed++
} else {
    Write-Host "  ❌ 出现 $($totals.http_500) 次 5xx 错误，存在系统稳定性问题" -ForegroundColor Red
    $failed++
}

# 验证3：QPS 合理（服务未被压垮）
$targetQPS = $Concurrency * 5  # 理论最大 QPS
$actualQPS = $totals.total / $elapsed.TotalSeconds
if ($actualQPS -gt 0) {
    Write-Host "  ✅ 服务保持响应，实际 QPS: $([math]::Round($actualQPS, 1))" -ForegroundColor Green
    $passed++
} else {
    Write-Host "  ❌ 服务可能已无响应" -ForegroundColor Red
    $failed++
}

Write-Host "`n=== 实验总结 ===" -ForegroundColor Magenta
Write-Host "通过: $passed  失败: $failed"

if ($failed -eq 0) {
    Write-Host "`n✅ CE-005 通过 — 速率限制在高并发下正常工作" -ForegroundColor Green
    exit 0
} else {
    Write-Host "`n❌ CE-005 失败 — 存在 $failed 个验证问题" -ForegroundColor Red
    exit 1
}
