# ColaFlow Day 5 QA Integration Test Suite
# Comprehensive testing for Refresh Token + RBAC

$baseUrl = "http://localhost:5167"
$ErrorActionPreference = "Continue"

# Test counters
$totalTests = 0
$passedTests = 0
$failedTests = 0
$errors = @()

function Test-Api {
    param($Name, $ScriptBlock)
    $totalTests++
    Write-Host "`n========================================" -ForegroundColor Cyan
    Write-Host "Test $totalTests : $Name" -ForegroundColor Cyan
    Write-Host "========================================" -ForegroundColor Cyan

    try {
        & $ScriptBlock
        $passedTests++
        Write-Host "[PASS] $Name" -ForegroundColor Green
        return $true
    } catch {
        $failedTests++
        $script:errors += @{Name=$Name; Error=$_.Exception.Message}
        Write-Host "[FAIL] $Name" -ForegroundColor Red
        Write-Host "Error: $($_.Exception.Message)" -ForegroundColor Red
        return $false
    }
}

Write-Host "===================================================" -ForegroundColor Magenta
Write-Host "  ColaFlow Day 5 Integration Test Suite" -ForegroundColor Magenta
Write-Host "  Testing: Refresh Token + RBAC + Regression" -ForegroundColor Magenta
Write-Host "===================================================" -ForegroundColor Magenta

# Wait for API
Write-Host "`nWaiting for API to be ready..." -ForegroundColor Yellow
Start-Sleep -Seconds 5

# ============================================================================
# PHASE 1: REFRESH TOKEN TESTS
# ============================================================================

Write-Host "`n" -ForegroundColor Yellow
Write-Host "=====================================" -ForegroundColor Yellow
Write-Host "  PHASE 1: REFRESH TOKEN TESTS" -ForegroundColor Yellow
Write-Host "=====================================" -ForegroundColor Yellow

# Global variables for tokens
$script:tenantSlug = ""
$script:accessToken1 = ""
$script:refreshToken1 = ""
$script:accessToken2 = ""
$script:refreshToken2 = ""
$script:userId = ""

# Test 1: Register and Get Tokens
Test-Api "Register Tenant - Get Access & Refresh Tokens" {
    $slug = "test-$(Get-Random -Minimum 1000 -Maximum 9999)"
    $body = @{
        tenantName = "Test Corp Day5"
        tenantSlug = $slug
        subscriptionPlan = "Professional"
        adminEmail = "admin@testday5.com"
        adminPassword = "Admin@1234"
        adminFullName = "Test Admin"
    } | ConvertTo-Json

    $response = Invoke-RestMethod -Uri "$baseUrl/api/tenants/register" `
        -Method Post -ContentType "application/json" -Body $body

    if (-not $response.accessToken -or -not $response.refreshToken) {
        throw "Missing tokens in response"
    }

    $script:tenantSlug = $slug
    $script:accessToken1 = $response.accessToken
    $script:refreshToken1 = $response.refreshToken
    $script:userId = $response.user.id

    Write-Host "  Tenant: $slug" -ForegroundColor Gray
    Write-Host "  User ID: $($script:userId)" -ForegroundColor Gray
    Write-Host "  Access Token: $($script:accessToken1.Substring(0,20))..." -ForegroundColor Gray
    Write-Host "  Refresh Token: $($script:refreshToken1.Substring(0,20))..." -ForegroundColor Gray
}

# Test 2: Use Access Token
Test-Api "Access Protected Endpoint with Access Token" {
    $headers = @{ "Authorization" = "Bearer $($script:accessToken1)" }
    $response = Invoke-RestMethod -Uri "$baseUrl/api/auth/me" -Method Get -Headers $headers

    if (-not $response.userId) {
        throw "No user data returned"
    }

    Write-Host "  User: $($response.email)" -ForegroundColor Gray
}

# Test 3: Refresh Token
Test-Api "Refresh Access Token (Token Rotation)" {
    $body = @{ refreshToken = $script:refreshToken1 } | ConvertTo-Json
    $response = Invoke-RestMethod -Uri "$baseUrl/api/auth/refresh" `
        -Method Post -ContentType "application/json" -Body $body

    if (-not $response.accessToken -or -not $response.refreshToken) {
        throw "Missing tokens in refresh response"
    }

    if ($response.accessToken -eq $script:accessToken1 -or $response.refreshToken -eq $script:refreshToken1) {
        throw "Tokens were not rotated"
    }

    $script:accessToken2 = $response.accessToken
    $script:refreshToken2 = $response.refreshToken

    Write-Host "  New Access Token: $($script:accessToken2.Substring(0,20))..." -ForegroundColor Gray
    Write-Host "  Tokens rotated successfully" -ForegroundColor Gray
}

# Test 4: Token Reuse Detection
Test-Api "Token Reuse Detection (Security)" {
    $body = @{ refreshToken = $script:refreshToken1 } | ConvertTo-Json

    try {
        $response = Invoke-RestMethod -Uri "$baseUrl/api/auth/refresh" `
            -Method Post -ContentType "application/json" -Body $body
        throw "Old refresh token was accepted - SECURITY ISSUE!"
    } catch {
        $statusCode = $_.Exception.Response.StatusCode.value__
        if ($statusCode -ne 401) {
            throw "Expected 401, got $statusCode"
        }
        Write-Host "  Old token correctly rejected (401)" -ForegroundColor Gray
    }
}

# Test 5: New Token Works
Test-Api "New Access Token Works" {
    $headers = @{ "Authorization" = "Bearer $($script:accessToken2)" }
    $response = Invoke-RestMethod -Uri "$baseUrl/api/auth/me" -Method Get -Headers $headers

    if ($response.userId -ne $script:userId) {
        throw "User ID mismatch"
    }

    Write-Host "  New token validated successfully" -ForegroundColor Gray
}

# Test 6: Logout
Test-Api "Logout - Revoke Refresh Token" {
    $body = @{ refreshToken = $script:refreshToken2 } | ConvertTo-Json
    $response = Invoke-RestMethod -Uri "$baseUrl/api/auth/logout" `
        -Method Post -ContentType "application/json" -Body $body

    if (-not ($response.message -like "*success*")) {
        throw "Logout did not return success"
    }

    Write-Host "  Token revoked successfully" -ForegroundColor Gray
}

# Test 7: Revoked Token Rejected
Test-Api "Revoked Token Cannot Be Used" {
    $body = @{ refreshToken = $script:refreshToken2 } | ConvertTo-Json

    try {
        $response = Invoke-RestMethod -Uri "$baseUrl/api/auth/refresh" `
            -Method Post -ContentType "application/json" -Body $body
        throw "Revoked token was accepted - SECURITY ISSUE!"
    } catch {
        $statusCode = $_.Exception.Response.StatusCode.value__
        if ($statusCode -ne 401) {
            throw "Expected 401, got $statusCode"
        }
        Write-Host "  Revoked token correctly rejected" -ForegroundColor Gray
    }
}

# ============================================================================
# PHASE 2: RBAC TESTS
# ============================================================================

Write-Host "`n" -ForegroundColor Yellow
Write-Host "=====================================" -ForegroundColor Yellow
Write-Host "  PHASE 2: RBAC TESTS" -ForegroundColor Yellow
Write-Host "=====================================" -ForegroundColor Yellow

# Global variables for RBAC tests
$script:rbacAccessToken = ""
$script:rbacRefreshToken = ""
$script:rbacTenantSlug = ""

# Test 8: Register for RBAC
Test-Api "Register Tenant for RBAC Testing" {
    $slug = "rbac-$(Get-Random -Minimum 1000 -Maximum 9999)"
    $body = @{
        tenantName = "RBAC Test Corp"
        tenantSlug = $slug
        subscriptionPlan = "Professional"
        adminEmail = "rbac@test.com"
        adminPassword = "Admin@1234"
        adminFullName = "RBAC Admin"
    } | ConvertTo-Json

    $response = Invoke-RestMethod -Uri "$baseUrl/api/tenants/register" `
        -Method Post -ContentType "application/json" -Body $body

    $script:rbacAccessToken = $response.accessToken
    $script:rbacRefreshToken = $response.refreshToken
    $script:rbacTenantSlug = $slug

    Write-Host "  Tenant: $slug" -ForegroundColor Gray
}

# Test 9: Verify TenantOwner Role
Test-Api "Verify TenantOwner Role Assignment" {
    $headers = @{ "Authorization" = "Bearer $($script:rbacAccessToken)" }
    $response = Invoke-RestMethod -Uri "$baseUrl/api/auth/me" -Method Get -Headers $headers

    if ($response.tenantRole -ne "TenantOwner" -or $response.role -ne "TenantOwner") {
        throw "Expected TenantOwner, got tenantRole=$($response.tenantRole), role=$($response.role)"
    }

    Write-Host "  Role: $($response.tenantRole)" -ForegroundColor Gray
}

# Test 10: Role Persistence
Test-Api "Role Persistence Across Login" {
    $body = @{
        tenantSlug = $script:rbacTenantSlug
        email = "rbac@test.com"
        password = "Admin@1234"
    } | ConvertTo-Json

    $response = Invoke-RestMethod -Uri "$baseUrl/api/auth/login" `
        -Method Post -ContentType "application/json" -Body $body

    $headers = @{ "Authorization" = "Bearer $($response.accessToken)" }
    $meResponse = Invoke-RestMethod -Uri "$baseUrl/api/auth/me" -Method Get -Headers $headers

    if ($meResponse.tenantRole -ne "TenantOwner") {
        throw "Role not persisted, got $($meResponse.tenantRole)"
    }

    Write-Host "  Role persisted after login" -ForegroundColor Gray
}

# Test 11: Role in Refreshed Token
Test-Api "Role Preserved in Refreshed Token" {
    $body = @{ refreshToken = $script:rbacRefreshToken } | ConvertTo-Json
    $response = Invoke-RestMethod -Uri "$baseUrl/api/auth/refresh" `
        -Method Post -ContentType "application/json" -Body $body

    $headers = @{ "Authorization" = "Bearer $($response.accessToken)" }
    $meResponse = Invoke-RestMethod -Uri "$baseUrl/api/auth/me" -Method Get -Headers $headers

    if ($meResponse.tenantRole -ne "TenantOwner") {
        throw "Role not preserved in refresh, got $($meResponse.tenantRole)"
    }

    Write-Host "  Role preserved after token refresh" -ForegroundColor Gray
}

# Test 12: JWT Claims
Test-Api "JWT Claims Inspection" {
    $headers = @{ "Authorization" = "Bearer $($script:rbacAccessToken)" }
    $response = Invoke-RestMethod -Uri "$baseUrl/api/auth/me" -Method Get -Headers $headers

    $required = @("userId", "email", "tenantRole", "role", "tenantId")
    foreach ($claim in $required) {
        if (-not $response.$claim) {
            throw "Missing claim: $claim"
        }
    }

    Write-Host "  All required claims present" -ForegroundColor Gray
}

# ============================================================================
# PHASE 3: REGRESSION TESTS
# ============================================================================

Write-Host "`n" -ForegroundColor Yellow
Write-Host "=====================================" -ForegroundColor Yellow
Write-Host "  PHASE 3: REGRESSION TESTS" -ForegroundColor Yellow
Write-Host "=====================================" -ForegroundColor Yellow

# Test 13: Password Hashing
Test-Api "Password Hashing (Day 4 Regression)" {
    $slug = "hash-$(Get-Random -Minimum 1000 -Maximum 9999)"
    $body = @{
        tenantName = "Hash Test"
        tenantSlug = $slug
        subscriptionPlan = "Free"
        adminEmail = "hash@test.com"
        adminPassword = "Password@123"
        adminFullName = "Hash Tester"
    } | ConvertTo-Json

    $regResponse = Invoke-RestMethod -Uri "$baseUrl/api/tenants/register" `
        -Method Post -ContentType "application/json" -Body $body

    # Try login
    $loginBody = @{
        tenantSlug = $slug
        email = "hash@test.com"
        password = "Password@123"
    } | ConvertTo-Json

    $loginResponse = Invoke-RestMethod -Uri "$baseUrl/api/auth/login" `
        -Method Post -ContentType "application/json" -Body $loginBody

    if (-not $loginResponse.accessToken) {
        throw "Login failed after registration"
    }

    Write-Host "  Password hashing working correctly" -ForegroundColor Gray
}

# Test 14: JWT Authentication
Test-Api "JWT Authentication (Day 4 Regression)" {
    $headers = @{ "Authorization" = "Bearer $($script:rbacAccessToken)" }
    $response = Invoke-RestMethod -Uri "$baseUrl/api/auth/me" -Method Get -Headers $headers

    if (-not $response.userId) {
        throw "JWT authentication failed"
    }

    Write-Host "  JWT authentication working" -ForegroundColor Gray
}

# ============================================================================
# TEST SUMMARY
# ============================================================================

Write-Host "`n" -ForegroundColor Magenta
Write-Host "===================================================" -ForegroundColor Magenta
Write-Host "  TEST EXECUTION SUMMARY" -ForegroundColor Magenta
Write-Host "===================================================" -ForegroundColor Magenta

Write-Host "`nTotal Tests:  $totalTests" -ForegroundColor White
Write-Host "Passed:       $passedTests" -ForegroundColor Green
Write-Host "Failed:       $failedTests" -ForegroundColor $(if ($failedTests -eq 0) { "Green" } else { "Red" })

$passRate = if ($totalTests -gt 0) { [math]::Round(($passedTests / $totalTests) * 100, 2) } else { 0 }
Write-Host "Pass Rate:    $passRate%" -ForegroundColor $(if ($passRate -ge 95) { "Green" } elseif ($passRate -ge 80) { "Yellow" } else { "Red" })

if ($failedTests -gt 0) {
    Write-Host "`nFailed Tests:" -ForegroundColor Red
    foreach ($error in $errors) {
        Write-Host "  - $($error.Name)" -ForegroundColor Red
        Write-Host "    $($error.Error)" -ForegroundColor DarkRed
    }
}

Write-Host "`n===================================================" -ForegroundColor Magenta
Write-Host "  DEPLOYMENT RECOMMENDATION" -ForegroundColor Magenta
Write-Host "===================================================" -ForegroundColor Magenta

if ($passRate -eq 100) {
    Write-Host "`n[EXCELLENT] All tests passed. Ready for production!" -ForegroundColor Green
    Write-Host "Recommendation: DEPLOY" -ForegroundColor Green
    exit 0
} elseif ($passRate -ge 95) {
    Write-Host "`n[GOOD] Minor issues found. Review failed tests." -ForegroundColor Yellow
    Write-Host "Recommendation: CONDITIONAL DEPLOY" -ForegroundColor Yellow
    exit 0
} elseif ($passRate -ge 80) {
    Write-Host "`n[WARNING] Multiple issues found. Fix before deploy." -ForegroundColor Yellow
    Write-Host "Recommendation: DO NOT DEPLOY" -ForegroundColor Yellow
    exit 1
} else {
    Write-Host "`n[CRITICAL] Major issues found. DO NOT DEPLOY!" -ForegroundColor Red
    Write-Host "Recommendation: DO NOT DEPLOY" -ForegroundColor Red
    exit 1
}
