/**
 * Test script for Phase 7: Advanced Rate Limiting + Header Redaction
 * Tests the new rate limiting system and header redaction functionality
 */

const http = require('http');

const BASE_URL = 'http://localhost:3333';

// Helper function to make HTTP requests
function makeRequest(options, data = null) {
  return new Promise((resolve, reject) => {
    const req = http.request(options, (res) => {
      let body = '';
      res.on('data', (chunk) => body += chunk);
      res.on('end', () => {
        try {
          const result = {
            statusCode: res.statusCode,
            headers: res.headers,
            body: res.headers['content-type'] && res.headers['content-type'].includes('application/json') 
              ? JSON.parse(body) 
              : body
          };
          resolve(result);
        } catch (error) {
          resolve({
            statusCode: res.statusCode,
            headers: res.headers,
            body: body
          });
        }
      });
    });

    req.on('error', reject);
    
    if (data) {
      if (typeof data === 'string') {
        req.write(data);
      } else {
        req.write(JSON.stringify(data));
      }
    }
    
    req.end();
  });
}

// Helper function to sleep
function sleep(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

async function runTests() {
  console.log('🧪 Starting Phase 7: Advanced Rate Limiting + Header Redaction Tests\n');

  let authToken = null;

  // Test 1: User Registration/Login
  console.log('1️⃣ Testing user authentication...');
  try {
    const loginResult = await makeRequest({
      hostname: 'localhost',
      port: 3333,
      path: '/api/v1/auth/login',
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
    }, {
      email: 'rate-test@example.com',
      password: 'ratetest123'
    });

    if (loginResult.statusCode === 200 && loginResult.body.success) {
      authToken = loginResult.body.data.token;
      console.log('✅ User login successful');
    } else {
      // Try to register if login fails
      const registerResult = await makeRequest({
        hostname: 'localhost',
        port: 3333,
        path: '/api/v1/auth/register',
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
      }, {
        email: 'rate-test@example.com',
        name: 'Rate Test User',
        password: 'ratetest123',
        organizationName: 'Rate Test Org'
      });

      if (registerResult.statusCode === 201 && registerResult.body.success) {
        authToken = registerResult.body.data.token;
        console.log('✅ User registration successful');
      } else {
        console.log('❌ Authentication failed:', registerResult.body);
        return;
      }
    }
  } catch (error) {
    console.log('❌ Authentication error:', error.message);
    return;
  }

  // Test 2: Rate Limit Headers
  console.log('\n2️⃣ Testing rate limit headers...');
  try {
    const trackResult = await makeRequest({
      hostname: 'localhost',
      port: 3333,
      path: '/api/v2/track',
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${authToken}`,
      },
    }, {
      url: 'https://example.com'
    });

    console.log('Status Code:', trackResult.statusCode);
    console.log('Rate Limit Headers:');
    console.log('  X-RateLimit-Limit:', trackResult.headers['x-ratelimit-limit']);
    console.log('  X-RateLimit-Remaining:', trackResult.headers['x-ratelimit-remaining']);
    console.log('  X-RateLimit-Reset:', trackResult.headers['x-ratelimit-reset']);
    console.log('  X-RateLimit-Tier:', trackResult.headers['x-ratelimit-tier']);

    if (trackResult.headers['x-ratelimit-limit']) {
      console.log('✅ Rate limit headers present');
    } else {
      console.log('⚠️ Rate limit headers missing');
    }
  } catch (error) {
    console.log('❌ Rate limit headers test error:', error.message);
  }

  // Test 3: Anonymous vs Authenticated Rate Limits
  console.log('\n3️⃣ Testing anonymous vs authenticated rate limits...');
  try {
    // Anonymous request
    const anonResult = await makeRequest({
      hostname: 'localhost',
      port: 3333,
      path: '/api/v2/track',
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
    }, {
      url: 'https://httpbin.org/get'
    });

    console.log('Anonymous Request:');
    console.log('  Limit:', anonResult.headers['x-ratelimit-limit']);
    console.log('  Tier:', anonResult.headers['x-ratelimit-tier']);

    // Authenticated request
    const authResult = await makeRequest({
      hostname: 'localhost',
      port: 3333,
      path: '/api/v2/track',
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${authToken}`,
      },
    }, {
      url: 'https://httpbin.org/get'
    });

    console.log('Authenticated Request:');
    console.log('  Limit:', authResult.headers['x-ratelimit-limit']);
    console.log('  Tier:', authResult.headers['x-ratelimit-tier']);

    const anonLimit = parseInt(anonResult.headers['x-ratelimit-limit'] || '0');
    const authLimit = parseInt(authResult.headers['x-ratelimit-limit'] || '0');

    if (authLimit > anonLimit) {
      console.log('✅ Authenticated users have higher rate limits');
    } else {
      console.log('⚠️ Rate limit difference not detected');
    }
  } catch (error) {
    console.log('❌ Rate limit comparison error:', error.message);
  }

  // Test 4: Legacy Endpoint Rate Limiting
  console.log('\n4️⃣ Testing legacy endpoint rate limiting...');
  try {
    const legacyResult = await makeRequest({
      hostname: 'localhost',
      port: 3333,
      path: '/api/track',
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
    }, {
      url: 'https://example.com'
    });

    console.log('Legacy endpoint status:', legacyResult.statusCode);
    console.log('Legacy rate limit:', legacyResult.headers['x-ratelimit-limit']);

    if (legacyResult.headers['x-ratelimit-limit']) {
      console.log('✅ Legacy endpoints have rate limiting');
    } else {
      console.log('⚠️ Legacy endpoints missing rate limiting');
    }
  } catch (error) {
    console.log('❌ Legacy rate limiting test error:', error.message);
  }

  // Test 5: Burst Protection
  console.log('\n5️⃣ Testing burst protection...');
  try {
    console.log('Making rapid authenticated requests...');
    const requests = [];
    
    for (let i = 0; i < 15; i++) {
      requests.push(
        makeRequest({
          hostname: 'localhost',
          port: 3333,
          path: '/api/v2/track',
          method: 'POST',
          headers: {
            'Content-Type': 'application/json',
            'Authorization': `Bearer ${authToken}`,
          },
        }, {
          url: `https://httpbin.org/delay/0`,
          timeout: 5000
        })
      );
    }

    const results = await Promise.allSettled(requests);
    const statusCodes = results.map(r => r.status === 'fulfilled' ? r.value.statusCode : 'error');
    const rateLimited = statusCodes.filter(code => code === 429).length;
    const successful = statusCodes.filter(code => code === 200 || code === 201).length;

    console.log(`Results: ${successful} successful, ${rateLimited} rate limited`);
    
    if (rateLimited > 0) {
      console.log('✅ Burst protection is working');
    } else {
      console.log('⚠️ Burst protection may not be active (or limits are very high)');
    }
  } catch (error) {
    console.log('❌ Burst protection test error:', error.message);
  }

  // Test 6: Header Redaction (indirect test via response logs)
  console.log('\n6️⃣ Testing header redaction...');
  try {
    const sensitiveHeadersResult = await makeRequest({
      hostname: 'localhost',
      port: 3333,
      path: '/api/v2/track',
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${authToken}`,
        'X-Secret-Key': 'secret123',
        'Cookie': 'session=abc123',
        'X-API-Key': 'api_key_12345',
        'User-Agent': 'RedirectIntelligence Test Client v1.0',
      },
    }, {
      url: 'https://httpbin.org/headers'
    });

    console.log('Request with sensitive headers sent');
    console.log('Status:', sensitiveHeadersResult.statusCode);
    
    // Check if the request was processed (indicating headers were handled properly)
    if (sensitiveHeadersResult.statusCode === 200 || sensitiveHeadersResult.statusCode === 201) {
      console.log('✅ Request with sensitive headers processed successfully');
      console.log('   (Header redaction occurs server-side in logs/storage)');
    } else {
      console.log('⚠️ Request with sensitive headers failed');
    }
  } catch (error) {
    console.log('❌ Header redaction test error:', error.message);
  }

  // Test 7: Bulk Rate Limiting
  console.log('\n7️⃣ Testing bulk endpoint rate limiting...');
  try {
    const bulkResult = await makeRequest({
      hostname: 'localhost',
      port: 3333,
      path: '/api/v2/bulk/jobs',
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${authToken}`,
      },
    }, {
      urls: [
        { url: 'https://example.com', label: 'Test 1' }
      ]
    });

    console.log('Bulk endpoint status:', bulkResult.statusCode);
    console.log('Bulk rate limit tier:', bulkResult.headers['x-ratelimit-tier']);
    console.log('Bulk rate limit:', bulkResult.headers['x-ratelimit-limit']);

    if (bulkResult.headers['x-ratelimit-tier']) {
      console.log('✅ Bulk endpoints have tier-based rate limiting');
    } else {
      console.log('⚠️ Bulk rate limiting not detected');
    }
  } catch (error) {
    console.log('❌ Bulk rate limiting test error:', error.message);
  }

  // Test 8: Rate Limit Exceeded Response
  console.log('\n8️⃣ Testing rate limit exceeded response...');
  try {
    console.log('Making requests to approach rate limit...');
    let lastResponse = null;
    
    // Make many requests quickly to trigger rate limiting
    for (let i = 0; i < 60; i++) {
      try {
        const response = await makeRequest({
          hostname: 'localhost',
          port: 3333,
          path: '/api/track', // Use legacy endpoint for predictable low limits
          method: 'POST',
          headers: {
            'Content-Type': 'application/json',
          },
        }, {
          url: 'https://httpbin.org/get'
        });
        
        lastResponse = response;
        
        if (response.statusCode === 429) {
          console.log('✅ Rate limit exceeded (429) response received');
          console.log('Response body:', response.body);
          console.log('Retry-After header:', response.headers['retry-after']);
          console.log('X-RateLimit headers:', {
            limit: response.headers['x-ratelimit-limit'],
            remaining: response.headers['x-ratelimit-remaining'],
            reset: response.headers['x-ratelimit-reset'],
          });
          break;
        }
        
        // Small delay to avoid overwhelming the server
        await sleep(50);
      } catch (error) {
        console.log('Request error (expected for rate limiting):', error.message);
      }
    }
    
    if (!lastResponse || lastResponse.statusCode !== 429) {
      console.log('⚠️ Rate limit not triggered (limits may be too high for testing)');
    }
  } catch (error) {
    console.log('❌ Rate limit exceeded test error:', error.message);
  }

  // Test 9: Different User Agent Handling
  console.log('\n9️⃣ Testing different user agent handling...');
  try {
    const userAgents = [
      'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
      'curl/7.68.0',
      'RedirectIntelligence/2.0 TestClient',
    ];

    for (const ua of userAgents) {
      const result = await makeRequest({
        hostname: 'localhost',
        port: 3333,
        path: '/api/v2/track',
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'Authorization': `Bearer ${authToken}`,
          'User-Agent': ua,
        },
      }, {
        url: 'https://httpbin.org/user-agent'
      });

      console.log(`User-Agent: ${ua.substring(0, 30)}... -> Status: ${result.statusCode}`);
    }
    
    console.log('✅ User-Agent handling test completed');
  } catch (error) {
    console.log('❌ User-Agent test error:', error.message);
  }

  // Test 10: Health Check (should not be rate limited)
  console.log('\n🔟 Testing health check endpoint...');
  try {
    const healthResult = await makeRequest({
      hostname: 'localhost',
      port: 3333,
      path: '/health',
      method: 'GET',
    });

    console.log('Health check status:', healthResult.statusCode);
    console.log('Health check rate limited:', !!healthResult.headers['x-ratelimit-limit']);
    
    if (healthResult.statusCode === 200 && !healthResult.headers['x-ratelimit-limit']) {
      console.log('✅ Health check endpoint is not rate limited');
    } else {
      console.log('⚠️ Health check endpoint may have rate limiting');
    }
  } catch (error) {
    console.log('❌ Health check test error:', error.message);
  }

  console.log('\n🎉 Phase 7 testing completed!');
  console.log('\nKey features tested:');
  console.log('✓ Advanced rate limiting with user tiers');
  console.log('✓ Rate limit headers in responses');
  console.log('✓ Anonymous vs authenticated rate limits');
  console.log('✓ Legacy endpoint rate limiting');
  console.log('✓ Burst protection for rapid requests');
  console.log('✓ Header redaction (server-side)');
  console.log('✓ Bulk endpoint tier-based limiting');
  console.log('✓ Rate limit exceeded responses');
  console.log('✓ User-Agent handling');
  console.log('✓ Health check endpoint exclusion');
}

// Error handling
process.on('uncaughtException', (error) => {
  console.log('\n💥 Uncaught Exception:', error.message);
  process.exit(1);
});

process.on('unhandledRejection', (reason) => {
  console.log('\n💥 Unhandled Rejection:', reason);
  process.exit(1);
});

// Run tests
runTests().catch(error => {
  console.log('\n💥 Test execution failed:', error.message);
  process.exit(1);
});
