/**
 * Security testing helpers
 */

import { vi } from 'vitest';

/**
 * Mock security vulnerability scanner
 */
export function createMockVulnerabilityScanner() {
  return {
    scan: vi.fn().mockResolvedValue({
      vulnerabilities: [],
      severity: 'low',
      timestamp: new Date(),
    }),
    scanFile: vi.fn().mockResolvedValue({
      vulnerabilities: [],
      severity: 'low',
    }),
  };
}

/**
 * Create test data for security testing
 */
export function createSecurityTestData() {
  return {
    // SQL injection test cases
    sqlInjectionPayloads: [
      "' OR '1'='1",
      "'; DROP TABLE users; --",
      "1' UNION SELECT NULL--",
      "admin'--",
      "' OR 1=1--",
    ],
    
    // XSS test cases
    xssPayloads: [
      "<script>alert('XSS')</script>",
      "<img src=x onerror=alert('XSS')>",
      "javascript:alert('XSS')",
      "<svg onload=alert('XSS')>",
      "'><script>alert('XSS')</script>",
    ],
    
    // Command injection test cases
    commandInjectionPayloads: [
      "; ls -la",
      "| cat /etc/passwd",
      "&& whoami",
      "$(id)",
      "`id`",
    ],
    
    // Path traversal test cases
    pathTraversalPayloads: [
      "../../../etc/passwd",
      "..\\..\\..\\windows\\system32\\config\\sam",
      "....//....//....//etc/passwd",
      "%2e%2e%2f%2e%2e%2f%2e%2e%2fetc%2fpasswd",
    ],
    
    // LDAP injection test cases
    ldapInjectionPayloads: [
      "*)(&",
      "*))%00",
      "*)(|(&",
      "admin)(&(password=*",
    ],
  };
}

/**
 * Test authentication bypass
 */
export async function testAuthenticationBypass(
  makeRequest: (headers?: Record<string, string>) => Promise<{ status: number }>
): Promise<boolean> {
  const testCases = [
    // Missing token
    {},
    // Invalid token
    { Authorization: 'Bearer invalid-token' },
    // Expired token
    { Authorization: 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1MTYyMzkwMjJ9.invalid' },
    // Malformed token
    { Authorization: 'Bearer not.a.valid.token' },
  ];
  
  for (const headers of testCases) {
    const response = await makeRequest(headers);
    if (response.status !== 401 && response.status !== 403) {
      return false; // Authentication bypass possible
    }
  }
  
  return true; // Authentication is properly enforced
}

/**
 * Test authorization bypass
 */
export async function testAuthorizationBypass(
  makeRequest: (user: string, resource: string) => Promise<{ status: number }>
): Promise<boolean> {
  // Test if user can access resources they shouldn't
  const testCases = [
    { user: 'user1', resource: 'user2-resource' },
    { user: 'admin', resource: 'super-admin-resource' },
    { user: 'guest', resource: 'admin-resource' },
  ];
  
  for (const testCase of testCases) {
    const response = await makeRequest(testCase.user, testCase.resource);
    if (response.status !== 403 && response.status !== 404) {
      return false; // Authorization bypass possible
    }
  }
  
  return true; // Authorization is properly enforced
}

/**
 * Test input validation
 */
export async function testInputValidation(
  makeRequest: (input: string) => Promise<{ status: number; body: unknown }>,
  securityTestData: ReturnType<typeof createSecurityTestData>
): Promise<{
  sqlInjection: boolean;
  xss: boolean;
  commandInjection: boolean;
  pathTraversal: boolean;
}> {
  const results = {
    sqlInjection: true,
    xss: true,
    commandInjection: true,
    pathTraversal: true,
  };
  
  // Test SQL injection
  for (const payload of securityTestData.sqlInjectionPayloads) {
    const response = await makeRequest(payload);
    if (response.status === 200 && JSON.stringify(response.body).includes('error') === false) {
      results.sqlInjection = false;
      break;
    }
  }
  
  // Test XSS
  for (const payload of securityTestData.xssPayloads) {
    const response = await makeRequest(payload);
    const bodyStr = JSON.stringify(response.body);
    if (bodyStr.includes(payload) && !bodyStr.includes('&lt;') && !bodyStr.includes('&gt;')) {
      results.xss = false;
      break;
    }
  }
  
  // Test command injection
  for (const payload of securityTestData.commandInjectionPayloads) {
    const response = await makeRequest(payload);
    if (response.status === 200) {
      results.commandInjection = false;
      break;
    }
  }
  
  // Test path traversal
  for (const payload of securityTestData.pathTraversalPayloads) {
    const response = await makeRequest(payload);
    if (response.status === 200) {
      results.pathTraversal = false;
      break;
    }
  }
  
  return results;
}

/**
 * Test rate limiting
 */
export async function testRateLimiting(
  makeRequest: () => Promise<{ status: number }>,
  limit: number = 100
): Promise<boolean> {
  // Make requests up to the limit
  for (let i = 0; i < limit; i++) {
    const response = await makeRequest();
    if (response.status === 429) {
      return false; // Rate limit triggered too early
    }
  }
  
  // Make one more request that should be rate limited
  const response = await makeRequest();
  if (response.status !== 429) {
    return false; // Rate limiting not working
  }
  
  return true; // Rate limiting is working correctly
}

/**
 * Test CSRF protection
 */
export async function testCSRFProtection(
  makeRequest: (headers?: Record<string, string>) => Promise<{ status: number }>
): Promise<boolean> {
  // Request without CSRF token should fail
  const responseWithoutToken = await makeRequest();
  if (responseWithoutToken.status !== 403 && responseWithoutToken.status !== 401) {
    return false; // CSRF protection not working
  }
  
  // Request with CSRF token should succeed
  const responseWithToken = await makeRequest({
    'X-CSRF-Token': 'valid-token',
  });
  if (responseWithToken.status === 403 || responseWithToken.status === 401) {
    return false; // CSRF token validation not working
  }
  
  return true; // CSRF protection is working correctly
}

