# ColaFlow Day 5 Comprehensive Integration Test Suite
# Tests: Refresh Token + RBAC Implementation

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

# Test Results Tracking
$testResults = @{
    Total = 0
    Passed = 0
    Failed = 0
    Errors = @()
}

function Write-TestHeader {
    param($TestName)
    Write-Host "`n========================================" -ForegroundColor Cyan
    Write-Host "$TestName" -ForegroundColor Cyan
    Write-Host "========================================" -ForegroundColor Cyan
    $testResults.Total++
}

function Write-TestSuccess {
    param($Message)
    Write-Host "✅ $Message" -ForegroundColor Green
    $testResults.Passed++
}

function Write-TestFailure {
    param($Message, $Error)
    Write-Host "❌ $Message" -ForegroundColor Red
    Write-Host "   Error: $Error" -ForegroundColor DarkRed
    $testResults.Failed++
    $testResults.Errors += @{Message=$Message; Error=$Error}
}

function Write-TestInfo {
    param($Message)
    Write-Host "   $Message" -ForegroundColor Gray
}

# Wait for API to start
Write-Host "Waiting for API server to start..." -ForegroundColor Yellow
Start-Sleep -Seconds 5

# Check if API is running
try {
    $healthCheck = Invoke-RestMethod -Uri "$baseUrl/api/auth/me" -Method Get 2>&1
} catch {
    Write-Host "Waiting additional time for API startup..." -ForegroundColor Yellow
    Start-Sleep -Seconds 5
}

Write-Host "`n╔════════════════════════════════════════════════════════╗" -ForegroundColor Magenta
Write-Host "║   ColaFlow Day 5 Integration Test Suite               ║" -ForegroundColor Magenta
Write-Host "║   Testing: Refresh Token + RBAC                       ║" -ForegroundColor Magenta
Write-Host "╚════════════════════════════════════════════════════════╝" -ForegroundColor Magenta

# ============================================================================
# Phase 1: Refresh Token Tests
# ============================================================================

Write-Host "`n┌────────────────────────────────────────┐" -ForegroundColor Yellow
Write-Host "│  PHASE 1: REFRESH TOKEN TESTS          │" -ForegroundColor Yellow
Write-Host "└────────────────────────────────────────┘" -ForegroundColor Yellow

# Test 1: Register Tenant - Get Access & Refresh Token
Write-TestHeader "Test 1: Register Tenant (Get Tokens)"
$tenantSlug = "test-$(Get-Random -Minimum 1000 -Maximum 9999)"
$registerBody = @{
    tenantName = "Test Corp Day 5"
    tenantSlug = $tenantSlug
    subscriptionPlan = "Professional"
    adminEmail = "admin@testday5.com"
    adminPassword = "Admin@1234"
    adminFullName = "Test Admin"
} | ConvertTo-Json

try {
    $registerResponse = Invoke-RestMethod -Uri "$baseUrl/api/tenants/register" `
        -Method Post -ContentType "application/json" -Body $registerBody

    $accessToken1 = $registerResponse.accessToken
    $refreshToken1 = $registerResponse.refreshToken
    $tenantId = $registerResponse.tenant.id

    if ($accessToken1 -and $refreshToken1) {
        Write-TestSuccess "Tenant registered with access token and refresh token"
        Write-TestInfo "Tenant ID: $tenantId"
        Write-TestInfo "Access Token Length: $($accessToken1.Length)"
        Write-TestInfo "Refresh Token Length: $($refreshToken1.Length)"
    } else {
        Write-TestFailure "Registration did not return both tokens" "Missing tokens"
    }
} catch {
    Write-TestFailure "Tenant registration failed" $_.Exception.Message
    Write-Host "`nCRITICAL: Cannot proceed without successful registration. Exiting." -ForegroundColor Red
    exit 1
}

# Test 2: Use Access Token to Access Protected Endpoint
Write-TestHeader "Test 2: Access Protected Endpoint with Access Token"
try {
    $headers = @{
        "Authorization" = "Bearer $accessToken1"
    }
    $meResponse1 = Invoke-RestMethod -Uri "$baseUrl/api/auth/me" -Method Get -Headers $headers

    if ($meResponse1.userId -and $meResponse1.email) {
        Write-TestSuccess "Access token works for protected endpoint"
        Write-TestInfo "User ID: $($meResponse1.userId)"
        Write-TestInfo "Email: $($meResponse1.email)"
    } else {
        Write-TestFailure "Protected endpoint did not return expected data" "Missing user data"
    }
} catch {
    Write-TestFailure "Failed to access protected endpoint" $_.Exception.Message
}

# Test 3: Refresh Access Token
Write-TestHeader "Test 3: Refresh Access Token (Token Rotation)"
try {
    $refreshBody = @{
        refreshToken = $refreshToken1
    } | ConvertTo-Json

    $refreshResponse1 = Invoke-RestMethod -Uri "$baseUrl/api/auth/refresh" `
        -Method Post -ContentType "application/json" -Body $refreshBody

    $accessToken2 = $refreshResponse1.accessToken
    $refreshToken2 = $refreshResponse1.refreshToken

    if ($accessToken2 -and $refreshToken2 -and $accessToken2 -ne $accessToken1 -and $refreshToken2 -ne $refreshToken1) {
        Write-TestSuccess "Token refresh successful (new tokens generated)"
        Write-TestInfo "New Access Token: $($accessToken2.Substring(0, 20))..."
        Write-TestInfo "New Refresh Token: $($refreshToken2.Substring(0, 20))..."
    } else {
        Write-TestFailure "Token refresh failed or did not rotate tokens" "Token rotation failed"
    }
} catch {
    Write-TestFailure "Token refresh request failed" $_.Exception.Message
}

# Test 4: Try Using Old Refresh Token (Should Fail - Token Reuse Detection)
Write-TestHeader "Test 4: Token Reuse Detection (Security Test)"
try {
    $oldRefreshBody = @{
        refreshToken = $refreshToken1
    } | ConvertTo-Json

    try {
        $shouldFail = Invoke-RestMethod -Uri "$baseUrl/api/auth/refresh" `
            -Method Post -ContentType "application/json" -Body $oldRefreshBody

        Write-TestFailure "Old refresh token was accepted (security vulnerability!)" "Token reuse not detected"
    } catch {
        $statusCode = $_.Exception.Response.StatusCode.value__
        if ($statusCode -eq 401) {
            Write-TestSuccess "Old refresh token correctly rejected (401 Unauthorized)"
            Write-TestInfo "Token reuse detection working correctly"
        } else {
            Write-TestFailure "Unexpected status code: $statusCode" "Expected 401"
        }
    }
} catch {
    Write-TestFailure "Token reuse detection test failed" $_.Exception.Message
}

# Test 5: Use New Access Token
Write-TestHeader "Test 5: New Access Token Works"
try {
    $headers2 = @{
        "Authorization" = "Bearer $accessToken2"
    }
    $meResponse2 = Invoke-RestMethod -Uri "$baseUrl/api/auth/me" -Method Get -Headers $headers2

    if ($meResponse2.userId -eq $meResponse1.userId) {
        Write-TestSuccess "New access token works for same user"
        Write-TestInfo "User ID matches: $($meResponse2.userId)"
    } else {
        Write-TestFailure "New access token returned different user" "User ID mismatch"
    }
} catch {
    Write-TestFailure "New access token failed" $_.Exception.Message
}

# Test 6: Logout (Revoke Refresh Token)
Write-TestHeader "Test 6: Logout (Revoke Refresh Token)"
try {
    $logoutBody = @{
        refreshToken = $refreshToken2
    } | ConvertTo-Json

    $logoutResponse = Invoke-RestMethod -Uri "$baseUrl/api/auth/logout" `
        -Method Post -ContentType "application/json" -Body $logoutBody

    if ($logoutResponse.message -like "*success*") {
        Write-TestSuccess "Logout successful"
        Write-TestInfo $logoutResponse.message
    } else {
        Write-TestFailure "Logout did not return success message" $logoutResponse
    }
} catch {
    Write-TestFailure "Logout request failed" $_.Exception.Message
}

# Test 7: Try Using Revoked Token (Should Fail)
Write-TestHeader "Test 7: Revoked Token Cannot Be Used"
try {
    $revokedRefreshBody = @{
        refreshToken = $refreshToken2
    } | ConvertTo-Json

    try {
        $shouldFail2 = Invoke-RestMethod -Uri "$baseUrl/api/auth/refresh" `
            -Method Post -ContentType "application/json" -Body $revokedRefreshBody

        Write-TestFailure "Revoked token was accepted (security issue!)" "Revoked token still works"
    } catch {
        $statusCode = $_.Exception.Response.StatusCode.value__
        if ($statusCode -eq 401) {
            Write-TestSuccess "Revoked token correctly rejected (401)"
        } else {
            Write-TestFailure "Unexpected status code: $statusCode" "Expected 401"
        }
    }
} catch {
    Write-TestFailure "Revoked token test failed" $_.Exception.Message
}

# ============================================================================
# Phase 2: RBAC Tests
# ============================================================================

Write-Host "`n┌────────────────────────────────────────┐" -ForegroundColor Yellow
Write-Host "│  PHASE 2: RBAC TESTS                   │" -ForegroundColor Yellow
Write-Host "└────────────────────────────────────────┘" -ForegroundColor Yellow

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

try {
    $registerResponse2 = Invoke-RestMethod -Uri "$baseUrl/api/tenants/register" `
        -Method Post -ContentType "application/json" -Body $registerBody2

    $rbacAccessToken = $registerResponse2.accessToken
    $rbacRefreshToken = $registerResponse2.refreshToken

    Write-TestSuccess "RBAC test tenant registered"
    Write-TestInfo "Tenant Slug: $tenantSlug2"
} catch {
    Write-TestFailure "RBAC tenant registration failed" $_.Exception.Message
}

# Test 9: Verify TenantOwner Role in JWT
Write-TestHeader "Test 9: Verify TenantOwner Role Assignment"
try {
    $rbacHeaders = @{
        "Authorization" = "Bearer $rbacAccessToken"
    }
    $rbacMe = Invoke-RestMethod -Uri "$baseUrl/api/auth/me" -Method Get -Headers $rbacHeaders

    if ($rbacMe.tenantRole -eq "TenantOwner" -and $rbacMe.role -eq "TenantOwner") {
        Write-TestSuccess "TenantOwner role correctly assigned"
        Write-TestInfo "Tenant Role: $($rbacMe.tenantRole)"
        Write-TestInfo "Standard Role: $($rbacMe.role)"
    } else {
        Write-TestFailure "Expected TenantOwner role" "Got: tenant_role=$($rbacMe.tenantRole), role=$($rbacMe.role)"
    }
} catch {
    Write-TestFailure "Failed to verify role assignment" $_.Exception.Message
}

# Test 10: Login and Verify Role Persistence
Write-TestHeader "Test 10: Role Persistence Across Login"
try {
    $loginBody = @{
        tenantSlug = $tenantSlug2
        email = "rbac@test.com"
        password = "Admin@1234"
    } | ConvertTo-Json

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

    $loginAccessToken = $loginResponse.accessToken
    $loginHeaders = @{
        "Authorization" = "Bearer $loginAccessToken"
    }
    $loginMe = Invoke-RestMethod -Uri "$baseUrl/api/auth/me" -Method Get -Headers $loginHeaders

    if ($loginMe.tenantRole -eq "TenantOwner") {
        Write-TestSuccess "Role persisted after login"
        Write-TestInfo "Role after login: $($loginMe.tenantRole)"
    } else {
        Write-TestFailure "Role not persisted after login" "Got: $($loginMe.tenantRole)"
    }
} catch {
    Write-TestFailure "Login role persistence test failed" $_.Exception.Message
}

# Test 11: Refresh Token Preserves Role
Write-TestHeader "Test 11: Role Preserved in Refreshed Token"
try {
    $refreshBody3 = @{
        refreshToken = $rbacRefreshToken
    } | ConvertTo-Json

    $refreshResponse3 = Invoke-RestMethod -Uri "$baseUrl/api/auth/refresh" `
        -Method Post -ContentType "application/json" -Body $refreshBody3

    $refreshedAccessToken = $refreshResponse3.accessToken
    $refreshedHeaders = @{
        "Authorization" = "Bearer $refreshedAccessToken"
    }
    $refreshedMe = Invoke-RestMethod -Uri "$baseUrl/api/auth/me" -Method Get -Headers $refreshedHeaders

    if ($refreshedMe.tenantRole -eq "TenantOwner") {
        Write-TestSuccess "Role preserved in refreshed token"
        Write-TestInfo "Role after refresh: $($refreshedMe.tenantRole)"
    } else {
        Write-TestFailure "Role not preserved in refreshed token" "Got: $($refreshedMe.tenantRole)"
    }
} catch {
    Write-TestFailure "Refreshed token role test failed" $_.Exception.Message
}

# Test 12: JWT Claims Inspection
Write-TestHeader "Test 12: Inspect JWT Claims"
try {
    $rbacHeaders = @{
        "Authorization" = "Bearer $rbacAccessToken"
    }
    $claimsResponse = Invoke-RestMethod -Uri "$baseUrl/api/auth/me" -Method Get -Headers $rbacHeaders

    $hasUserId = $claimsResponse.userId -ne $null
    $hasEmail = $claimsResponse.email -ne $null
    $hasTenantRole = $claimsResponse.tenantRole -ne $null
    $hasRole = $claimsResponse.role -ne $null
    $hasTenantId = $claimsResponse.tenantId -ne $null

    if ($hasUserId -and $hasEmail -and $hasTenantRole -and $hasRole -and $hasTenantId) {
        Write-TestSuccess "All required JWT claims present"
        Write-TestInfo "Claims: user_id, email, tenant_role, role, tenant_id"
    } else {
        Write-TestFailure "Missing JWT claims" "userId=$hasUserId, email=$hasEmail, tenantRole=$hasTenantRole, role=$hasRole, tenantId=$hasTenantId"
    }
} catch {
    Write-TestFailure "JWT claims inspection failed" $_.Exception.Message
}

# ============================================================================
# Phase 3: Regression Tests (Day 4 Functionality)
# ============================================================================

Write-Host "`n┌────────────────────────────────────────┐" -ForegroundColor Yellow
Write-Host "│  PHASE 3: REGRESSION TESTS             │" -ForegroundColor Yellow
Write-Host "└────────────────────────────────────────┘" -ForegroundColor Yellow

# Test 13: Password Hashing Still Works
Write-TestHeader "Test 13: Password Hashing (Regression)"
try {
    $testSlug = "hash-test-$(Get-Random -Minimum 1000 -Maximum 9999)"
    $hashTestBody = @{
        tenantName = "Hash Test"
        tenantSlug = $testSlug
        subscriptionPlan = "Free"
        adminEmail = "hash@test.com"
        adminPassword = "Password@123"
        adminFullName = "Hash Tester"
    } | ConvertTo-Json

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

    # Try login with correct password
    $loginHashBody = @{
        tenantSlug = $testSlug
        email = "hash@test.com"
        password = "Password@123"
    } | ConvertTo-Json

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

    if ($loginHashResponse.accessToken) {
        Write-TestSuccess "Password hashing and verification working"
    } else {
        Write-TestFailure "Password hashing regression detected" "Login failed"
    }
} catch {
    Write-TestFailure "Password hashing test failed" $_.Exception.Message
}

# Test 14: JWT Still Works
Write-TestHeader "Test 14: JWT Authentication (Regression)"
try {
    $headers = @{
        "Authorization" = "Bearer $accessToken1"
    }
    $regMeResponse = Invoke-RestMethod -Uri "$baseUrl/api/auth/me" -Method Get -Headers $headers 2>&1

    # Access token1 might be revoked due to token family revocation
    # Use a fresh token instead
    $headers = @{
        "Authorization" = "Bearer $rbacAccessToken"
    }
    $regMeResponse = Invoke-RestMethod -Uri "$baseUrl/api/auth/me" -Method Get -Headers $headers

    if ($regMeResponse.userId) {
        Write-TestSuccess "JWT authentication still working (Day 4 regression test passed)"
    } else {
        Write-TestFailure "JWT authentication regression" "No user data returned"
    }
} catch {
    Write-TestFailure "JWT regression test failed" $_.Exception.Message
}

# ============================================================================
# Test Summary
# ============================================================================

Write-Host "`n╔════════════════════════════════════════════════════════╗" -ForegroundColor Magenta
Write-Host "║   TEST EXECUTION SUMMARY                               ║" -ForegroundColor Magenta
Write-Host "╚════════════════════════════════════════════════════════╝" -ForegroundColor Magenta

Write-Host "`nTotal Tests: $($testResults.Total)" -ForegroundColor White
Write-Host "Passed:      $($testResults.Passed)" -ForegroundColor Green
Write-Host "Failed:      $($testResults.Failed)" -ForegroundColor $(if ($testResults.Failed -eq 0) { "Green" } else { "Red" })

$passRate = [math]::Round(($testResults.Passed / $testResults.Total) * 100, 2)
Write-Host "Pass Rate:   $passRate%" -ForegroundColor $(if ($passRate -ge 90) { "Green" } elseif ($passRate -ge 70) { "Yellow" } else { "Red" })

if ($testResults.Failed -gt 0) {
    Write-Host "`n❌ FAILED TESTS:" -ForegroundColor Red
    foreach ($error in $testResults.Errors) {
        Write-Host "  - $($error.Message)" -ForegroundColor Red
        Write-Host "    $($error.Error)" -ForegroundColor DarkRed
    }
}

Write-Host "`n┌────────────────────────────────────────┐" -ForegroundColor Cyan
Write-Host "│  FEATURE COVERAGE                      │" -ForegroundColor Cyan
Write-Host "└────────────────────────────────────────┘" -ForegroundColor Cyan

Write-Host "Phase 1 - Refresh Token:"
Write-Host "  ✓ Token generation (register/login)"
Write-Host "  ✓ Token refresh and rotation"
Write-Host "  ✓ Token reuse detection"
Write-Host "  ✓ Token revocation (logout)"
Write-Host "  ✓ Security validation"

Write-Host "`nPhase 2 - RBAC:"
Write-Host "  ✓ Role assignment (TenantOwner)"
Write-Host "  ✓ JWT role claims"
Write-Host "  ✓ Role persistence (login)"
Write-Host "  ✓ Role preservation (refresh)"
Write-Host "  ✓ Claims inspection"

Write-Host "`nPhase 3 - Regression:"
Write-Host "  ✓ Password hashing (Day 4)"
Write-Host "  ✓ JWT authentication (Day 4)"

Write-Host "`n╔════════════════════════════════════════════════════════╗" -ForegroundColor Magenta
Write-Host "║   QUALITY ASSESSMENT                                   ║" -ForegroundColor Magenta
Write-Host "╚════════════════════════════════════════════════════════╝" -ForegroundColor Magenta

if ($passRate -ge 95) {
    Write-Host "`n✅ EXCELLENT - All tests passed. Ready for production!" -ForegroundColor Green
    exit 0
} elseif ($passRate -ge 80) {
    Write-Host "`n⚠️  GOOD - Minor issues found. Review failed tests." -ForegroundColor Yellow
    exit 1
} else {
    Write-Host "`n❌ CRITICAL - Major issues found. DO NOT DEPLOY!" -ForegroundColor Red
    exit 1
}
