import { EventEmitter } from 'events';
import { LicenseManager } from './licenseManager.js';
import { LicensePerformanceOptimizer } from './licensePerformanceOptimizer.js';
import { SecurityHardeningManager } from './securityHardeningManager.js';
import { CodeIntegrityChecker, displaySecurityWarnings } from './codeIntegrityChecker.js';
import { createHash, randomBytes } from 'crypto';
import fs from 'fs/promises';
import path from 'path';

/**
 * MCP License Validator
 * Validates ZAI Bridge license before allowing MCP server activation
 * Ensures only licensed users can access AI-to-AI communication features
 */
export class MCPLicenseValidator extends EventEmitter {
  constructor() {
    super();
    
    this.licenseManager = new LicenseManager();
    this.performanceOptimizer = new LicensePerformanceOptimizer();
    this.securityHardening = new SecurityHardeningManager();
    this.integrityChecker = new CodeIntegrityChecker();
    this.bridgeConnections = new Map();
    this.validationCache = new Map();
    this.licenseStatus = {
      isValid: false,
      license: null,
      bridgeConnected: false,
      lastValidation: null,
      validationErrors: []
    };
    
    // License validation configuration
    this.validationConfig = {
      requireBridge: true,
      bridgeTimeout: 30000, // 30 seconds to detect bridge
      validationInterval: 300000, // 5 minutes revalidation
      cacheTimeout: 60000, // 1 minute cache
      maxRetries: 3,
      gracePeriod: 86400000 // 24 hours grace period for temporary issues
    };
    
    // Bridge detection methods
    this.bridgeDetectionMethods = [
      'environment_variable',
      'config_file',
      'process_detection',
      'network_scan',
      'registry_check'
    ];
    
    console.log('🔐 MCP License Validator initialized');
  }

  /**
   * Initialize license validation system
   */
  async initialize() {
    try {
      console.log('🔐 Initializing MCP License Validator...');
      
      // 🔐 SECURITY: Initialize code integrity checking
      await this.integrityChecker.initialize();
      const integrityValid = await this.integrityChecker.verifyIntegrity();

      if (!integrityValid) {
        displaySecurityWarnings(this.integrityChecker);
        console.warn('⚠️ Code integrity violations detected - proceeding with caution');
      }

      // Initialize license manager
      await this.licenseManager.initialize();

      // Set up license manager event listeners
      this.setupLicenseManagerEvents();

      // Start validation monitoring
      this.startValidationMonitoring();

      // 🔐 Enable runtime integrity monitoring
      this.integrityChecker.enableRuntimeMonitoring();
      
      console.log('✅ MCP License Validator initialized successfully');
      this.emit('initialized');
      
      return true;
    } catch (error) {
      console.error('❌ MCP License Validator initialization failed:', error.message);
      throw error;
    }
  }

  /**
   * Validate MCP server startup requirements
   */
  async validateMCPStartup() {
    const validationId = this.generateValidationId();
    
    const validation = {
      id: validationId,
      timestamp: Date.now(),
      canStart: false,
      requirements: {
        licenseValid: false,
        bridgeDetected: false,
        deviceAuthorized: false,
        featuresEnabled: false
      },
      errors: [],
      warnings: [],
      gracePeriod: false
    };
    
    try {
      console.log('🔐 Validating MCP server startup requirements...');
      
      // Step 1: Detect ZAI Bridge
      const bridgeDetection = await this.detectZAIBridge();
      validation.requirements.bridgeDetected = bridgeDetection.detected;
      
      if (!bridgeDetection.detected) {
        if (this.validationConfig.requireBridge) {
          validation.errors.push('ZAI Bridge not detected - MCP server requires licensed bridge connection');
          
          // Check for grace period
          const gracePeriodCheck = await this.checkGracePeriod();
          if (gracePeriodCheck.inGracePeriod) {
            validation.warnings.push(`Running in grace period - ${gracePeriodCheck.timeRemaining}ms remaining`);
            validation.gracePeriod = true;
            validation.requirements.bridgeDetected = true; // Allow during grace period
          }
        } else {
          validation.warnings.push('ZAI Bridge not detected but not required in current configuration');
        }
      } else {
        console.log(`✅ ZAI Bridge detected via: ${bridgeDetection.method}`);
      }
      
      // Step 2: Validate license through bridge or direct
      let licenseValidation;
      if (bridgeDetection.detected) {
        licenseValidation = await this.validateLicenseThroughBridge(bridgeDetection);
      } else {
        licenseValidation = await this.validateLicenseDirect();
      }
      
      validation.requirements.licenseValid = licenseValidation.isValid;
      
      if (!licenseValidation.isValid) {
        validation.errors.push(`License validation failed: ${licenseValidation.error}`);
      } else {
        console.log(`✅ License validated: ${licenseValidation.license.licenseId} (${licenseValidation.license.tier})`);
        
        // Step 3: Check device authorization
        validation.requirements.deviceAuthorized = licenseValidation.deviceValidation?.isValid || false;
        
        // Step 4: Check feature access
        const features = licenseValidation.license.features || [];
        validation.requirements.featuresEnabled = features.includes('ai_to_ai_communication');
        
        if (!validation.requirements.featuresEnabled) {
          validation.errors.push('License does not include AI-to-AI communication features');
        }
      }
      
      // Determine if MCP server can start
      validation.canStart = (
        validation.requirements.licenseValid &&
        validation.requirements.bridgeDetected &&
        validation.requirements.deviceAuthorized &&
        validation.requirements.featuresEnabled
      ) || validation.gracePeriod;
      
      // Update license status
      this.licenseStatus = {
        isValid: validation.requirements.licenseValid,
        license: licenseValidation?.license || null,
        bridgeConnected: validation.requirements.bridgeDetected,
        lastValidation: Date.now(),
        validationErrors: validation.errors
      };
      
      // Cache validation result
      this.validationCache.set(validationId, {
        validation,
        timestamp: Date.now()
      });
      
      console.log(`🔐 MCP startup validation ${validation.canStart ? 'PASSED' : 'FAILED'}`);
      this.emit('startupValidated', validation);
      
      return validation;
      
    } catch (error) {
      validation.errors.push(`Validation error: ${error.message}`);
      console.error('❌ MCP startup validation failed:', error.message);
      
      return validation;
    }
  }

  /**
   * Detect ZAI Bridge presence using multiple methods
   */
  async detectZAIBridge() {
    const detection = {
      detected: false,
      method: null,
      bridgeInfo: null,
      confidence: 0
    };
    
    for (const method of this.bridgeDetectionMethods) {
      try {
        const result = await this.detectBridgeByMethod(method);
        
        if (result.detected) {
          detection.detected = true;
          detection.method = method;
          detection.bridgeInfo = result.info;
          detection.confidence = result.confidence;
          break;
        }
      } catch (error) {
        console.warn(`⚠️ Bridge detection method ${method} failed:`, error.message);
      }
    }
    
    return detection;
  }

  /**
   * Detect bridge using specific method
   */
  async detectBridgeByMethod(method) {
    switch (method) {
      case 'environment_variable':
        return await this.detectBridgeByEnvironment();
      case 'config_file':
        return await this.detectBridgeByConfig();
      case 'process_detection':
        return await this.detectBridgeByProcess();
      case 'network_scan':
        return await this.detectBridgeByNetwork();
      case 'registry_check':
        return await this.detectBridgeByRegistry();
      default:
        throw new Error(`Unknown detection method: ${method}`);
    }
  }

  /**
   * Detect bridge via environment variables
   */
  async detectBridgeByEnvironment() {
    const bridgeToken = process.env.ZAI_BRIDGE_TOKEN;
    const bridgePort = process.env.ZAI_BRIDGE_PORT;
    const bridgePid = process.env.ZAI_BRIDGE_PID;
    
    if (bridgeToken || bridgePort || bridgePid) {
      return {
        detected: true,
        confidence: 0.9,
        info: {
          token: bridgeToken ? 'present' : 'missing',
          port: bridgePort || 'unknown',
          pid: bridgePid || 'unknown'
        }
      };
    }
    
    return { detected: false, confidence: 0 };
  }

  /**
   * Detect bridge via configuration file
   */
  async detectBridgeByConfig() {
    const configPaths = [
      '.zai-bridge.json',
      'zai-bridge.config.json',
      path.join(process.env.HOME || process.env.USERPROFILE || '', '.zai', 'bridge.json'),
      // Add test configuration path
      path.join(process.env.HOME || process.env.USERPROFILE || '', '.zai-test', 'bridge.json')
    ];
    
    for (const configPath of configPaths) {
      try {
        const configData = await fs.readFile(configPath, 'utf8');
        const config = JSON.parse(configData);
        
        if (config.bridge && config.bridge.active) {
          return {
            detected: true,
            confidence: 0.8,
            info: {
              configPath,
              bridgeConfig: config.bridge
            }
          };
        }
      } catch (error) {
        // Config file doesn't exist or is invalid, continue
      }
    }
    
    return { detected: false, confidence: 0 };
  }

  /**
   * Detect bridge via process detection
   */
  async detectBridgeByProcess() {
    try {
      // Check for VSCode processes that might indicate bridge presence
      const { exec } = await import('child_process');
      const { promisify } = await import('util');
      const execAsync = promisify(exec);
      
      let command;
      if (process.platform === 'win32') {
        command = 'tasklist /FI "IMAGENAME eq Code.exe" /FO CSV';
      } else {
        command = 'ps aux | grep -i "code\\|vscode"';
      }
      
      const { stdout } = await execAsync(command);
      
      if (stdout.includes('Code') || stdout.includes('vscode')) {
        return {
          detected: true,
          confidence: 0.6,
          info: {
            method: 'process_detection',
            processes: stdout.split('\n').filter(line => 
              line.includes('Code') || line.includes('vscode')
            ).length
          }
        };
      }
    } catch (error) {
      // Process detection failed
    }
    
    return { detected: false, confidence: 0 };
  }

  /**
   * Detect bridge via network scanning
   */
  async detectBridgeByNetwork() {
    const commonPorts = [8080, 8081, 3000, 3001, 5000, 5001];
    
    for (const port of commonPorts) {
      try {
        const response = await fetch(`http://localhost:${port}/zai-bridge/status`, {
          method: 'GET',
          timeout: 1000
        });
        
        if (response.ok) {
          const status = await response.json();
          
          if (status.bridge === 'active') {
            return {
              detected: true,
              confidence: 0.95,
              info: {
                port,
                status,
                endpoint: `http://localhost:${port}/zai-bridge/status`
              }
            };
          }
        }
      } catch (error) {
        // Port not responding, continue
      }
    }
    
    return { detected: false, confidence: 0 };
  }

  /**
   * Detect bridge via registry check (Windows) or similar
   */
  async detectBridgeByRegistry() {
    try {
      if (process.platform === 'win32') {
        // Check Windows registry for VSCode extensions
        const { exec } = await import('child_process');
        const { promisify } = await import('util');
        const execAsync = promisify(exec);
        
        const command = 'reg query "HKCU\\Software\\Microsoft\\VSCode" /s 2>nul | findstr /i "zai\\|bridge"';
        const { stdout } = await execAsync(command);
        
        if (stdout.trim()) {
          return {
            detected: true,
            confidence: 0.7,
            info: {
              method: 'registry_check',
              registryEntries: stdout.split('\n').filter(line => line.trim())
            }
          };
        }
      }
    } catch (error) {
      // Registry check failed
    }
    
    return { detected: false, confidence: 0 };
  }

  /**
   * Validate license through ZAI Bridge
   */
  async validateLicenseThroughBridge(bridgeDetection) {
    try {
      console.log('🔐 Validating license through ZAI Bridge...');
      
      // Try to communicate with bridge to get license token
      const bridgeInfo = bridgeDetection.bridgeInfo;
      let licenseToken = null;
      
      // Method 1: Environment variable
      licenseToken = process.env.ZAI_LICENSE_TOKEN;
      
      // Method 2: Bridge API call
      if (!licenseToken && bridgeInfo?.port) {
        try {
          const response = await fetch(`http://localhost:${bridgeInfo.port}/zai-bridge/license`, {
            method: 'GET',
            timeout: 5000
          });
          
          if (response.ok) {
            const data = await response.json();
            licenseToken = data.token;
          }
        } catch (error) {
          console.warn('⚠️ Failed to get license from bridge API:', error.message);
        }
      }
      
      // Method 3: Config file
      if (!licenseToken && bridgeInfo?.configPath) {
        try {
          const configData = await fs.readFile(bridgeInfo.configPath, 'utf8');
          const config = JSON.parse(configData);
          licenseToken = config.license?.token;
        } catch (error) {
          console.warn('⚠️ Failed to get license from config:', error.message);
        }
      }
      
      if (!licenseToken) {
        return {
          isValid: false,
          error: 'No license token found in ZAI Bridge'
        };
      }
      
      // Validate the license token with security hardening and performance optimization
      const validation = await this.securityHardening.secureValidation(licenseToken, {
        bridgeInfo,
        method: 'bridge_validation',
        userId: 'bridge-user',
        ip: 'bridge-connection',
        userAgent: 'ZAI-Bridge/1.0'
      });
      
      if (validation.isValid) {
        // Register bridge connection
        this.registerBridgeConnection(bridgeDetection, validation.license);
      }
      
      return validation;
      
    } catch (error) {
      return {
        isValid: false,
        error: `Bridge license validation failed: ${error.message}`
      };
    }
  }

  /**
   * Validate license directly (fallback method)
   */
  async validateLicenseDirect() {
    try {
      console.log('🔐 Validating license directly...');
      
      // Try to load license from environment or local storage
      const licenseToken = process.env.ZAI_LICENSE_TOKEN;
      
      if (!licenseToken) {
        return {
          isValid: false,
          error: 'No license token found - ZAI Bridge required for license access'
        };
      }
      
      return await this.licenseManager.validateLicense(licenseToken);
      
    } catch (error) {
      return {
        isValid: false,
        error: `Direct license validation failed: ${error.message}`
      };
    }
  }

  /**
   * Register bridge connection
   */
  registerBridgeConnection(bridgeDetection, license) {
    const connectionId = this.generateConnectionId();
    
    const connection = {
      id: connectionId,
      bridgeInfo: bridgeDetection.bridgeInfo,
      license,
      connectedAt: Date.now(),
      lastSeen: Date.now(),
      active: true
    };
    
    this.bridgeConnections.set(connectionId, connection);
    
    console.log(`✅ Bridge connection registered: ${connectionId}`);
    this.emit('bridgeConnected', connection);
    
    return connection;
  }

  /**
   * Check grace period for temporary license issues
   */
  async checkGracePeriod() {
    const gracePeriodFile = path.join(process.cwd(), '.zai-grace-period');
    
    try {
      const graceData = await fs.readFile(gracePeriodFile, 'utf8');
      const grace = JSON.parse(graceData);
      
      const timeRemaining = grace.expiresAt - Date.now();
      
      if (timeRemaining > 0) {
        return {
          inGracePeriod: true,
          timeRemaining,
          reason: grace.reason
        };
      } else {
        // Grace period expired, remove file
        await fs.unlink(gracePeriodFile);
      }
    } catch (error) {
      // No grace period file or invalid
    }
    
    return {
      inGracePeriod: false,
      timeRemaining: 0
    };
  }

  /**
   * Setup license manager event listeners
   */
  setupLicenseManagerEvents() {
    this.licenseManager.on('licenseValidated', (license) => {
      console.log(`✅ License validated: ${license.licenseId}`);
      this.emit('licenseValidated', license);
    });
    
    this.licenseManager.on('licenseValidationFailed', (error) => {
      console.error(`❌ License validation failed: ${error.message}`);
      this.emit('licenseValidationFailed', error);
    });
  }

  /**
   * Start validation monitoring
   */
  startValidationMonitoring() {
    // Revalidate license periodically
    setInterval(() => {
      this.revalidateLicense();
    }, this.validationConfig.validationInterval);
    
    console.log('🔐 License validation monitoring started');
  }

  /**
   * Revalidate license periodically
   */
  async revalidateLicense() {
    try {
      if (this.licenseStatus.isValid) {
        const validation = await this.validateMCPStartup();
        
        if (!validation.canStart) {
          console.warn('⚠️ License validation failed during monitoring - MCP server may need to shut down');
          this.emit('licenseInvalidated', validation);
        }
      }
    } catch (error) {
      console.error('❌ License revalidation failed:', error.message);
    }
  }

  /**
   * Utility methods
   */
  generateValidationId() {
    return 'VAL_' + Date.now() + '_' + randomBytes(4).toString('hex').toUpperCase();
  }
  
  generateConnectionId() {
    return 'CONN_' + Date.now() + '_' + randomBytes(4).toString('hex').toUpperCase();
  }
  
  /**
   * Get current license status
   */
  getLicenseStatus() {
    return {
      ...this.licenseStatus,
      bridgeConnections: this.bridgeConnections.size,
      lastValidation: this.licenseStatus.lastValidation ? 
        new Date(this.licenseStatus.lastValidation).toISOString() : null
    };
  }
}
