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

const scryptAsync = promisify(scrypt);

/**
 * Enhanced Security Manager for ZAI Platform
 * Implements multi-layer security with fraud detection and monitoring
 */
export class SecurityManager extends EventEmitter {
  constructor() {
    super();
    
    this.failedAttempts = new Map(); // IP -> { count, lastAttempt, blocked }
    this.suspiciousActivity = new Map(); // IP -> activity log
    this.activeTokens = new Map(); // token -> { ip, created, lastUsed }
    this.securityEvents = [];
    
    // Security configuration
    this.config = {
      maxFailedAttempts: 5,
      blockDuration: 15 * 60 * 1000, // 15 minutes
      tokenExpiry: 24 * 60 * 60 * 1000, // 24 hours
      suspiciousThreshold: 10, // requests per minute
      fraudDetectionEnabled: true
    };
    
    console.log('🔒 Security Manager initialized');
  }

  /**
   * Generate secure admin session token
   */
  async generateSecureToken(adminKey, clientIP) {
    try {
      // Verify admin key
      if (!this.verifyAdminKey(adminKey)) {
        this.logSecurityEvent('INVALID_ADMIN_KEY', clientIP);
        throw new Error('Invalid admin key');
      }
      
      // Check if IP is blocked
      if (this.isIPBlocked(clientIP)) {
        this.logSecurityEvent('BLOCKED_IP_ACCESS', clientIP);
        throw new Error('IP address is temporarily blocked');
      }
      
      // Generate secure token
      const tokenData = {
        timestamp: Date.now(),
        ip: clientIP,
        random: randomBytes(32).toString('hex')
      };
      
      const token = this.hashData(JSON.stringify(tokenData));
      
      // Store active token
      this.activeTokens.set(token, {
        ip: clientIP,
        created: Date.now(),
        lastUsed: Date.now()
      });
      
      this.logSecurityEvent('TOKEN_GENERATED', clientIP);
      return token;
      
    } catch (error) {
      this.recordFailedAttempt(clientIP);
      throw error;
    }
  }

  /**
   * Validate admin session token
   */
  validateToken(token, clientIP) {
    const tokenInfo = this.activeTokens.get(token);
    
    if (!tokenInfo) {
      this.logSecurityEvent('INVALID_TOKEN', clientIP);
      return false;
    }
    
    // Check if token expired
    if (Date.now() - tokenInfo.created > this.config.tokenExpiry) {
      this.activeTokens.delete(token);
      this.logSecurityEvent('EXPIRED_TOKEN', clientIP);
      return false;
    }
    
    // Check if IP matches
    if (tokenInfo.ip !== clientIP) {
      this.logSecurityEvent('TOKEN_IP_MISMATCH', clientIP);
      return false;
    }
    
    // Update last used
    tokenInfo.lastUsed = Date.now();
    this.logSecurityEvent('TOKEN_VALIDATED', clientIP);
    
    return true;
  }

  /**
   * Verify admin key with enhanced security
   */
  verifyAdminKey(providedKey) {
    const expectedKey = process.env.ADMIN_KEY || 'your-super-secret-admin-key';
    
    // Constant-time comparison to prevent timing attacks
    const providedHash = this.hashData(providedKey);
    const expectedHash = this.hashData(expectedKey);
    
    return providedHash === expectedHash;
  }

  /**
   * Record failed authentication attempt
   */
  recordFailedAttempt(clientIP) {
    const now = Date.now();
    const attempts = this.failedAttempts.get(clientIP) || { count: 0, lastAttempt: 0, blocked: false };
    
    attempts.count++;
    attempts.lastAttempt = now;
    
    // Block IP if too many failed attempts
    if (attempts.count >= this.config.maxFailedAttempts) {
      attempts.blocked = true;
      attempts.blockedUntil = now + this.config.blockDuration;
      this.logSecurityEvent('IP_BLOCKED', clientIP, { attempts: attempts.count });
    }
    
    this.failedAttempts.set(clientIP, attempts);
    this.logSecurityEvent('FAILED_ATTEMPT', clientIP, { totalAttempts: attempts.count });
  }

  /**
   * Check if IP is currently blocked
   */
  isIPBlocked(clientIP) {
    const attempts = this.failedAttempts.get(clientIP);
    
    if (!attempts || !attempts.blocked) {
      return false;
    }
    
    // Check if block period has expired
    if (Date.now() > attempts.blockedUntil) {
      attempts.blocked = false;
      attempts.count = 0;
      this.failedAttempts.set(clientIP, attempts);
      this.logSecurityEvent('IP_UNBLOCKED', clientIP);
      return false;
    }
    
    return true;
  }

  /**
   * Detect suspicious activity patterns
   */
  detectSuspiciousActivity(clientIP, action) {
    const now = Date.now();
    const activity = this.suspiciousActivity.get(clientIP) || [];
    
    // Add current activity
    activity.push({ action, timestamp: now });
    
    // Remove activities older than 1 minute
    const recentActivity = activity.filter(a => now - a.timestamp < 60000);
    
    // Check for suspicious patterns
    if (recentActivity.length > this.config.suspiciousThreshold) {
      this.logSecurityEvent('SUSPICIOUS_ACTIVITY', clientIP, { 
        actionsPerMinute: recentActivity.length,
        actions: recentActivity.map(a => a.action)
      });
      
      // Auto-block suspicious IPs
      this.recordFailedAttempt(clientIP);
      this.recordFailedAttempt(clientIP);
      this.recordFailedAttempt(clientIP);
    }
    
    this.suspiciousActivity.set(clientIP, recentActivity);
  }

  /**
   * License fraud detection
   */
  detectLicenseFraud(licenseData, clientIP) {
    const fraudIndicators = [];
    
    // Check for rapid license generation
    const recentLicenses = this.getRecentLicensesByIP(clientIP);
    if (recentLicenses.length > 3) {
      fraudIndicators.push('RAPID_LICENSE_GENERATION');
    }
    
    // Check for suspicious email patterns
    if (this.isSuspiciousEmail(licenseData.userEmail)) {
      fraudIndicators.push('SUSPICIOUS_EMAIL');
    }
    
    // Check for duplicate user information
    if (this.isDuplicateUser(licenseData)) {
      fraudIndicators.push('DUPLICATE_USER_INFO');
    }
    
    if (fraudIndicators.length > 0) {
      this.logSecurityEvent('FRAUD_DETECTED', clientIP, { 
        indicators: fraudIndicators,
        licenseData: {
          email: licenseData.userEmail,
          tier: licenseData.tier
        }
      });
      
      return { fraudDetected: true, indicators: fraudIndicators };
    }
    
    return { fraudDetected: false, indicators: [] };
  }

  /**
   * Log security events
   */
  logSecurityEvent(eventType, clientIP, details = {}) {
    const event = {
      timestamp: new Date().toISOString(),
      type: eventType,
      ip: clientIP,
      details
    };
    
    this.securityEvents.push(event);
    
    // Keep only last 1000 events
    if (this.securityEvents.length > 1000) {
      this.securityEvents = this.securityEvents.slice(-1000);
    }
    
    // Emit event for real-time monitoring
    this.emit('securityEvent', event);
    
    console.log(`🔒 Security Event: ${eventType} from ${clientIP}`, details);
  }

  /**
   * Get security dashboard data
   */
  getSecurityDashboard() {
    const now = Date.now();
    const last24Hours = now - (24 * 60 * 60 * 1000);
    
    const recentEvents = this.securityEvents.filter(e => 
      new Date(e.timestamp).getTime() > last24Hours
    );
    
    const eventCounts = {};
    recentEvents.forEach(event => {
      eventCounts[event.type] = (eventCounts[event.type] || 0) + 1;
    });
    
    const blockedIPs = Array.from(this.failedAttempts.entries())
      .filter(([ip, data]) => data.blocked && now < data.blockedUntil)
      .map(([ip, data]) => ({
        ip,
        blockedUntil: new Date(data.blockedUntil).toISOString(),
        attempts: data.count
      }));
    
    return {
      recentEvents: recentEvents.slice(-50), // Last 50 events
      eventCounts,
      blockedIPs,
      activeTokens: this.activeTokens.size,
      suspiciousIPs: this.suspiciousActivity.size
    };
  }

  /**
   * Utility methods
   */
  hashData(data) {
    return createHash('sha256').update(data).digest('hex');
  }

  getRecentLicensesByIP(clientIP) {
    // This would integrate with license storage to check recent licenses
    // For now, return empty array
    return [];
  }

  isSuspiciousEmail(email) {
    const suspiciousPatterns = [
      /temp.*mail/i,
      /10.*minute.*mail/i,
      /guerrilla.*mail/i,
      /mailinator/i,
      /throwaway/i
    ];
    
    return suspiciousPatterns.some(pattern => pattern.test(email));
  }

  isDuplicateUser(licenseData) {
    // This would check against existing licenses for duplicates
    // For now, return false
    return false;
  }

  /**
   * Cleanup expired tokens and old data
   */
  cleanup() {
    const now = Date.now();
    
    // Remove expired tokens
    for (const [token, info] of this.activeTokens.entries()) {
      if (now - info.created > this.config.tokenExpiry) {
        this.activeTokens.delete(token);
      }
    }
    
    // Remove old failed attempts
    for (const [ip, data] of this.failedAttempts.entries()) {
      if (data.blocked && now > data.blockedUntil) {
        data.blocked = false;
        data.count = 0;
      }
    }
    
    console.log('🔒 Security cleanup completed');
  }

  /**
   * Start security monitoring
   */
  startMonitoring() {
    // Cleanup every 5 minutes
    setInterval(() => this.cleanup(), 5 * 60 * 1000);
    
    console.log('🔒 Security monitoring started');
  }
}
