/**
 * E2E Test: Enhanced Security Generator
 *
 * This test verifies that the enhanced security generator actually writes
 * all expected security configuration files to disk with correct content.
 */

import * as fs from 'fs';
import * as path from 'path';
import '../generators/index'; // Ensure all generators are registered
import { GenerationOrchestrator } from '../generators/generation-orchestrator';
import { Workflow } from '../types/workflow';

describe('E2E: Enhanced Security Generator', () => {
  const testOutputDir = path.join(__dirname, '../../.e2e-output/enhanced-security');
  let orchestrator: GenerationOrchestrator;

  beforeEach(() => {
    // Clean up test directory before each test
    if (fs.existsSync(testOutputDir)) {
      fs.rmSync(testOutputDir, { recursive: true, force: true });
    }

    orchestrator = new GenerationOrchestrator();
  });

  afterEach(() => {
    // Clean up test directory after each test
    if (fs.existsSync(testOutputDir)) {
      fs.rmSync(testOutputDir, { recursive: true, force: true });
    }
  });

  it('should generate all security files for complete security schema', async () => {
    const workflow: Workflow = {
      workflow: {
        id: 'e2e-security-test',
        version: '1.0.0',
        name: 'E2E Security Test',
        description: 'Testing enhanced security generator E2E',
      },
      stack: {
        api: {
          type: 'backend',
          technology: 'typescript/express',
          config: { port: 3000 },
        },
        web: {
          type: 'frontend',
          technology: 'react',
          config: { port: 5173 },
        },
      },
      security: {
        compliance: {
          regulations: ['gdpr', 'hipaa', 'pci_dss'],
          data_retention: {
            user_data: '7_years',
            audit_logs: '10_years',
          },
          gdpr: {
            right_to_access: true,
            right_to_erasure: true,
            data_portability: true,
            consent_management: true,
          },
        },
        encryption: {
          at_rest: true,
          in_transit: true,
          field_level: ['ssn', 'credit_card', 'phone'],
        },
        audit_logging: {
          enabled: true,
          retention: '10_years',
          log_all_database_changes: true,
          log_api_requests: true,
        },
        csp: {
          enabled: true,
          directives: {
            'default-src': ["'self'"],
            'script-src': ["'self'", "'unsafe-inline'"],
          },
        },
        rate_limiting: {
          global: {
            requests_per_minute: 100,
            burst: 20,
          },
          per_endpoint: [
            { path: '/api/auth/login', limit: '5/minute' },
          ],
        },
      },
      stages: {
        local: {
          infrastructure: {
            databases: { primary: 'postgresql://localhost/test' },
            services: {},
          },
        },
      },
    };

    // Generate code
    const _result = await orchestrator.generate(workflow, {
      outputDirectory: testOutputDir,
      dryRun: false,
      verbose: false,
    });

    // Verify files were generated
    expect(_result.files.length).toBeGreaterThan(0);

    // Define expected files
    const expectedFiles = [
      'api/src/config/encryption.ts',
      'api/src/config/audit-logging.ts',
      'api/src/middleware/rate-limiting.ts',
      'api/src/utils/gdpr.ts',
      'api/src/utils/hipaa.ts',
      'api/src/utils/pci-dss.ts',
      'api/src/utils/data-retention.ts',
      'web/src/utils/csp.ts',
      'web/src/utils/gdpr.ts',
      'SECURITY.md',
    ];

    // Verify each expected file exists
    expectedFiles.forEach(expectedFile => {
      const fullPath = path.join(testOutputDir, expectedFile);
      expect(fs.existsSync(fullPath)).toBe(true);
    });
  });

  it('should generate encryption configuration with correct algorithm', async () => {
    const workflow: Workflow = {
      workflow: {
        id: 'encryption-test',
        version: '1.0.0',
        name: 'Encryption Test',
        description: 'Test workflow',
      },
      stack: {
        api: {
          type: 'backend',
          technology: 'typescript/express',
          config: { port: 3000 },
        },
      },
      security: {
        encryption: {
          at_rest: true,
          in_transit: true,
          field_level: ['ssn', 'credit_card'],
        },
      },
      stages: {
        local: {
          infrastructure: {
            databases: { primary: 'postgresql://localhost/test' },
            services: {},
          },
        },
      },
    };

    const _result = await orchestrator.generate(workflow, {
      outputDirectory: testOutputDir,
      dryRun: false,
      verbose: false,
    });

    // Read the generated encryption config
    const encryptionConfigPath = path.join(testOutputDir, 'api/src/config/encryption.ts');
    expect(fs.existsSync(encryptionConfigPath)).toBe(true);

    const encryptionConfig = fs.readFileSync(encryptionConfigPath, 'utf-8');

    // Verify encryption configuration
    expect(encryptionConfig).toContain('AES-256-GCM');
    expect(encryptionConfig).toContain('atRest: true');
    expect(encryptionConfig).toContain('inTransit: true');
    expect(encryptionConfig).toContain('ssn');
    expect(encryptionConfig).toContain('credit_card');
    expect(encryptionConfig).toContain('function encrypt(');
    expect(encryptionConfig).toContain('function decrypt(');
    expect(encryptionConfig).toContain('PBKDF2');
  });

  it('should generate audit logging with Winston integration', async () => {
    const workflow: Workflow = {
      workflow: {
        id: 'audit-logging-test',
        version: '1.0.0',
        name: 'Audit Logging Test',
        description: 'Test workflow',
      },
      stack: {
        api: {
          type: 'backend',
          technology: 'typescript/express',
          config: { port: 3000 },
        },
      },
      security: {
        audit_logging: {
          enabled: true,
          retention: '7_years',
          log_all_database_changes: true,
          log_api_requests: true,
        },
      },
      stages: {
        local: {
          infrastructure: {
            databases: { primary: 'postgresql://localhost/test' },
            services: {},
          },
        },
      },
    };

    const _result = await orchestrator.generate(workflow, {
      outputDirectory: testOutputDir,
      dryRun: false,
      verbose: false,
    });

    // Read the generated audit logging config
    const auditLoggingPath = path.join(testOutputDir, 'api/src/config/audit-logging.ts');
    expect(fs.existsSync(auditLoggingPath)).toBe(true);

    const auditLogging = fs.readFileSync(auditLoggingPath, 'utf-8');

    // Verify audit logging setup
    expect(auditLogging).toContain('winston');
    expect(auditLogging).toContain('auditLogger');
    expect(auditLogging).toContain("retention: '7_years'");
    expect(auditLogging).toContain('logDatabaseChanges: true');
    expect(auditLogging).toContain('logApiRequests: true');
    expect(auditLogging).toContain('AuditEventType');
    expect(auditLogging).toContain('USER_LOGIN');
    expect(auditLogging).toContain('SENSITIVE_DATA_ACCESSED');
  });

  it('should generate rate limiting middleware', async () => {
    const workflow: Workflow = {
      workflow: {
        id: 'rate-limiting-test',
        version: '1.0.0',
        name: 'Rate Limiting Test',
        description: 'Test workflow',
      },
      stack: {
        api: {
          type: 'backend',
          technology: 'typescript/express',
          config: { port: 3000 },
        },
      },
      security: {
        rate_limiting: {
          global: {
            requests_per_minute: 100,
          },
          per_endpoint: [
            { path: '/api/auth/login', limit: '5/minute' },
            { path: '/api/search', limit: '50/hour' },
          ],
        },
      },
      stages: {
        local: {
          infrastructure: {
            databases: { primary: 'postgresql://localhost/test' },
            services: {},
          },
        },
      },
    };

    const _result = await orchestrator.generate(workflow, {
      outputDirectory: testOutputDir,
      dryRun: false,
      verbose: false,
    });

    // Read rate limiting middleware
    const rateLimitingPath = path.join(testOutputDir, 'api/src/middleware/rate-limiting.ts');
    expect(fs.existsSync(rateLimitingPath)).toBe(true);

    const rateLimiting = fs.readFileSync(rateLimitingPath, 'utf-8');

    // Verify rate limiting configuration
    expect(rateLimiting).toContain('express-rate-limit');
    expect(rateLimiting).toContain('globalRateLimiter');
    expect(rateLimiting).toContain('/api/auth/login');
    expect(rateLimiting).toContain('5/minute');
    expect(rateLimiting).toContain('createEndpointRateLimiter');
  });

  it('should generate GDPR compliance utilities for both backend and frontend', async () => {
    const workflow: Workflow = {
      workflow: {
        id: 'gdpr-test',
        version: '1.0.0',
        name: 'GDPR Test',
        description: 'Test workflow',
      },
      stack: {
        api: {
          type: 'backend',
          technology: 'typescript/express',
          config: { port: 3000 },
        },
        web: {
          type: 'frontend',
          technology: 'react',
          config: { port: 5173 },
        },
      },
      security: {
        compliance: {
          regulations: ['gdpr'],
          gdpr: {
            right_to_access: true,
            right_to_erasure: true,
            data_portability: true,
            consent_management: true,
          },
        },
      },
      stages: {
        local: {
          infrastructure: {
            databases: { primary: 'postgresql://localhost/test' },
            services: {},
          },
        },
      },
    };

    const _result = await orchestrator.generate(workflow, {
      outputDirectory: testOutputDir,
      dryRun: false,
      verbose: false,
    });

    // Read backend GDPR utilities
    const backendGdprPath = path.join(testOutputDir, 'api/src/utils/gdpr.ts');
    expect(fs.existsSync(backendGdprPath)).toBe(true);

    const backendGdpr = fs.readFileSync(backendGdprPath, 'utf-8');
    expect(backendGdpr).toContain('exportUserData');
    expect(backendGdpr).toContain('deleteUserData');
    expect(backendGdpr).toContain('updateConsent');
    expect(backendGdpr).toContain('rightToAccess: true');

    // Read frontend GDPR utilities
    const frontendGdprPath = path.join(testOutputDir, 'web/src/utils/gdpr.ts');
    expect(fs.existsSync(frontendGdprPath)).toBe(true);

    const frontendGdpr = fs.readFileSync(frontendGdprPath, 'utf-8');
    expect(frontendGdpr).toContain('useConsentManagement');
    expect(frontendGdpr).toContain('requestDataExport');
    expect(frontendGdpr).toContain('requestAccountDeletion');
    expect(frontendGdpr).toContain('ConsentBanner');
  });

  it('should generate HIPAA compliance utilities', async () => {
    const workflow: Workflow = {
      workflow: {
        id: 'hipaa-test',
        version: '1.0.0',
        name: 'HIPAA Test',
        description: 'Test workflow',
      },
      stack: {
        api: {
          type: 'backend',
          technology: 'typescript/express',
          config: { port: 3000 },
        },
      },
      security: {
        compliance: {
          regulations: ['hipaa'],
        },
      },
      stages: {
        local: {
          infrastructure: {
            databases: { primary: 'postgresql://localhost/test' },
            services: {},
          },
        },
      },
    };

    const _result = await orchestrator.generate(workflow, {
      outputDirectory: testOutputDir,
      dryRun: false,
      verbose: false,
    });

    // Read HIPAA utilities
    const hipaaPath = path.join(testOutputDir, 'api/src/utils/hipaa.ts');
    expect(fs.existsSync(hipaaPath)).toBe(true);

    const hipaa = fs.readFileSync(hipaaPath, 'utf-8');
    expect(hipaa).toContain('containsPHI');
    expect(hipaa).toContain('encryptPHI');
    expect(hipaa).toContain('logPHIAccess');
    expect(hipaa).toContain('applyMinimumNecessary');
    expect(hipaa).toContain('Protected Health Information');
  });

  it('should generate PCI DSS compliance utilities', async () => {
    const workflow: Workflow = {
      workflow: {
        id: 'pci-dss-test',
        version: '1.0.0',
        name: 'PCI DSS Test',
        description: 'Test workflow',
      },
      stack: {
        api: {
          type: 'backend',
          technology: 'typescript/express',
          config: { port: 3000 },
        },
      },
      security: {
        compliance: {
          regulations: ['pci_dss'],
        },
      },
      stages: {
        local: {
          infrastructure: {
            databases: { primary: 'postgresql://localhost/test' },
            services: {},
          },
        },
      },
    };

    const _result = await orchestrator.generate(workflow, {
      outputDirectory: testOutputDir,
      dryRun: false,
      verbose: false,
    });

    // Read PCI DSS utilities
    const pciDssPath = path.join(testOutputDir, 'api/src/utils/pci-dss.ts');
    expect(fs.existsSync(pciDssPath)).toBe(true);

    const pciDss = fs.readFileSync(pciDssPath, 'utf-8');
    expect(pciDss).toContain('maskCardNumber');
    expect(pciDss).toContain('validateCardNumber');
    expect(pciDss).toContain('encryptCardData');
    expect(pciDss).toContain('Luhn algorithm');
    expect(pciDss).toContain('tokenizeCard');
  });

  it('should generate Content Security Policy configuration', async () => {
    const workflow: Workflow = {
      workflow: {
        id: 'csp-test',
        version: '1.0.0',
        name: 'CSP Test',
        description: 'Test workflow',
      },
      stack: {
        web: {
          type: 'frontend',
          technology: 'react',
          config: { port: 5173 },
        },
      },
      security: {
        csp: {
          enabled: true,
          directives: {
            'default-src': ["'self'"],
            'script-src': ["'self'", 'https://cdn.example.com'],
          },
        },
      },
      stages: {
        local: {
          infrastructure: {
            databases: { primary: 'postgresql://localhost/test' },
            services: {},
          },
        },
      },
    };

    const _result = await orchestrator.generate(workflow, {
      outputDirectory: testOutputDir,
      dryRun: false,
      verbose: false,
    });

    // Read CSP configuration
    const cspPath = path.join(testOutputDir, 'web/src/utils/csp.ts');
    expect(fs.existsSync(cspPath)).toBe(true);

    const csp = fs.readFileSync(cspPath, 'utf-8');
    expect(csp).toContain('cspDirectives');
    expect(csp).toContain('default-src');
    expect(csp).toContain('script-src');
    expect(csp).toContain('https://cdn.example.com');
    expect(csp).toContain('generateCSPHeader');
    expect(csp).toContain('cspMiddleware');
  });

  it('should generate data retention policy configuration', async () => {
    const workflow: Workflow = {
      workflow: {
        id: 'data-retention-test',
        version: '1.0.0',
        name: 'Data Retention Test',
        description: 'Test workflow',
      },
      stack: {
        api: {
          type: 'backend',
          technology: 'typescript/express',
          config: { port: 3000 },
        },
      },
      security: {
        compliance: {
          regulations: ['gdpr'],
          data_retention: {
            user_data: '7_years',
            audit_logs: '10_years',
            session_data: '30_days',
          },
        },
      },
      stages: {
        local: {
          infrastructure: {
            databases: { primary: 'postgresql://localhost/test' },
            services: {},
          },
        },
      },
    };

    const _result = await orchestrator.generate(workflow, {
      outputDirectory: testOutputDir,
      dryRun: false,
      verbose: false,
    });

    // Read data retention configuration
    const retentionPath = path.join(testOutputDir, 'api/src/utils/data-retention.ts');
    expect(fs.existsSync(retentionPath)).toBe(true);

    const retention = fs.readFileSync(retentionPath, 'utf-8');
    expect(retention).toContain('user_data');
    expect(retention).toContain('7_years');
    expect(retention).toContain('audit_logs');
    expect(retention).toContain('10_years');
    expect(retention).toContain('session_data');
    expect(retention).toContain('30_days');
    expect(retention).toContain('calculateDeletionDate');
    expect(retention).toContain('cleanupExpiredData');
  });

  it('should generate security policy documentation', async () => {
    const workflow: Workflow = {
      workflow: {
        id: 'security-docs-test',
        version: '1.0.0',
        name: 'Security Documentation Test',
        description: 'Test workflow',
      },
      stack: {
        api: {
          type: 'backend',
          technology: 'typescript/express',
          config: { port: 3000 },
        },
      },
      security: {
        compliance: {
          regulations: ['gdpr', 'hipaa', 'soc2'],
        },
        encryption: {
          at_rest: true,
          in_transit: true,
        },
        audit_logging: {
          enabled: true,
          retention: '7_years',
        },
        rate_limiting: {
          global: {
            requests_per_minute: 100,
          },
        },
      },
      stages: {
        local: {
          infrastructure: {
            databases: { primary: 'postgresql://localhost/test' },
            services: {},
          },
        },
      },
    };

    const _result = await orchestrator.generate(workflow, {
      outputDirectory: testOutputDir,
      dryRun: false,
      verbose: false,
    });

    // Read security policy documentation
    const securityPolicyPath = path.join(testOutputDir, 'SECURITY.md');
    expect(fs.existsSync(securityPolicyPath)).toBe(true);

    const securityPolicy = fs.readFileSync(securityPolicyPath, 'utf-8');
    expect(securityPolicy).toContain('# Security & Compliance Policy');
    expect(securityPolicy).toContain('GDPR');
    expect(securityPolicy).toContain('HIPAA');
    expect(securityPolicy).toContain('SOC2');
    expect(securityPolicy).toContain('Encryption at Rest');
    expect(securityPolicy).toContain('Encryption in Transit');
    expect(securityPolicy).toContain('Audit logging');
    expect(securityPolicy).toContain('Rate limiting');
  });
});
