/**
 * 🛡️ VIGTHORIA ERROR BOUNDARY SYSTEM
 * Comprehensive error handling and recovery mechanisms
 */

// Real VSCode import - No Mock!
const vscode = require('vscode');

const fs = require('fs').promises;
const path = require('path');

class ErrorBoundarySystem {
    constructor() {
        this.errorHistory = new Map();
        this.recoveryStrategies = new Map();
        this.circuitBreakers = new Map();
        this.fallbackResponses = new Map();
        this.errorMetrics = {
            totalErrors: 0,
            criticalErrors: 0,
            recoveredErrors: 0,
            lastErrorTime: null
        };
        
        this.initializeErrorBoundaries();
        this.setupGlobalErrorHandlers();
    }

    initializeErrorBoundaries() {
        // AI Service Error Boundaries
        this.registerErrorBoundary('ai_orchestrator', {
            maxFailures: 3,
            resetTimeout: 60000,
            fallbackStrategy: 'graceful_degradation'
        });

        this.registerErrorBoundary('model_manager', {
            maxFailures: 5,
            resetTimeout: 30000,
            fallbackStrategy: 'model_fallback'
        });

        this.registerErrorBoundary('sub_agent_system', {
            maxFailures: 2,
            resetTimeout: 120000,
            fallbackStrategy: 'agent_isolation'
        });

        this.registerErrorBoundary('file_operations', {
            maxFailures: 10,
            resetTimeout: 15000,
            fallbackStrategy: 'readonly_mode'
        });

        console.log('🛡️ Error boundaries initialized for all critical systems');
    }

    setupGlobalErrorHandlers() {
        // Unhandled Promise Rejections
        process.on('unhandledRejection', (reason, promise) => {
            this.handleCriticalError('unhandled_promise_rejection', {
                reason: reason,
                promise: promise.toString(),
                stack: reason?.stack
            });
        });

        // Uncaught Exceptions
        process.on('uncaughtException', (error) => {
            this.handleCriticalError('uncaught_exception', {
                message: error.message,
                stack: error.stack,
                name: error.name
            });
        });

        // VS Code Extension Specific Errors
        this.setupVSCodeErrorHandlers();
    }

    setupVSCodeErrorHandlers() {
        // Webview errors
        this.registerErrorHandler('webview_error', async (error, context) => {
            console.error('🚨 Webview Error:', error);
            
            // Attempt to recover webview
            if (context.webview) {
                try {
                    await this.recoverWebview(context.webview);
                    return { recovered: true, strategy: 'webview_restart' };
                } catch (recoveryError) {
                    return { recovered: false, error: recoveryError.message };
                }
            }
            
            return { recovered: false, error: 'No webview context available' };
        });

        // AI service communication errors
        this.registerErrorHandler('ai_service_error', async (error, context) => {
            const serviceName = context.service || 'unknown';
            const circuitBreaker = this.getCircuitBreaker(serviceName);
            
            if (circuitBreaker.isOpen()) {
                return this.getFallbackResponse(serviceName, context.request);
            }
            
            circuitBreaker.recordFailure();
            
            // Try alternative AI service
            const alternativeService = this.getAlternativeService(serviceName);
            if (alternativeService) {
                try {
                    const response = await this.retryWithAlternativeService(
                        alternativeService, 
                        context.request
                    );
                    return { recovered: true, response, strategy: 'alternative_service' };
                } catch (altError) {
                    return this.getFallbackResponse(serviceName, context.request);
                }
            }
            
            return this.getFallbackResponse(serviceName, context.request);
        });

        // File operation errors
        this.registerErrorHandler('file_operation_error', async (error, context) => {
            const operation = context.operation || 'unknown';
            const filePath = context.filePath || 'unknown';
            
            console.warn(`📁 File operation failed: ${operation} on ${filePath}`);
            
            // Implement retry logic with exponential backoff
            if (context.retryCount < 3) {
                const delay = Math.pow(2, context.retryCount) * 1000;
                await new Promise(resolve => setTimeout(resolve, delay));
                
                try {
                    return await this.retryFileOperation(operation, context);
                } catch (retryError) {
                    context.retryCount++;
                    return this.handleError('file_operation_error', retryError, context);
                }
            }
            
            // Switch to safe mode
            return this.enterSafeMode('file_operations', context);
        });
    }

    registerErrorBoundary(boundaryName, config) {
        this.circuitBreakers.set(boundaryName, new CircuitBreaker(config));
        this.recoveryStrategies.set(boundaryName, config.fallbackStrategy);
    }

    registerErrorHandler(errorType, handler) {
        this.recoveryStrategies.set(errorType, handler);
    }

    async handleError(errorType, error, context = {}) {
        this.errorMetrics.totalErrors++;
        this.errorMetrics.lastErrorTime = new Date();
        
        // Log error with context
        const errorEntry = {
            timestamp: new Date().toISOString(),
            type: errorType,
            message: error.message || error,
            stack: error.stack,
            context: context,
            severity: this.classifyErrorSeverity(errorType, error)
        };
        
        this.errorHistory.set(Date.now(), errorEntry);
        
        // Apply circuit breaker logic
        const circuitBreaker = this.getCircuitBreaker(errorType);
        if (circuitBreaker && circuitBreaker.isOpen()) {
            return this.getFallbackResponse(errorType, context);
        }
        
        if (circuitBreaker) {
            circuitBreaker.recordFailure();
        }
        
        // Attempt recovery
        const handler = this.recoveryStrategies.get(errorType);
        if (handler && typeof handler === 'function') {
            try {
                const recoveryResult = await handler(error, context);
                if (recoveryResult.recovered) {
                    this.errorMetrics.recoveredErrors++;
                    console.log(`✅ Error recovered: ${errorType} using ${recoveryResult.strategy}`);
                    return recoveryResult;
                }
            } catch (recoveryError) {
                console.error(`❌ Recovery failed for ${errorType}:`, recoveryError);
            }
        }
        
        // Critical error handling
        if (errorEntry.severity === 'critical') {
            this.handleCriticalError(errorType, error, context);
        }
        
        // Show user-friendly error message
        this.showUserError(errorType, error, context);
        
        return { recovered: false, error: error.message };
    }

    handleCriticalError(errorType, error, context = {}) {
        this.errorMetrics.criticalErrors++;
        
        console.error(`🚨 CRITICAL ERROR [${errorType}]:`, error);
        
        // Notify user immediately
        vscode.window.showErrorMessage(
            `Vigthoria AI encountered a critical error. The extension will attempt to recover.`,
            'View Details',
            'Report Issue'
        ).then(selection => {
            if (selection === 'View Details') {
                this.showErrorDetails(errorType, error);
            } else if (selection === 'Report Issue') {
                this.openIssueReporter(errorType, error);
            }
        });
        
        // Attempt system recovery
        this.attemptSystemRecovery(errorType, error, context);
    }

    classifyErrorSeverity(errorType, error) {
        const criticalTypes = [
            'uncaught_exception',
            'unhandled_promise_rejection',
            'system_failure',
            'data_corruption'
        ];
        
        const highSeverityTypes = [
            'ai_service_error',
            'model_manager_error',
            'authentication_error'
        ];
        
        if (criticalTypes.includes(errorType)) {
            return 'critical';
        }
        
        if (highSeverityTypes.includes(errorType)) {
            return 'high';
        }
        
        if (error?.message?.includes('ENOENT') || error?.message?.includes('permission')) {
            return 'medium';
        }
        
        return 'low';
    }

    getCircuitBreaker(serviceName) {
        return this.circuitBreakers.get(serviceName);
    }

    getFallbackResponse(serviceName, context) {
        const fallbackResponses = {
            'ai_orchestrator': {
                success: false,
                response: "I'm experiencing technical difficulties. Please try again in a moment.",
                fallback: true,
                service: 'local_fallback'
            },
            'model_manager': {
                success: true,
                response: "Using cached response while AI services recover.",
                fallback: true,
                cached: true
            },
            'sub_agent_system': {
                success: false,
                response: "Sub-agent system is temporarily unavailable. Using simplified processing.",
                fallback: true,
                simplified: true
            }
        };
        
        return fallbackResponses[serviceName] || {
            success: false,
            response: "Service temporarily unavailable. Please try again later.",
            fallback: true
        };
    }

    getAlternativeService(serviceName) {
        const alternatives = {
            'ollama': 'huggingface',
            'huggingface': 'ollama',
            'agent': 'local_agent',
            'operator': 'local_operator'
        };
        
        return alternatives[serviceName];
    }

    async retryWithAlternativeService(serviceName, request) {
        // Implementation for alternative service retry
        console.log(`🔄 Retrying with alternative service: ${serviceName}`);
        
        // This would be implemented with actual service switching logic
        throw new Error('Alternative service not available');
    }

    async recoverWebview(webview) {
        console.log('🔄 Attempting webview recovery...');
        
        try {
            // Clear webview and reinitialize
            webview.html = this.getEmptyWebviewContent();
            
            // Wait a moment for cleanup
            await new Promise(resolve => setTimeout(resolve, 1000));
            
            // Reload with fresh content
            const { getWebviewContent } = require('../ui/webview-content');
            webview.html = getWebviewContent();
            
            return true;
        } catch (error) {
            console.error('Webview recovery failed:', error);
            throw error;
        }
    }

    getEmptyWebviewContent() {
        return `<!DOCTYPE html>
        <html>
        <head><title>Vigthoria AI - Recovering</title></head>
        <body>
            <div style="display:flex;align-items:center;justify-content:center;height:100vh;">
                <div>🔄 Recovering Vigthoria AI...</div>
            </div>
        </body>
        </html>`;
    }

    async retryFileOperation(operation, context) {
        console.log(`🔄 Retrying file operation: ${operation}`);
        
        // Add implementation for specific file operations
        switch (operation) {
            case 'read':
                return await fs.readFile(context.filePath, context.encoding || 'utf8');
            case 'write':
                return await fs.writeFile(context.filePath, context.content);
            case 'delete':
                return await fs.unlink(context.filePath);
            default:
                throw new Error(`Unknown file operation: ${operation}`);
        }
    }

    enterSafeMode(systemName, context) {
        console.warn(`⚠️ Entering safe mode for: ${systemName}`);
        
        return {
            success: true,
            response: `System switched to safe mode. Limited functionality available.`,
            safeMode: true,
            system: systemName
        };
    }

    async attemptSystemRecovery(errorType, error, context) {
        console.log(`🔧 Attempting system recovery for: ${errorType}`);
        
        // System-specific recovery strategies
        const recoveryStrategies = {
            'system_failure': async () => {
                // Restart essential services
                await this.restartEssentialServices();
            },
            'memory_overflow': async () => {
                // Clear caches and free memory
                await this.clearCaches();
                global.gc && global.gc();
            },
            'ai_service_failure': async () => {
                // Reset AI service connections
                await this.resetAIConnections();
            }
        };
        
        const strategy = recoveryStrategies[errorType];
        if (strategy) {
            try {
                await strategy();
                console.log(`✅ System recovery completed for: ${errorType}`);
            } catch (recoveryError) {
                console.error(`❌ System recovery failed for ${errorType}:`, recoveryError);
            }
        }
    }

    async restartEssentialServices() {
        // Implementation for restarting essential services
        console.log('🔄 Restarting essential services...');
    }

    async clearCaches() {
        // Clear all system caches
        console.log('🗑️ Clearing system caches...');
    }

    async resetAIConnections() {
        // Reset AI service connections
        console.log('🔌 Resetting AI connections...');
    }

    showUserError(errorType, error, context) {
        const userFriendlyMessages = {
            'ai_service_error': 'AI service is temporarily unavailable. Please try again.',
            'file_operation_error': 'File operation failed. Check file permissions.',
            'network_error': 'Network connection issue. Check your internet connection.',
            'authentication_error': 'Authentication failed. Please check your credentials.'
        };
        
        const message = userFriendlyMessages[errorType] || 'An unexpected error occurred.';
        
        vscode.window.showWarningMessage(message, 'Retry', 'Help').then(selection => {
            if (selection === 'Retry') {
                // Implement retry logic
            } else if (selection === 'Help') {
                this.openHelpDocumentation(errorType);
            }
        });
    }

    showErrorDetails(errorType, error) {
        const details = `
Error Type: ${errorType}
Message: ${error.message || error}
Time: ${new Date().toISOString()}
Stack: ${error.stack || 'Not available'}
        `;
        
        vscode.workspace.openTextDocument({
            content: details,
            language: 'text'
        }).then(doc => {
            vscode.window.showTextDocument(doc);
        });
    }

    openIssueReporter(errorType, error) {
        const issueUrl = `https://github.com/vigthoria/vigthoria-ai/issues/new?template=bug_report.md&title=${encodeURIComponent(`Error: ${errorType}`)}&body=${encodeURIComponent(error.message || error)}`;
        vscode.env.openExternal(vscode.Uri.parse(issueUrl));
    }

    openHelpDocumentation(errorType) {
        // Internal help instead of external broken link
        vscode.window.showInformationMessage(
            `Help for ${errorType}: Please try reloading the window or restarting VS Code. Check the extension logs for more details.`,
            'Reload Window',
            'Open Logs'
        ).then(selection => {
            if (selection === 'Reload Window') {
                vscode.commands.executeCommand('workbench.action.reloadWindow');
            } else if (selection === 'Open Logs') {
                vscode.commands.executeCommand('workbench.action.openExtensionLogs');
            }
        });
    }

    getErrorMetrics() {
        return {
            ...this.errorMetrics,
            errorHistory: Array.from(this.errorHistory.values()).slice(-50), // Last 50 errors
            circuitBreakerStatus: this.getCircuitBreakerStatus()
        };
    }

    getCircuitBreakerStatus() {
        const status = {};
        for (const [name, breaker] of this.circuitBreakers.entries()) {
            status[name] = {
                state: breaker.getState(),
                failures: breaker.getFailureCount(),
                isOpen: breaker.isOpen()
            };
        }
        return status;
    }
}

/**
 * 🔌 CIRCUIT BREAKER IMPLEMENTATION
 * Prevents cascade failures by temporarily disabling failed services
 */
class CircuitBreaker {
    constructor(config) {
        this.maxFailures = config.maxFailures || 5;
        this.resetTimeout = config.resetTimeout || 60000;
        this.failures = 0;
        this.lastFailureTime = null;
        this.state = 'CLOSED'; // CLOSED, OPEN, HALF_OPEN
    }

    recordFailure() {
        this.failures++;
        this.lastFailureTime = Date.now();
        
        if (this.failures >= this.maxFailures) {
            this.state = 'OPEN';
            console.warn(`🔌 Circuit breaker opened after ${this.failures} failures`);
        }
    }

    recordSuccess() {
        this.failures = 0;
        this.state = 'CLOSED';
    }

    isOpen() {
        if (this.state === 'OPEN') {
            // Check if enough time has passed to try again
            if (Date.now() - this.lastFailureTime > this.resetTimeout) {
                this.state = 'HALF_OPEN';
                console.log('🔌 Circuit breaker moved to HALF_OPEN state');
                return false;
            }
            return true;
        }
        return false;
    }

    getState() {
        return this.state;
    }

    getFailureCount() {
        return this.failures;
    }
}

module.exports = { ErrorBoundarySystem, CircuitBreaker };
