/**
 * Performance Manager
 *
 * Central orchestrator for all performance optimizations:
 * - Coordinates lazy loading, caching, and request optimization
 * - Provides unified API for performance monitoring
 * - Manages performance budgets and thresholds
 */
import { EventEmitter } from 'events';
import { initializeLazyLoader } from './lazy-loader.js';
import { getToolCache } from './tool-cache.js';
import { getRequestOptimizer } from './request-optimizer.js';
import { getApiCache } from '../utils/semantic-cache.js';
// ============================================================================
// Default Configuration
// ============================================================================
const DEFAULT_CONFIG = {
    enabled: true,
    lazyLoading: true,
    toolCaching: true,
    requestOptimization: true,
    apiCaching: true,
    budgetMs: 5000, // 5 second budget
    enableMetrics: true,
    metricsRetention: 1000,
};
// ============================================================================
// Performance Manager Class
// ============================================================================
export class PerformanceManager extends EventEmitter {
    config;
    lazyLoader = null;
    toolCache = null;
    requestOptimizer = null;
    apiCache = null;
    metrics = [];
    initialized = false;
    constructor(config = {}) {
        super();
        this.config = { ...DEFAULT_CONFIG, ...config };
    }
    /**
     * Initialize all performance systems
     */
    async initialize() {
        if (this.initialized)
            return;
        if (this.config.lazyLoading) {
            this.lazyLoader = initializeLazyLoader();
            this.setupLazyLoaderEvents();
        }
        if (this.config.toolCaching) {
            this.toolCache = getToolCache();
            this.setupToolCacheEvents();
        }
        if (this.config.requestOptimization) {
            this.requestOptimizer = getRequestOptimizer();
            this.setupRequestOptimizerEvents();
        }
        if (this.config.apiCaching) {
            this.apiCache = getApiCache();
        }
        this.initialized = true;
        this.emit('initialized');
    }
    /**
     * Record a performance metric
     */
    recordMetric(metric) {
        if (!this.config.enableMetrics)
            return;
        const fullMetric = {
            ...metric,
            timestamp: Date.now(),
        };
        this.metrics.push(fullMetric);
        // Trim old metrics
        if (this.metrics.length > this.config.metricsRetention) {
            this.metrics = this.metrics.slice(-this.config.metricsRetention);
        }
        this.emit('metric', fullMetric);
        // Check budget
        if (metric.duration > this.config.budgetMs) {
            this.emit('budget:exceeded', {
                operation: metric.operation,
                duration: metric.duration,
                budget: this.config.budgetMs,
            });
        }
    }
    /**
     * Measure an async operation
     */
    async measure(operation, fn, metadata) {
        const startTime = Date.now();
        let success = true;
        try {
            return await fn();
        }
        catch (error) {
            success = false;
            throw error;
        }
        finally {
            this.recordMetric({
                operation,
                duration: Date.now() - startTime,
                cached: false,
                success,
                metadata,
            });
        }
    }
    /**
     * Get performance summary
     */
    getSummary() {
        const lazyLoaderStats = this.lazyLoader?.getStats() || {
            totalModules: 0,
            loadedModules: 0,
            totalLoadTime: 0,
            averageLoadTime: 0,
        };
        const toolCacheStats = this.toolCache?.getStats() || {
            hits: 0,
            misses: 0,
            hitRate: 0,
            savedCalls: 0,
            savedTime: 0,
        };
        const requestOptimizerStats = this.requestOptimizer?.getStats() || {
            totalRequests: 0,
            successfulRequests: 0,
            failedRequests: 0,
            retriedRequests: 0,
            deduplicatedRequests: 0,
            averageLatency: 0,
            currentConcurrency: 0,
        };
        const apiCacheStats = this.apiCache?.getStats() || {
            hits: 0,
            misses: 0,
            hitRate: 0,
            totalEntries: 0,
            avgSimilarity: 0,
            semanticHits: 0,
            exactHits: 0,
            evictions: 0,
        };
        // Calculate overall stats
        const cachedOps = this.metrics.filter((m) => m.cached).length;
        const totalOps = this.metrics.length;
        const avgDuration = totalOps > 0
            ? this.metrics.reduce((sum, m) => sum + m.duration, 0) / totalOps
            : 0;
        return {
            lazyLoader: lazyLoaderStats,
            toolCache: toolCacheStats,
            requestOptimizer: requestOptimizerStats,
            apiCache: {
                hits: apiCacheStats.hits,
                misses: apiCacheStats.misses,
                hitRate: apiCacheStats.hitRate,
                entries: apiCacheStats.totalEntries,
            },
            overall: {
                totalOperations: totalOps,
                cachedOperations: cachedOps,
                cacheHitRate: totalOps > 0 ? cachedOps / totalOps : 0,
                averageDuration: avgDuration,
                estimatedTimeSaved: toolCacheStats.savedTime +
                    requestOptimizerStats.deduplicatedRequests * 500, // Estimate 500ms per deduplicated request
            },
        };
    }
    /**
     * Get recent metrics
     */
    getMetrics(limit) {
        const metrics = [...this.metrics];
        return limit ? metrics.slice(-limit) : metrics;
    }
    /**
     * Get slow operations
     */
    getSlowOperations(thresholdMs = 1000) {
        return this.metrics.filter((m) => m.duration > thresholdMs);
    }
    /**
     * Clear all caches
     */
    clearCaches() {
        this.toolCache?.clear();
        this.apiCache?.clear();
        this.emit('caches:cleared');
    }
    /**
     * Invalidate caches for a file
     */
    invalidateForFile(filePath) {
        this.toolCache?.invalidateForFile(filePath);
        this.emit('cache:invalidated', { filePath });
    }
    /**
     * Reset all statistics
     */
    resetStats() {
        this.metrics = [];
        this.toolCache?.resetStats();
        this.requestOptimizer?.resetStats();
        this.emit('stats:reset');
    }
    /**
     * Get lazy loader instance
     */
    getLazyLoader() {
        return this.lazyLoader;
    }
    /**
     * Get tool cache instance
     */
    getToolCache() {
        return this.toolCache;
    }
    /**
     * Get request optimizer instance
     */
    getRequestOptimizer() {
        return this.requestOptimizer;
    }
    /**
     * Update configuration
     */
    updateConfig(config) {
        this.config = { ...this.config, ...config };
        this.emit('config:updated', this.config);
    }
    /**
     * Dispose all resources
     */
    dispose() {
        this.lazyLoader?.clear();
        this.toolCache?.dispose();
        this.requestOptimizer?.clear();
        this.apiCache?.dispose();
        this.removeAllListeners();
        this.initialized = false;
    }
    // ============================================================================
    // Private Methods
    // ============================================================================
    setupLazyLoaderEvents() {
        if (!this.lazyLoader)
            return;
        this.lazyLoader.on('module:loaded', ({ name, loadTime }) => {
            this.recordMetric({
                operation: `lazy:${name}`,
                duration: loadTime,
                cached: false,
                success: true,
            });
        });
        this.lazyLoader.on('module:error', ({ name, error }) => {
            this.emit('error', { source: 'lazyLoader', name, error });
        });
    }
    setupToolCacheEvents() {
        if (!this.toolCache)
            return;
        this.toolCache.on('hit', ({ key }) => {
            this.recordMetric({
                operation: `cache:hit:${key}`,
                duration: 0,
                cached: true,
                success: true,
            });
        });
        this.toolCache.on('miss', ({ key }) => {
            this.recordMetric({
                operation: `cache:miss:${key}`,
                duration: 0,
                cached: false,
                success: true,
            });
        });
    }
    setupRequestOptimizerEvents() {
        if (!this.requestOptimizer)
            return;
        this.requestOptimizer.on('success', ({ key, latency }) => {
            this.recordMetric({
                operation: `request:${key}`,
                duration: latency,
                cached: false,
                success: true,
            });
        });
        this.requestOptimizer.on('failure', ({ key, error }) => {
            this.emit('error', { source: 'requestOptimizer', key, error });
        });
        this.requestOptimizer.on('deduplicated', ({ key }) => {
            this.recordMetric({
                operation: `request:dedup:${key}`,
                duration: 0,
                cached: true,
                success: true,
            });
        });
    }
}
// ============================================================================
// Singleton Instance
// ============================================================================
let managerInstance = null;
export function getPerformanceManager(config) {
    if (!managerInstance) {
        managerInstance = new PerformanceManager(config);
    }
    return managerInstance;
}
export async function initializePerformanceManager(config) {
    const manager = getPerformanceManager(config);
    await manager.initialize();
    return manager;
}
export function resetPerformanceManager() {
    if (managerInstance) {
        managerInstance.dispose();
    }
    managerInstance = null;
}
// ============================================================================
// Utility Functions
// ============================================================================
/**
 * Measure an async operation with automatic recording
 */
export async function measureOperation(operation, fn, metadata) {
    const manager = getPerformanceManager();
    return manager.measure(operation, fn, metadata);
}
/**
 * Get a quick performance summary
 */
export function getPerformanceSummary() {
    return getPerformanceManager().getSummary();
}
//# sourceMappingURL=performance-manager.js.map