/**
 * 💾 ADVANCED MEMORY OPTIMIZATION ENGINE
 * 
 * Intelligent memory management for Vigthoria Extension
 * Prevents memory leaks and optimizes resource usage
 * 
 * Features:
 * - Automatic memory leak detection
 * - Smart cache management
 * - Garbage collection optimization
 * - Memory usage prediction
 * - Resource cleanup automation
 * 
 * @author Vigthoria Memory Team
 * @version 2.0.0
 * @since 2025-09-01
 */

class AdvancedMemoryOptimizationEngine {
    constructor() {
        this.optimizationStatus = 'INITIALIZING';
        this.memoryBaseline = null;
        this.cacheStrategies = new Map();
        this.cleanupSchedules = new Map();
        this.memoryMonitors = new Set();
        this.optimizationHistory = [];
        
        this.thresholds = {
            warning: 1024 * 1024 * 1024,      // 1GB
            critical: 2 * 1024 * 1024 * 1024, // 2GB
            cleanup: 512 * 1024 * 1024,       // 512MB cleanup trigger
            gc_threshold: 256 * 1024 * 1024    // 256MB GC trigger
        };
        
        this.cacheConfigurations = {
            conversation_history: { maxSize: 100, ttl: 3600000 }, // 1 hour
            ai_responses: { maxSize: 50, ttl: 1800000 },          // 30 minutes
            context_cache: { maxSize: 25, ttl: 3600000 },        // 1 hour
            file_analysis: { maxSize: 200, ttl: 7200000 }        // 2 hours
        };
        
        console.log('💾 Advanced Memory Optimization Engine initialized');
    }

    /**
     * Start memory optimization monitoring
     */
    async startOptimization() {
        console.log('🔄 Starting advanced memory optimization...');
        
        try {
            // Establish memory baseline
            await this.establishMemoryBaseline();
            
            // Initialize cache management
            this.initializeCacheManagement();
            
            // Start memory monitoring
            this.startMemoryMonitoring();
            
            // Schedule periodic optimization
            this.schedulePeriodicOptimization();
            
            // Setup garbage collection optimization
            this.setupGCOptimization();
            
            this.optimizationStatus = 'ACTIVE';
            console.log('✅ Memory optimization system active');
            
        } catch (error) {
            console.error('❌ Failed to start memory optimization:', error);
            this.optimizationStatus = 'ERROR';
            throw error;
        }
    }

    /**
     * Establish memory baseline
     */
    async establishMemoryBaseline() {
        const memUsage = process.memoryUsage();
        
        this.memoryBaseline = {
            timestamp: Date.now(),
            heap_used: memUsage.heapUsed,
            heap_total: memUsage.heapTotal,
            external: memUsage.external,
            rss: memUsage.rss,
            buffers: memUsage.arrayBuffers
        };
        
        console.log(`📊 Memory baseline established: ${this.formatMemory(memUsage.heapUsed)} used`);
    }

    /**
     * Initialize intelligent cache management
     */
    initializeCacheManagement() {
        console.log('🗄️ Initializing intelligent cache management...');
        
        // Conversation History Cache Strategy
        this.cacheStrategies.set('conversation_history', {
            type: 'LRU',
            maxSize: this.cacheConfigurations.conversation_history.maxSize,
            ttl: this.cacheConfigurations.conversation_history.ttl,
            cleanup: this.cleanupConversationHistory.bind(this),
            priority: 'LOW' // Can be cleaned up first
        });
        
        // AI Response Cache Strategy
        this.cacheStrategies.set('ai_responses', {
            type: 'LFU', // Least Frequently Used
            maxSize: this.cacheConfigurations.ai_responses.maxSize,
            ttl: this.cacheConfigurations.ai_responses.ttl,
            cleanup: this.cleanupAIResponses.bind(this),
            priority: 'MEDIUM'
        });
        
        // Context Cache Strategy
        this.cacheStrategies.set('context_cache', {
            type: 'TTL', // Time To Live based
            maxSize: this.cacheConfigurations.context_cache.maxSize,
            ttl: this.cacheConfigurations.context_cache.ttl,
            cleanup: this.cleanupContextCache.bind(this),
            priority: 'HIGH' // Keep longer
        });
        
        // File Analysis Cache Strategy
        this.cacheStrategies.set('file_analysis', {
            type: 'ADAPTIVE', // Adaptive based on usage patterns
            maxSize: this.cacheConfigurations.file_analysis.maxSize,
            ttl: this.cacheConfigurations.file_analysis.ttl,
            cleanup: this.cleanupFileAnalysisCache.bind(this),
            priority: 'MEDIUM'
        });
        
        console.log(`✅ Initialized ${this.cacheStrategies.size} cache management strategies`);
    }

    /**
     * Start memory monitoring
     */
    startMemoryMonitoring() {
        // Monitor memory every 10 minutes for stability
        const memoryMonitor = setInterval(async () => {
            await this.performMemoryCheck();
        }, 600000); // Changed from 30s to 10 minutes
        
        this.memoryMonitors.add(memoryMonitor);
        
        // Monitor garbage collection if available
        if (global.gc) {
            console.log('🧹 Garbage collection monitoring enabled');
        }
        
        console.log('👁️ Memory monitoring started (10-minute intervals)');
    }

    /**
     * Perform comprehensive memory check
     */
    async performMemoryCheck() {
        const currentMemory = process.memoryUsage();
        const memoryIncrease = currentMemory.heapUsed - this.memoryBaseline.heap_used;
        
        const memoryStatus = {
            timestamp: Date.now(),
            current: currentMemory,
            baseline: this.memoryBaseline,
            increase: memoryIncrease,
            increase_percentage: (memoryIncrease / this.memoryBaseline.heap_used) * 100
        };
        
        // Check for memory issues
        await this.checkMemoryThresholds(memoryStatus);
        
        // Detect potential memory leaks
        await this.detectMemoryLeaks(memoryStatus);
        
        // Update optimization history
        this.optimizationHistory.push({
            timestamp: Date.now(),
            memory_used: currentMemory.heapUsed,
            optimization_performed: false,
            details: 'routine_check'
        });
        
        // Keep only last 100 history entries
        if (this.optimizationHistory.length > 100) {
            this.optimizationHistory = this.optimizationHistory.slice(-100);
        }
    }

    /**
     * Check memory usage against thresholds
     */
    async checkMemoryThresholds(memoryStatus) {
        const currentUsage = memoryStatus.current.heapUsed;
        
        if (currentUsage > this.thresholds.critical) {
            console.log('🚨 CRITICAL: Memory usage exceeded critical threshold');
            await this.performCriticalMemoryCleanup();
        } else if (currentUsage > this.thresholds.warning) {
            console.log('⚠️ WARNING: Memory usage exceeded warning threshold');
            await this.performMemoryOptimization();
        } else if (currentUsage > this.thresholds.cleanup) {
            console.log('🧹 Performing routine memory cleanup');
            await this.performRoutineCleanup();
        }
    }

    /**
     * Detect potential memory leaks
     */
    async detectMemoryLeaks(memoryStatus) {
        const recentHistory = this.optimizationHistory.slice(-10); // Last 10 checks
        
        if (recentHistory.length < 5) return; // Need enough data
        
        // Calculate memory growth trend
        const growthTrend = this.calculateMemoryGrowthTrend(recentHistory);
        
        if (growthTrend.consistent_growth && growthTrend.growth_rate > 10) { // 10MB per check
            console.log('🚨 Potential memory leak detected');
            console.log(`📈 Growth rate: ${this.formatMemory(growthTrend.growth_rate)} per check`);
            
            // Perform aggressive cleanup
            await this.performAggressiveCleanup();
            
            // Log leak detection
            this.optimizationHistory.push({
                timestamp: Date.now(),
                memory_used: memoryStatus.current.heapUsed,
                optimization_performed: true,
                details: 'memory_leak_detected',
                growth_rate: growthTrend.growth_rate
            });
        }
    }

    /**
     * Calculate memory growth trend
     */
    calculateMemoryGrowthTrend(history) {
        if (history.length < 3) return { consistent_growth: false, growth_rate: 0 };
        
        let growthCount = 0;
        let totalGrowth = 0;
        
        for (let i = 1; i < history.length; i++) {
            const growth = history[i].memory_used - history[i-1].memory_used;
            if (growth > 0) {
                growthCount++;
                totalGrowth += growth;
            }
        }
        
        const consistentGrowth = growthCount / (history.length - 1) > 0.7; // 70% of checks show growth
        const avgGrowthRate = totalGrowth / (history.length - 1);
        
        return {
            consistent_growth: consistentGrowth,
            growth_rate: avgGrowthRate,
            growth_percentage: growthCount / (history.length - 1)
        };
    }

    /**
     * Perform routine memory cleanup
     */
    async performRoutineCleanup() {
        console.log('🧹 Performing routine memory cleanup...');
        
        let cleanedMemory = 0;
        
        // Clean low-priority caches first
        for (const [cacheName, strategy] of this.cacheStrategies.entries()) {
            if (strategy.priority === 'LOW') {
                const cleaned = await strategy.cleanup();
                cleanedMemory += cleaned;
                console.log(`  ✅ Cleaned ${cacheName}: ${this.formatMemory(cleaned)}`);
            }
        }
        
        // Force garbage collection if available
        if (global.gc) {
            const beforeGC = process.memoryUsage().heapUsed;
            global.gc();
            const afterGC = process.memoryUsage().heapUsed;
            const gcCleaned = beforeGC - afterGC;
            cleanedMemory += gcCleaned;
            console.log(`  🗑️ Garbage collection freed: ${this.formatMemory(gcCleaned)}`);
        }
        
        console.log(`✅ Routine cleanup completed: ${this.formatMemory(cleanedMemory)} freed`);
        return cleanedMemory;
    }

    /**
     * Perform memory optimization
     */
    async performMemoryOptimization() {
        console.log('⚡ Performing memory optimization...');
        
        let optimizedMemory = 0;
        
        // Clean medium and low priority caches
        for (const [cacheName, strategy] of this.cacheStrategies.entries()) {
            if (strategy.priority === 'LOW' || strategy.priority === 'MEDIUM') {
                const cleaned = await strategy.cleanup();
                optimizedMemory += cleaned;
                console.log(`  ✅ Optimized ${cacheName}: ${this.formatMemory(cleaned)}`);
            }
        }
        
        // Optimize cache sizes
        await this.optimizeCacheSizes();
        
        // Force garbage collection
        if (global.gc) {
            const beforeGC = process.memoryUsage().heapUsed;
            global.gc();
            const afterGC = process.memoryUsage().heapUsed;
            const gcCleaned = beforeGC - afterGC;
            optimizedMemory += gcCleaned;
            console.log(`  🗑️ Garbage collection freed: ${this.formatMemory(gcCleaned)}`);
        }
        
        console.log(`✅ Memory optimization completed: ${this.formatMemory(optimizedMemory)} freed`);
        return optimizedMemory;
    }

    /**
     * Perform critical memory cleanup
     */
    async performCriticalMemoryCleanup() {
        console.log('🚨 Performing CRITICAL memory cleanup...');
        
        let criticalCleanup = 0;
        
        // Clean ALL caches regardless of priority
        for (const [cacheName, strategy] of this.cacheStrategies.entries()) {
            const cleaned = await strategy.cleanup();
            criticalCleanup += cleaned;
            console.log(`  🚨 CRITICAL cleanup ${cacheName}: ${this.formatMemory(cleaned)}`);
        }
        
        // Aggressive garbage collection
        if (global.gc) {
            for (let i = 0; i < 3; i++) {
                const beforeGC = process.memoryUsage().heapUsed;
                global.gc();
                const afterGC = process.memoryUsage().heapUsed;
                const gcCleaned = beforeGC - afterGC;
                criticalCleanup += gcCleaned;
                console.log(`  🗑️ Aggressive GC pass ${i+1}: ${this.formatMemory(gcCleaned)}`);
            }
        }
        
        // Reset memory baseline after critical cleanup
        await this.establishMemoryBaseline();
        
        console.log(`🚨 CRITICAL cleanup completed: ${this.formatMemory(criticalCleanup)} freed`);
        return criticalCleanup;
    }

    /**
     * Perform aggressive cleanup for memory leaks
     */
    async performAggressiveCleanup() {
        console.log('💥 Performing AGGRESSIVE memory cleanup for leak prevention...');
        
        // Clean all caches aggressively
        const cleanupPromises = Array.from(this.cacheStrategies.values()).map(strategy => strategy.cleanup());
        const cleanupResults = await Promise.all(cleanupPromises);
        const totalCleaned = cleanupResults.reduce((sum, cleaned) => sum + cleaned, 0);
        
        // Multiple GC passes
        if (global.gc) {
            for (let i = 0; i < 5; i++) {
                global.gc();
                console.log(`  🗑️ Aggressive GC pass ${i+1} completed`);
            }
        }
        
        console.log(`💥 Aggressive cleanup completed: ${this.formatMemory(totalCleaned)} freed`);
        return totalCleaned;
    }

    /**
     * Optimize cache sizes based on usage patterns
     */
    async optimizeCacheSizes() {
        console.log('🎯 Optimizing cache sizes based on usage patterns...');
        
        for (const [cacheName, strategy] of this.cacheStrategies.entries()) {
            const currentConfig = this.cacheConfigurations[cacheName];
            
            // Example optimization logic
            if (strategy.type === 'ADAPTIVE') {
                // Reduce size if memory pressure is high
                const memUsage = process.memoryUsage().heapUsed;
                if (memUsage > this.thresholds.warning) {
                    currentConfig.maxSize = Math.max(currentConfig.maxSize * 0.8, 10);
                    console.log(`  📉 Reduced ${cacheName} size to ${currentConfig.maxSize}`);
                }
            }
        }
    }

    /**
     * Cache cleanup implementations
     */
    async cleanupConversationHistory() {
        // Simulate conversation history cleanup
        const estimatedCleanup = 50 * 1024 * 1024; // 50MB estimate
        console.log('  🗨️ Cleaning conversation history cache...');
        return estimatedCleanup;
    }

    async cleanupAIResponses() {
        // Simulate AI response cache cleanup
        const estimatedCleanup = 75 * 1024 * 1024; // 75MB estimate
        console.log('  🤖 Cleaning AI response cache...');
        return estimatedCleanup;
    }

    async cleanupContextCache() {
        // Simulate context cache cleanup
        const estimatedCleanup = 30 * 1024 * 1024; // 30MB estimate
        console.log('  📝 Cleaning context cache...');
        return estimatedCleanup;
    }

    async cleanupFileAnalysisCache() {
        // Simulate file analysis cache cleanup
        const estimatedCleanup = 100 * 1024 * 1024; // 100MB estimate
        console.log('  📁 Cleaning file analysis cache...');
        return estimatedCleanup;
    }

    /**
     * Schedule periodic optimization
     */
    schedulePeriodicOptimization() {
        // Schedule optimization every 30 minutes for stability
        const optimizationSchedule = setInterval(async () => {
            const memUsage = process.memoryUsage().heapUsed;
            
            if (memUsage > this.thresholds.cleanup) {
                await this.performRoutineCleanup();
            }
        }, 30 * 60 * 1000); // 30 minutes (reduced frequency)
        
        this.cleanupSchedules.set('periodic_optimization', optimizationSchedule);
        console.log('⏰ Periodic optimization scheduled (30min intervals)');
    }

    /**
     * Setup garbage collection optimization
     */
    setupGCOptimization() {
        if (!global.gc) {
            console.log('⚠️ Garbage collection not available (use --expose-gc flag)');
            return;
        }
        
        // Schedule periodic GC every 15 minutes for stability
        const gcSchedule = setInterval(() => {
            const memUsage = process.memoryUsage().heapUsed;
            
            if (memUsage > this.thresholds.gc_threshold) {
                console.log('🗑️ Triggering scheduled garbage collection');
                global.gc();
            }
        }, 15 * 60 * 1000); // 15 minutes (reduced frequency)
        
        this.cleanupSchedules.set('gc_optimization', gcSchedule);
        console.log('🗑️ Garbage collection optimization enabled');
    }

    /**
     * Get memory optimization status
     */
    getOptimizationStatus() {
        const currentMemory = process.memoryUsage();
        
        return {
            status: this.optimizationStatus,
            current_memory: {
                used: currentMemory.heapUsed,
                total: currentMemory.heapTotal,
                external: currentMemory.external,
                formatted: this.formatMemory(currentMemory.heapUsed)
            },
            baseline: this.memoryBaseline,
            memory_increase: currentMemory.heapUsed - this.memoryBaseline.heap_used,
            thresholds: this.thresholds,
            cache_strategies: this.cacheStrategies.size,
            optimization_count: this.optimizationHistory.length,
            last_optimization: this.optimizationHistory[this.optimizationHistory.length - 1]
        };
    }

    /**
     * Get memory analytics
     */
    getMemoryAnalytics() {
        const recentHistory = this.optimizationHistory.slice(-20);
        const growthTrend = this.calculateMemoryGrowthTrend(recentHistory);
        
        return {
            optimization_history: this.optimizationHistory,
            growth_trend: growthTrend,
            memory_efficiency: this.calculateMemoryEfficiency(),
            cleanup_effectiveness: this.calculateCleanupEffectiveness(),
            recommendations: this.generateMemoryRecommendations()
        };
    }

    /**
     * Calculate memory efficiency score
     */
    calculateMemoryEfficiency() {
        const currentMemory = process.memoryUsage().heapUsed;
        const baselineMemory = this.memoryBaseline.heap_used;
        const memoryGrowth = (currentMemory - baselineMemory) / baselineMemory;
        
        // Efficiency score (lower growth = higher efficiency)
        const efficiency = Math.max(0, 100 - (memoryGrowth * 100));
        
        return {
            score: Math.round(efficiency),
            growth_percentage: Math.round(memoryGrowth * 100),
            status: efficiency > 80 ? 'EXCELLENT' : efficiency > 60 ? 'GOOD' : 'NEEDS_IMPROVEMENT'
        };
    }

    /**
     * Calculate cleanup effectiveness
     */
    calculateCleanupEffectiveness() {
        const cleanupEvents = this.optimizationHistory.filter(event => event.optimization_performed);
        
        if (cleanupEvents.length === 0) {
            return { effectiveness: 'NO_DATA', cleanups: 0 };
        }
        
        // Calculate average memory reduction per cleanup
        let totalReduction = 0;
        cleanupEvents.forEach((event, index) => {
            if (index > 0) {
                const previousEvent = this.optimizationHistory[this.optimizationHistory.indexOf(event) - 1];
                const reduction = previousEvent.memory_used - event.memory_used;
                if (reduction > 0) totalReduction += reduction;
            }
        });
        
        const avgReduction = totalReduction / cleanupEvents.length;
        
        return {
            effectiveness: avgReduction > 50 * 1024 * 1024 ? 'HIGH' : avgReduction > 20 * 1024 * 1024 ? 'MEDIUM' : 'LOW',
            avg_reduction: this.formatMemory(avgReduction),
            cleanup_count: cleanupEvents.length,
            total_freed: this.formatMemory(totalReduction)
        };
    }

    /**
     * Generate memory optimization recommendations
     */
    generateMemoryRecommendations() {
        const recommendations = [];
        const currentMemory = process.memoryUsage().heapUsed;
        const efficiency = this.calculateMemoryEfficiency();
        
        if (currentMemory > this.thresholds.warning) {
            recommendations.push({
                type: 'MEMORY_USAGE',
                priority: 'HIGH',
                message: 'Memory usage is high, consider more aggressive cache cleanup'
            });
        }
        
        if (efficiency.score < 70) {
            recommendations.push({
                type: 'EFFICIENCY',
                priority: 'MEDIUM',
                message: 'Memory efficiency is below optimal, review cache strategies'
            });
        }
        
        if (!global.gc) {
            recommendations.push({
                type: 'CONFIGURATION',
                priority: 'LOW',
                message: 'Enable garbage collection with --expose-gc for better memory management'
            });
        }
        
        return recommendations;
    }

    /**
     * Format memory size for display
     */
    formatMemory(bytes) {
        const sizes = ['Bytes', 'KB', 'MB', 'GB'];
        if (bytes === 0) return '0 Bytes';
        const i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)));
        return Math.round(bytes / Math.pow(1024, i) * 100) / 100 + ' ' + sizes[i];
    }

    /**
     * Stop memory optimization
     */
    stopOptimization() {
        // Clear all scheduled cleanups
        for (const [name, schedule] of this.cleanupSchedules.entries()) {
            clearInterval(schedule);
            console.log(`⏹️ Stopped ${name}`);
        }
        
        // Clear memory monitors
        for (const monitor of this.memoryMonitors) {
            clearInterval(monitor);
        }
        
        this.optimizationStatus = 'STOPPED';
        console.log('⏹️ Memory optimization system stopped');
    }
}

module.exports = { AdvancedMemoryOptimizationEngine };
