import { EventEmitter } from 'events';
import { DigitalOceanClient } from '../licensing/digitalOceanClient.js';
import { createHash } from 'crypto';

/**
 * AI-to-AI Interaction Logger
 * Captures and stores all AI conversations and interactions
 */
export class InteractionLogger extends EventEmitter {
  constructor(licenseManager) {
    super();
    
    this.licenseManager = licenseManager;
    this.digitalOcean = new DigitalOceanClient();
    this.sessionId = this.generateSessionId();
    this.currentSession = null;
    this.pendingLogs = [];
    this.batchSize = 10;
    this.flushInterval = 30000; // 30 seconds
    
    // Start batch processing
    this.startBatchProcessor();
    
    console.log('📝 Interaction Logger initialized');
  }

  /**
   * Start a new AI-to-AI session
   */
  startSession(loopId, topic, options = {}) {
    try {
      this.currentSession = {
        sessionId: this.generateSessionId(),
        loopId,
        topic,
        userId: this.licenseManager.currentLicense?.userId || 'anonymous',
        deviceId: this.licenseManager.deviceId,
        licenseId: this.licenseManager.currentLicense?.licenseId,
        startTime: new Date().toISOString(),
        endTime: null,
        interactions: [],
        metadata: {
          aiToAi: options.aiToAi || false,
          maxIterations: options.maxIterations || 0,
          interval: options.interval || 0,
          model: options.model || 'unknown',
          ...options
        },
        performance: {
          totalDuration: 0,
          averageResponseTime: 0,
          successfulInteractions: 0,
          failedInteractions: 0,
          totalTokens: 0,
          totalCost: 0
        },
        status: 'active'
      };

      console.log(`📝 Session started: ${this.currentSession.sessionId} (${topic})`);
      this.emit('sessionStarted', this.currentSession);
      
      return this.currentSession.sessionId;
    } catch (error) {
      console.error('❌ Failed to start session:', error.message);
      throw error;
    }
  }

  /**
   * Log an AI-to-AI interaction
   */
  logInteraction(interactionData) {
    try {
      if (!this.currentSession) {
        console.warn('⚠️ No active session for interaction logging');
        return;
      }

      const interaction = {
        interactionId: this.generateInteractionId(),
        timestamp: new Date().toISOString(),
        type: interactionData.type || 'ai-to-ai',
        direction: interactionData.direction || 'outbound', // outbound, inbound
        content: this.sanitizeContent(interactionData.content),
        metadata: {
          model: interactionData.model,
          tokens: interactionData.tokens || 0,
          cost: interactionData.cost || 0,
          responseTime: interactionData.responseTime || 0,
          success: interactionData.success !== false,
          iteration: interactionData.iteration || 0,
          ...interactionData.metadata
        },
        context: {
          previousInteractionId: this.getPreviousInteractionId(),
          conversationLength: this.currentSession.interactions.length,
          sessionDuration: Date.now() - new Date(this.currentSession.startTime).getTime()
        }
      };

      // Add to current session
      this.currentSession.interactions.push(interaction);
      
      // Update session performance metrics
      this.updateSessionMetrics(interaction);
      
      // Add to pending logs for batch processing
      this.pendingLogs.push({
        sessionId: this.currentSession.sessionId,
        interaction
      });

      console.log(`📝 Interaction logged: ${interaction.interactionId} (${interaction.type})`);
      this.emit('interactionLogged', interaction);
      
      // Flush if batch is full
      if (this.pendingLogs.length >= this.batchSize) {
        this.flushLogs();
      }
      
      return interaction.interactionId;
    } catch (error) {
      console.error('❌ Failed to log interaction:', error.message);
    }
  }

  /**
   * Log conversation data (complete AI-to-AI conversation)
   */
  logConversation(conversationData) {
    try {
      const conversation = {
        conversationId: this.generateConversationId(),
        sessionId: this.currentSession?.sessionId,
        timestamp: new Date().toISOString(),
        topic: conversationData.topic,
        messages: conversationData.messages?.map(msg => this.sanitizeMessage(msg)) || [],
        metadata: {
          duration: conversationData.duration || 0,
          messageCount: conversationData.messages?.length || 0,
          model: conversationData.model,
          success: conversationData.success !== false,
          iteration: conversationData.iteration || 0,
          loopId: conversationData.loopId,
          ...conversationData.metadata
        },
        performance: {
          totalTokens: conversationData.totalTokens || 0,
          totalCost: conversationData.totalCost || 0,
          averageResponseTime: conversationData.averageResponseTime || 0,
          successRate: conversationData.successRate || 0
        },
        context: {
          userId: this.licenseManager.currentLicense?.userId || 'anonymous',
          deviceId: this.licenseManager.deviceId,
          licenseId: this.licenseManager.currentLicense?.licenseId
        }
      };

      // Store conversation data
      this.storeConversation(conversation);
      
      console.log(`📝 Conversation logged: ${conversation.conversationId}`);
      this.emit('conversationLogged', conversation);
      
      return conversation.conversationId;
    } catch (error) {
      console.error('❌ Failed to log conversation:', error.message);
    }
  }

  /**
   * End current session
   */
  endSession(endData = {}) {
    try {
      if (!this.currentSession) {
        console.warn('⚠️ No active session to end');
        return;
      }

      this.currentSession.endTime = new Date().toISOString();
      this.currentSession.status = 'completed';
      
      // Calculate final metrics
      const duration = new Date(this.currentSession.endTime) - new Date(this.currentSession.startTime);
      this.currentSession.performance.totalDuration = duration;
      
      if (this.currentSession.interactions.length > 0) {
        const avgResponseTime = this.currentSession.interactions
          .reduce((sum, i) => sum + (i.metadata.responseTime || 0), 0) / this.currentSession.interactions.length;
        this.currentSession.performance.averageResponseTime = avgResponseTime;
      }

      // Add end data
      this.currentSession.endData = endData;
      
      // Store complete session
      this.storeSession(this.currentSession);
      
      console.log(`📝 Session ended: ${this.currentSession.sessionId} (${duration}ms)`);
      this.emit('sessionEnded', this.currentSession);
      
      const completedSession = this.currentSession;
      this.currentSession = null;
      
      return completedSession;
    } catch (error) {
      console.error('❌ Failed to end session:', error.message);
    }
  }

  /**
   * Store conversation in DigitalOcean Spaces
   */
  async storeConversation(conversation) {
    try {
      const userId = this.licenseManager.currentLicense?.userId || 'anonymous';
      await this.digitalOcean.storeConversation(userId, conversation);
    } catch (error) {
      console.error('❌ Failed to store conversation:', error.message);
    }
  }

  /**
   * Store session data
   */
  async storeSession(session) {
    try {
      const userId = this.licenseManager.currentLicense?.userId || 'anonymous';
      const userHash = this.digitalOcean.hashUserId(userId);
      const date = session.startTime.split('T')[0];
      
      const key = `sessions/${date}/${userHash}/${session.sessionId}.json`;
      await this.digitalOcean.uploadData(key, session);
    } catch (error) {
      console.error('❌ Failed to store session:', error.message);
    }
  }

  /**
   * Batch process pending logs
   */
  startBatchProcessor() {
    setInterval(() => {
      if (this.pendingLogs.length > 0) {
        this.flushLogs();
      }
    }, this.flushInterval);
  }

  /**
   * Flush pending logs to storage
   */
  async flushLogs() {
    try {
      if (this.pendingLogs.length === 0) return;
      
      const logsToFlush = [...this.pendingLogs];
      this.pendingLogs = [];
      
      // Group logs by session
      const sessionLogs = {};
      logsToFlush.forEach(log => {
        if (!sessionLogs[log.sessionId]) {
          sessionLogs[log.sessionId] = [];
        }
        sessionLogs[log.sessionId].push(log.interaction);
      });
      
      // Store each session's interactions
      for (const [sessionId, interactions] of Object.entries(sessionLogs)) {
        const userId = this.licenseManager.currentLicense?.userId || 'anonymous';
        const userHash = this.digitalOcean.hashUserId(userId);
        const timestamp = new Date().toISOString();
        const date = timestamp.split('T')[0];
        
        const key = `interactions/${date}/${userHash}/${sessionId}-${Date.now()}.json`;
        
        await this.digitalOcean.uploadData(key, {
          sessionId,
          timestamp,
          interactions,
          count: interactions.length
        });
      }
      
      console.log(`📤 Flushed ${logsToFlush.length} interaction logs`);
      this.emit('logsFlushed', logsToFlush.length);
    } catch (error) {
      console.error('❌ Failed to flush logs:', error.message);
      // Re-add failed logs to pending
      this.pendingLogs.unshift(...logsToFlush);
    }
  }

  /**
   * Update session performance metrics
   */
  updateSessionMetrics(interaction) {
    const perf = this.currentSession.performance;
    
    if (interaction.metadata.success) {
      perf.successfulInteractions++;
    } else {
      perf.failedInteractions++;
    }
    
    perf.totalTokens += interaction.metadata.tokens || 0;
    perf.totalCost += interaction.metadata.cost || 0;
  }

  /**
   * Sanitize content for storage (remove sensitive data)
   */
  sanitizeContent(content) {
    if (typeof content !== 'string') {
      content = JSON.stringify(content);
    }
    
    // Remove potential sensitive information
    return content
      .replace(/\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b/g, '[EMAIL]')
      .replace(/\b\d{4}[-\s]?\d{4}[-\s]?\d{4}[-\s]?\d{4}\b/g, '[CARD]')
      .replace(/\b\d{3}-\d{2}-\d{4}\b/g, '[SSN]')
      .replace(/\b(?:\d{1,3}\.){3}\d{1,3}\b/g, '[IP]');
  }

  /**
   * Sanitize message for storage
   */
  sanitizeMessage(message) {
    return {
      role: message.role,
      content: this.sanitizeContent(message.content),
      timestamp: message.timestamp || new Date().toISOString(),
      metadata: message.metadata || {}
    };
  }

  /**
   * Helper methods
   */
  generateSessionId() {
    return 'sess_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9);
  }

  generateInteractionId() {
    return 'int_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9);
  }

  generateConversationId() {
    return 'conv_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9);
  }

  getPreviousInteractionId() {
    const interactions = this.currentSession?.interactions || [];
    return interactions.length > 0 ? interactions[interactions.length - 1].interactionId : null;
  }

  /**
   * Get session statistics
   */
  getSessionStats() {
    if (!this.currentSession) {
      return null;
    }

    return {
      sessionId: this.currentSession.sessionId,
      duration: Date.now() - new Date(this.currentSession.startTime).getTime(),
      interactionCount: this.currentSession.interactions.length,
      performance: this.currentSession.performance,
      status: this.currentSession.status
    };
  }

  /**
   * Get logging statistics
   */
  getLoggingStats() {
    return {
      pendingLogs: this.pendingLogs.length,
      batchSize: this.batchSize,
      flushInterval: this.flushInterval,
      currentSession: this.currentSession ? this.currentSession.sessionId : null
    };
  }
}
