/**
 * Rate Limiting Functionality Test
 *
 * Tests that rate limiting is working correctly on authentication endpoints.
 * Verifies that requests are blocked after exceeding limits and that proper
 * headers are returned.
 *
 * Prerequisites: Web server running on http://127.0.0.1:5000
 *
 * Usage: node tests/ui_tests/test_rate_limiting_settings.js
 */

const puppeteer = require('puppeteer');
const { getPuppeteerLaunchOptions } = require('./puppeteer_config');

async function testRateLimiting() {
    // Skip this test in CI unless ENABLE_RATE_LIMITING=true
    // Rate limiting is disabled in CI by default, so this test would fail
    if (process.env.CI && process.env.ENABLE_RATE_LIMITING !== 'true') {
        console.log('⚠️  Skipping rate limiting test in CI (requires ENABLE_RATE_LIMITING=true)');
        console.log('ℹ️  This test needs rate limiting enabled, but CI disables it by default');
        return;  // Caller awaits but doesn't use return value
    }

    const browser = await puppeteer.launch(getPuppeteerLaunchOptions());
    const page = await browser.newPage();
    const baseUrl = 'http://127.0.0.1:5000';

    try {
        console.log('🚀 Starting rate limiting functionality test...');

        // Test 1: Test login rate limiting (5 per 15 minutes)
        console.log('\n🔍 Test 1: Login endpoint should be rate limited (5 attempts per 15 min)');

        await page.goto(`${baseUrl}/auth/login`, { waitUntil: 'domcontentloaded' });

        let loginAttempts = 0;
        let rateLimitTriggered = false;

        // Make login attempts until rate limited
        for (let i = 0; i < 10; i++) {
            const response = await page.evaluate(async (url) => {
                const res = await fetch(`${url}/api/v1/auth/login`, {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json',
                    },
                    body: JSON.stringify({
                        username: 'testuser_nonexistent',
                        password: 'wrongpassword'  // gitleaks:allow
                    })
                });

                return {
                    status: res.status,
                    headers: {
                        ratelimitLimit: res.headers.get('X-RateLimit-Limit'),
                        ratelimitRemaining: res.headers.get('X-RateLimit-Remaining'),
                        ratelimitReset: res.headers.get('X-RateLimit-Reset')
                    }
                };
            }, baseUrl);

            loginAttempts++;

            if (response.status === 429) {
                console.log(`✅ Rate limit triggered after ${loginAttempts} login attempts`);
                console.log(`📊 Rate limit headers:`, response.headers);
                rateLimitTriggered = true;
                break;
            } else {
                console.log(`📍 Login attempt ${loginAttempts}: status ${response.status}, remaining: ${response.headers.ratelimitRemaining}`);
            }

            // Small delay between requests
            await new Promise(resolve => setTimeout(resolve, 100));
        }

        if (!rateLimitTriggered) {
            console.log('❌ Rate limit was not triggered after 10 login attempts');
            throw new Error('Login rate limiting is not working');
        }

        if (loginAttempts > 6) {
            console.log(`⚠️  Rate limit triggered later than expected (after ${loginAttempts} attempts, expected ~5)`);
        }

        // Test 2: Test registration rate limiting (3 per hour)
        console.log('\n🔍 Test 2: Registration endpoint should be rate limited (3 attempts per hour)');

        // Use a different page context to reset cookies/session
        const page2 = await browser.newPage();
        await page2.goto(`${baseUrl}/auth/register`, { waitUntil: 'domcontentloaded' });

        let registrationAttempts = 0;
        let regRateLimitTriggered = false;

        // Make registration attempts until rate limited
        for (let i = 0; i < 10; i++) {
            const response = await page2.evaluate(async (url, attemptNum) => {
                const res = await fetch(`${url}/api/v1/auth/register`, {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json',
                    },
                    body: JSON.stringify({
                        username: `testuser_ratelimit_${Date.now()}_${attemptNum}`,
                        password: 'testpassword123'  // gitleaks:allow
                    })
                });

                return {
                    status: res.status,
                    headers: {
                        ratelimitLimit: res.headers.get('X-RateLimit-Limit'),
                        ratelimitRemaining: res.headers.get('X-RateLimit-Remaining'),
                        ratelimitReset: res.headers.get('X-RateLimit-Reset')
                    }
                };
            }, baseUrl, i);

            registrationAttempts++;

            if (response.status === 429) {
                console.log(`✅ Rate limit triggered after ${registrationAttempts} registration attempts`);
                console.log(`📊 Rate limit headers:`, response.headers);
                regRateLimitTriggered = true;
                break;
            } else {
                console.log(`📍 Registration attempt ${registrationAttempts}: status ${response.status}, remaining: ${response.headers.ratelimitRemaining}`);
            }

            // Small delay between requests
            await new Promise(resolve => setTimeout(resolve, 100));
        }

        if (!regRateLimitTriggered) {
            console.log('❌ Rate limit was not triggered after 10 registration attempts');
            throw new Error('Registration rate limiting is not working');
        }

        if (registrationAttempts > 4) {
            console.log(`⚠️  Rate limit triggered later than expected (after ${registrationAttempts} attempts, expected ~3)`);
        }

        await page2.close();

        // Test 3: Verify 429 error response format
        console.log('\n🔍 Test 3: Verify 429 error response format');

        const errorResponse = await page.evaluate(async (url) => {
            const res = await fetch(`${url}/api/v1/auth/login`, {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                },
                body: JSON.stringify({
                    username: 'testuser',
                    password: 'testpass'  // gitleaks:allow
                })
            });

            const body = await res.json();
            return {
                status: res.status,
                body
            };
        }, baseUrl);

        if (errorResponse.status === 429) {
            console.log('✅ 429 status code returned correctly');
            console.log('📊 Error response body:', errorResponse.body);

            if (errorResponse.body.error && errorResponse.body.message) {
                console.log('✅ Error response has correct format (error and message fields)');
            } else {
                console.log('⚠️  Error response format unexpected:', errorResponse.body);
            }
        } else {
            console.log(`ℹ️  Rate limit may have reset, got status ${errorResponse.status}`);
        }

        // Summary
        console.log('\n📊 Test Summary:');
        console.log(`✅ Login rate limiting (5 per 15 min): PASS (triggered after ${loginAttempts} attempts)`);
        console.log(`✅ Registration rate limiting (3 per hour): PASS (triggered after ${registrationAttempts} attempts)`);
        console.log(`✅ Error response format: PASS`);

        console.log('\n🎉 Rate limiting functionality test completed successfully');

    } catch (error) {
        console.error('❌ Error during rate limiting test:', error);
        throw error;
    } finally {
        await browser.close();
    }
}

// Run the test
if (require.main === module) {
    testRateLimiting()
        .then(() => {
            console.log('✅ All rate limiting tests completed');
            process.exit(0);
        })
        .catch(error => {
            console.error('❌ Rate limiting tests failed:', error);
            process.exit(1);
        });
}

module.exports = { testRateLimiting };
