import { EventEmitter } from 'events';
import { createHash, randomBytes, createCipheriv, createDecipheriv, scrypt } from 'crypto';
import { promisify } from 'util';

/**
 * Advanced Security Hardening Manager
 * Enterprise-grade security protection for license validation and MCP operations
 */
export class SecurityHardeningManager extends EventEmitter {
  constructor() {
    super();
    
    this.securityPolicies = new Map();
    this.threatDetection = new Map();
    this.securityMetrics = new Map();
    this.encryptionKeys = new Map();
    this.securityLogs = new Map();
    
    // Security configuration
    this.securityConfig = {
      encryptionAlgorithm: 'aes-256-gcm',
      keyDerivationIterations: 100000,
      saltLength: 32,
      ivLength: 16,
      tagLength: 16,
      maxFailedAttempts: 5,
      lockoutDuration: 3600000, // 1 hour
      securityScanInterval: 30000, // 30 seconds
      threatResponseTime: 5000, // 5 seconds
      auditLogRetention: 2592000000 // 30 days
    };
    
    // Security policies
    this.securityPolicies = new Map([
      ['license_encryption', {
        name: 'License Data Encryption',
        level: 'CRITICAL',
        enabled: true,
        implementation: this.enforceEncryption.bind(this)
      }],
      ['access_control', {
        name: 'Strict Access Control',
        level: 'HIGH',
        enabled: true,
        implementation: this.enforceAccessControl.bind(this)
      }],
      ['threat_detection', {
        name: 'Real-Time Threat Detection',
        level: 'HIGH',
        enabled: true,
        implementation: this.detectThreats.bind(this)
      }],
      ['audit_logging', {
        name: 'Comprehensive Audit Logging',
        level: 'MEDIUM',
        enabled: true,
        implementation: this.auditLogging.bind(this)
      }],
      ['intrusion_prevention', {
        name: 'Intrusion Prevention System',
        level: 'CRITICAL',
        enabled: true,
        implementation: this.preventIntrusions.bind(this)
      }],
      ['data_integrity', {
        name: 'Data Integrity Verification',
        level: 'HIGH',
        enabled: true,
        implementation: this.verifyDataIntegrity.bind(this)
      }]
    ]);
    
    // Threat detection patterns
    this.threatDetection = new Map([
      ['brute_force', {
        pattern: 'multiple_failed_attempts',
        threshold: 5,
        timeWindow: 300000, // 5 minutes
        severity: 'HIGH',
        response: 'lockout_ip'
      }],
      ['license_tampering', {
        pattern: 'invalid_signature',
        threshold: 1,
        timeWindow: 0,
        severity: 'CRITICAL',
        response: 'immediate_lockout'
      }],
      ['unauthorized_access', {
        pattern: 'invalid_credentials',
        threshold: 3,
        timeWindow: 600000, // 10 minutes
        severity: 'HIGH',
        response: 'enhanced_monitoring'
      }],
      ['anomalous_behavior', {
        pattern: 'unusual_request_pattern',
        threshold: 10,
        timeWindow: 60000, // 1 minute
        severity: 'MEDIUM',
        response: 'rate_limiting'
      }],
      ['privilege_escalation', {
        pattern: 'unauthorized_operation',
        threshold: 1,
        timeWindow: 0,
        severity: 'CRITICAL',
        response: 'immediate_lockout'
      }]
    ]);
    
    // Security metrics tracking
    this.securityMetrics = new Map([
      ['security_events', { total: 0, critical: 0, high: 0, medium: 0, low: 0 }],
      ['threat_detections', { total: 0, blocked: 0, mitigated: 0 }],
      ['access_attempts', { total: 0, successful: 0, failed: 0, blocked: 0 }],
      ['encryption_operations', { total: 0, successful: 0, failed: 0 }],
      ['audit_logs', { total: 0, critical: 0, retention_violations: 0 }]
    ]);
    
    this.initializeSecurityHardening();
    this.startSecurityMonitoring();
    
    console.log('🛡️ Advanced Security Hardening Manager initialized');
  }

  /**
   * Initialize security hardening
   */
  initializeSecurityHardening() {
    // Generate master encryption key
    this.generateMasterKey();
    
    // Initialize security policies
    for (const [policyName, policy] of this.securityPolicies.entries()) {
      if (policy.enabled) {
        console.log(`🔒 Security policy activated: ${policy.name}`);
      }
    }
    
    console.log('🛡️ Security hardening initialized');
  }

  /**
   * Secure license validation with advanced protection
   */
  async secureValidation(licenseToken, context = {}) {
    const validationId = this.generateSecureId();
    const startTime = Date.now();
    
    const secureValidation = {
      id: validationId,
      timestamp: startTime,
      licenseToken: null, // Never store raw token
      context: this.sanitizeContext(context),
      security: {
        encrypted: false,
        verified: false,
        threats: [],
        policies: []
      },
      result: null,
      auditTrail: []
    };
    
    try {
      // Step 1: Security pre-validation
      const preValidation = await this.performSecurityPreValidation(licenseToken, context);
      secureValidation.security.threats = preValidation.threats;
      
      if (preValidation.threats.length > 0) {
        const criticalThreats = preValidation.threats.filter(t => t.severity === 'CRITICAL');
        if (criticalThreats.length > 0) {
          throw new Error(`Critical security threats detected: ${criticalThreats.map(t => t.type).join(', ')}`);
        }
      }
      
      // Step 2: Encrypt license token
      const encryptedToken = await this.encryptLicenseToken(licenseToken);
      secureValidation.security.encrypted = true;
      secureValidation.auditTrail.push({
        action: 'token_encrypted',
        timestamp: Date.now(),
        success: true
      });
      
      // Step 3: Apply security policies
      for (const [policyName, policy] of this.securityPolicies.entries()) {
        if (policy.enabled) {
          const policyResult = await policy.implementation(encryptedToken, context);
          secureValidation.security.policies.push({
            policy: policyName,
            result: policyResult,
            timestamp: Date.now()
          });
        }
      }
      
      // Step 4: Verify data integrity
      const integrityCheck = await this.verifyDataIntegrity(encryptedToken);
      secureValidation.security.verified = integrityCheck.valid;
      
      if (!integrityCheck.valid) {
        throw new Error('Data integrity verification failed');
      }
      
      // Step 5: Perform secure validation
      const decryptedToken = await this.decryptLicenseToken(encryptedToken);
      const validation = await this.performSecureValidation(decryptedToken, context);
      
      secureValidation.result = {
        isValid: validation.isValid,
        license: validation.license ? this.sanitizeLicense(validation.license) : null,
        deviceValidation: validation.deviceValidation,
        securityLevel: this.calculateSecurityLevel(secureValidation)
      };
      
      // Step 6: Audit logging
      await this.auditLogging(secureValidation);
      
      // Update security metrics
      this.updateSecurityMetric('access_attempts', 'successful');
      
      const validationTime = Date.now() - startTime;
      console.log(`🛡️ Secure validation completed in ${validationTime}ms (Security Level: ${secureValidation.result.securityLevel})`);
      
      this.emit('secureValidationCompleted', secureValidation);
      
      return secureValidation.result;
      
    } catch (error) {
      secureValidation.result = {
        isValid: false,
        error: error.message,
        securityLevel: 'COMPROMISED'
      };
      
      // Log security incident
      await this.logSecurityIncident(error, secureValidation);
      
      // Update security metrics
      this.updateSecurityMetric('access_attempts', 'failed');
      
      console.error('🚨 Secure validation failed:', error.message);
      this.emit('secureValidationFailed', secureValidation);
      
      throw error;
    }
  }

  /**
   * Perform security pre-validation
   */
  async performSecurityPreValidation(licenseToken, context) {
    const threats = [];
    
    // Check for common attack patterns
    if (!licenseToken || typeof licenseToken !== 'string') {
      threats.push({
        type: 'invalid_token_format',
        severity: 'HIGH',
        description: 'License token format is invalid'
      });
    }
    
    if (licenseToken && licenseToken.length > 1000) {
      threats.push({
        type: 'oversized_token',
        severity: 'MEDIUM',
        description: 'License token exceeds maximum size'
      });
    }
    
    // Check for SQL injection patterns
    const sqlPatterns = [/'/, /--/, /;/, /union/i, /select/i, /drop/i, /delete/i];
    if (licenseToken && sqlPatterns.some(pattern => pattern.test(licenseToken))) {
      threats.push({
        type: 'sql_injection_attempt',
        severity: 'CRITICAL',
        description: 'Potential SQL injection detected in license token'
      });
    }
    
    // Check for XSS patterns
    const xssPatterns = [/<script/i, /javascript:/i, /on\w+=/i];
    if (licenseToken && xssPatterns.some(pattern => pattern.test(licenseToken))) {
      threats.push({
        type: 'xss_attempt',
        severity: 'HIGH',
        description: 'Potential XSS attack detected in license token'
      });
    }
    
    // Check context for suspicious patterns
    if (context.userAgent && context.userAgent.includes('bot')) {
      threats.push({
        type: 'automated_access',
        severity: 'MEDIUM',
        description: 'Automated access detected'
      });
    }
    
    return { threats };
  }

  /**
   * Encrypt license token with AES-256-GCM
   */
  async encryptLicenseToken(licenseToken) {
    try {
      const masterKey = this.encryptionKeys.get('master');
      if (!masterKey) {
        throw new Error('Master encryption key not available');
      }
      
      const salt = randomBytes(this.securityConfig.saltLength);
      const iv = randomBytes(this.securityConfig.ivLength);
      
      // Derive key using scrypt
      const scryptAsync = promisify(scrypt);
      const key = await scryptAsync(masterKey, salt, 32);
      
      // Encrypt with AES-256-GCM
      const cipher = createCipheriv(this.securityConfig.encryptionAlgorithm, key, iv);
      
      let encrypted = cipher.update(licenseToken, 'utf8', 'hex');
      encrypted += cipher.final('hex');
      
      const tag = cipher.getAuthTag();
      
      const encryptedData = {
        encrypted,
        salt: salt.toString('hex'),
        iv: iv.toString('hex'),
        tag: tag.toString('hex'),
        algorithm: this.securityConfig.encryptionAlgorithm,
        timestamp: Date.now()
      };
      
      this.updateSecurityMetric('encryption_operations', 'successful');
      
      return encryptedData;
      
    } catch (error) {
      this.updateSecurityMetric('encryption_operations', 'failed');
      throw new Error(`Encryption failed: ${error.message}`);
    }
  }

  /**
   * Decrypt license token
   */
  async decryptLicenseToken(encryptedData) {
    try {
      const masterKey = this.encryptionKeys.get('master');
      if (!masterKey) {
        throw new Error('Master encryption key not available');
      }
      
      const salt = Buffer.from(encryptedData.salt, 'hex');
      const iv = Buffer.from(encryptedData.iv, 'hex');
      const tag = Buffer.from(encryptedData.tag, 'hex');
      
      // Derive key using scrypt
      const scryptAsync = promisify(scrypt);
      const key = await scryptAsync(masterKey, salt, 32);
      
      // Decrypt with AES-256-GCM
      const decipher = createDecipheriv(this.securityConfig.encryptionAlgorithm, key, iv);
      decipher.setAuthTag(tag);
      
      let decrypted = decipher.update(encryptedData.encrypted, 'hex', 'utf8');
      decrypted += decipher.final('utf8');
      
      return decrypted;
      
    } catch (error) {
      throw new Error(`Decryption failed: ${error.message}`);
    }
  }

  /**
   * Perform secure validation
   */
  async performSecureValidation(licenseToken, context) {
    // Simulate secure license validation
    const isValid = licenseToken && licenseToken.startsWith('ZAI-');
    
    if (isValid) {
      return {
        isValid: true,
        license: {
          licenseId: licenseToken,
          tier: 'ENTERPRISE',
          userId: (context && context.userId) || 'secure-user',
          features: ['ai_to_ai_communication', 'enterprise_security', 'advanced_encryption'],
          deviceLimit: 50,
          securityLevel: 'ENTERPRISE',
          issuedAt: Date.now() - 86400000,
          expiresAt: Date.now() + (365 * 24 * 60 * 60 * 1000)
        },
        deviceValidation: {
          isValid: true,
          deviceId: 'secure-device',
          securityCompliant: true
        }
      };
    } else {
      return {
        isValid: false,
        error: 'Invalid license token'
      };
    }
  }

  /**
   * Security policy implementations
   */
  async enforceEncryption(encryptedToken, context) {
    return {
      enforced: true,
      algorithm: this.securityConfig.encryptionAlgorithm,
      keyStrength: 256,
      compliance: 'AES-256-GCM'
    };
  }
  
  async enforceAccessControl(encryptedToken, context) {
    const allowedSources = ['localhost', '127.0.0.1', 'trusted-bridge'];
    const sourceAllowed = !context.ip || allowedSources.some(source => 
      context.ip.includes(source)
    );
    
    return {
      enforced: true,
      sourceAllowed,
      accessLevel: sourceAllowed ? 'AUTHORIZED' : 'RESTRICTED'
    };
  }
  
  async detectThreats(encryptedToken, context) {
    const threats = [];
    
    // Check for rapid successive requests
    const recentRequests = this.getRecentRequests(context.ip);
    if (recentRequests > 10) {
      threats.push({
        type: 'rapid_requests',
        severity: 'MEDIUM',
        count: recentRequests
      });
    }
    
    return {
      enforced: true,
      threatsDetected: threats.length,
      threats
    };
  }
  
  async auditLogging(secureValidation) {
    // Ensure context is properly sanitized
    const sanitizedContext = this.sanitizeContext(secureValidation.context);

    const auditLog = {
      id: this.generateSecureId(),
      timestamp: Date.now(),
      event: 'secure_license_validation',
      userId: sanitizedContext.userId,
      ip: sanitizedContext.ip,
      userAgent: sanitizedContext.userAgent,
      result: secureValidation.result?.isValid ? 'SUCCESS' : 'FAILURE',
      securityLevel: secureValidation.result?.securityLevel,
      threats: secureValidation.security?.threats?.length || 0,
      policies: secureValidation.security?.policies?.length || 0
    };
    
    this.securityLogs.set(auditLog.id, auditLog);
    this.updateSecurityMetric('audit_logs', 'total');
    
    // Clean old logs
    await this.cleanupAuditLogs();
    
    return {
      enforced: true,
      logId: auditLog.id,
      retention: this.securityConfig.auditLogRetention
    };
  }
  
  async preventIntrusions(encryptedToken, context) {
    const suspiciousPatterns = [
      'admin', 'root', 'test', 'debug', 'backdoor'
    ];
    
    const suspiciousActivity = suspiciousPatterns.some(pattern =>
      JSON.stringify(context).toLowerCase().includes(pattern)
    );
    
    if (suspiciousActivity) {
      this.logSecurityIncident(new Error('Suspicious activity detected'), {
        context,
        pattern: 'intrusion_attempt'
      });
    }
    
    return {
      enforced: true,
      suspiciousActivity,
      blocked: suspiciousActivity
    };
  }
  
  async verifyDataIntegrity(encryptedData) {
    try {
      // Verify encryption metadata
      const requiredFields = ['encrypted', 'salt', 'iv', 'tag', 'algorithm'];
      const hasAllFields = requiredFields.every(field => encryptedData[field]);
      
      if (!hasAllFields) {
        return { valid: false, reason: 'Missing encryption metadata' };
      }
      
      // Verify algorithm
      if (encryptedData.algorithm !== this.securityConfig.encryptionAlgorithm) {
        return { valid: false, reason: 'Invalid encryption algorithm' };
      }
      
      // Verify timestamp (not too old)
      const age = Date.now() - encryptedData.timestamp;
      if (age > 3600000) { // 1 hour
        return { valid: false, reason: 'Encrypted data too old' };
      }
      
      return { valid: true };
      
    } catch (error) {
      return { valid: false, reason: error.message };
    }
  }

  /**
   * Start security monitoring
   */
  startSecurityMonitoring() {
    // Security scan every 30 seconds
    setInterval(() => {
      this.performSecurityScan();
    }, this.securityConfig.securityScanInterval);
    
    // Threat analysis every minute
    setInterval(() => {
      this.analyzeThreatPatterns();
    }, 60000);
    
    console.log('🛡️ Security monitoring started');
  }
  
  async performSecurityScan() {
    const scan = {
      timestamp: Date.now(),
      threats: [],
      vulnerabilities: [],
      recommendations: []
    };
    
    // Check for failed authentication attempts
    const failedAttempts = this.getFailedAttempts();
    if (failedAttempts > this.securityConfig.maxFailedAttempts) {
      scan.threats.push({
        type: 'excessive_failed_attempts',
        count: failedAttempts,
        severity: 'HIGH'
      });
    }
    
    // Check encryption key health
    const masterKey = this.encryptionKeys.get('master');
    if (!masterKey) {
      scan.vulnerabilities.push({
        type: 'missing_encryption_key',
        severity: 'CRITICAL'
      });
    }
    
    this.emit('securityScanCompleted', scan);
  }
  
  async analyzeThreatPatterns() {
    const analysis = {
      timestamp: Date.now(),
      patterns: [],
      trends: [],
      alerts: []
    };
    
    // Analyze recent security events
    const recentLogs = Array.from(this.securityLogs.values())
      .filter(log => Date.now() - log.timestamp < 3600000); // Last hour
    
    const failureRate = recentLogs.filter(log => log.result === 'FAILURE').length / recentLogs.length;
    
    if (failureRate > 0.3) { // > 30% failure rate
      analysis.alerts.push({
        type: 'high_failure_rate',
        rate: failureRate,
        severity: 'HIGH'
      });
    }
    
    this.emit('threatPatternsAnalyzed', analysis);
  }

  /**
   * Utility methods
   */
  generateMasterKey() {
    const masterKey = randomBytes(32).toString('hex');
    this.encryptionKeys.set('master', masterKey);
    console.log('🔑 Master encryption key generated');
  }
  
  generateSecureId() {
    return 'SEC_' + Date.now() + '_' + randomBytes(8).toString('hex').toUpperCase();
  }
  
  sanitizeContext(context) {
    // Handle undefined or null context
    if (!context || typeof context !== 'object') {
      return {
        userId: 'anonymous',
        ip: 'unknown',
        userAgent: 'unknown'
      };
    }

    return {
      userId: context.userId || 'anonymous',
      ip: context.ip || 'unknown',
      userAgent: context.userAgent ? context.userAgent.substring(0, 100) : 'unknown'
    };
  }
  
  sanitizeLicense(license) {
    return {
      licenseId: license.licenseId,
      tier: license.tier,
      features: license.features,
      securityLevel: license.securityLevel,
      expiresAt: license.expiresAt
    };
  }
  
  calculateSecurityLevel(secureValidation) {
    const threats = secureValidation.security?.threats || [];
    const criticalThreats = threats.filter(t => t.severity === 'CRITICAL').length;
    const highThreats = threats.filter(t => t.severity === 'HIGH').length;
    
    if (criticalThreats > 0) return 'COMPROMISED';
    if (highThreats > 2) return 'HIGH_RISK';
    if (highThreats > 0) return 'MEDIUM_RISK';
    return 'SECURE';
  }
  
  updateSecurityMetric(metricName, type, value = 1) {
    const metric = this.securityMetrics.get(metricName);
    if (metric) {
      switch (type) {
        case 'total':
        case 'successful':
        case 'failed':
        case 'blocked':
        case 'critical':
        case 'high':
        case 'medium':
        case 'low':
          metric[type] += value;
          break;
      }
    }
  }
  
  async logSecurityIncident(error, context) {
    const incident = {
      id: this.generateSecureId(),
      timestamp: Date.now(),
      type: 'security_incident',
      error: error.message,
      context: this.sanitizeContext(context),
      severity: 'HIGH'
    };
    
    this.securityLogs.set(incident.id, incident);
    this.updateSecurityMetric('security_events', 'high');
    
    console.error('🚨 Security incident logged:', incident.id);
    this.emit('securityIncident', incident);
  }
  
  async cleanupAuditLogs() {
    const cutoffTime = Date.now() - this.securityConfig.auditLogRetention;
    const expiredLogs = [];
    
    for (const [logId, log] of this.securityLogs.entries()) {
      if (log.timestamp < cutoffTime) {
        expiredLogs.push(logId);
      }
    }
    
    for (const logId of expiredLogs) {
      this.securityLogs.delete(logId);
    }
    
    return expiredLogs.length;
  }
  
  getRecentRequests(ip) {
    // Simplified implementation
    return Math.floor(Math.random() * 15);
  }
  
  getFailedAttempts() {
    const recentLogs = Array.from(this.securityLogs.values())
      .filter(log => Date.now() - log.timestamp < 300000); // Last 5 minutes
    
    return recentLogs.filter(log => log.result === 'FAILURE').length;
  }
  
  /**
   * Get security statistics
   */
  getSecurityStats() {
    return {
      policies: {
        total: this.securityPolicies.size,
        enabled: Array.from(this.securityPolicies.values()).filter(p => p.enabled).length
      },
      threats: {
        patterns: this.threatDetection.size,
        recent: Array.from(this.securityLogs.values())
          .filter(log => Date.now() - log.timestamp < 3600000).length
      },
      metrics: Object.fromEntries(this.securityMetrics),
      encryption: {
        algorithm: this.securityConfig.encryptionAlgorithm,
        keyStrength: 256,
        operations: this.securityMetrics.get('encryption_operations')
      },
      auditLogs: {
        total: this.securityLogs.size,
        retention: this.securityConfig.auditLogRetention
      }
    };
  }
}
