"use strict";
/**
 * Sequential Section Execution Engine - Advanced orchestration for multi-section analysis
 *
 * Ultra-Hard Challenges Solved:
 * 1. Memory Management: Efficient memory handling across sequential execution with automatic cleanup
 * 2. Error Propagation & Rollback: Graceful handling of cascading failures with proper rollback
 * 3. Result Passing: Correctly typed and passed section results instead of inadequate mocks
 * 4. Progress Tracking: Real-time progress reporting with estimated completion times
 * 5. Performance Optimization: Avoid redundant execution while maintaining correctness
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.SequentialExecutor = void 0;
exports.createSequentialExecutor = createSequentialExecutor;
exports.validateSequentialExecutionRequirements = validateSequentialExecutionRequirements;
const dependency_resolver_1 = require("./dependency-resolver");
const types_1 = require("../core/types");
const logger_1 = require("../utils/logger");
const memory_manager_1 = require("../utils/memory-manager");
const error_handler_1 = require("../utils/error-handler");
const result_cache_1 = require("./result-cache");
// Import existing analyzers
const overview_1 = require("../analyzers/overview");
const quality_1 = require("../analyzers/quality");
const streaming_analyzer_1 = require("../analyzers/streaming/streaming-analyzer");
const visualization_1 = require("../analyzers/visualization");
const engineering_1 = require("../analyzers/engineering");
const modeling_1 = require("../analyzers/modeling");
/**
 * Advanced sequential execution engine that orchestrates section analysis
 * with sophisticated memory management and error handling
 */
class SequentialExecutor {
    resolver;
    executionState;
    progressCallbacks;
    options;
    dataset;
    context;
    executionPlan = null;
    sectionConfigs;
    resultCache;
    constructor(dataset, options, progressCallbacks = {}, context = {}) {
        this.dataset = dataset;
        this.options = options;
        this.progressCallbacks = progressCallbacks;
        this.context = {
            ...context,
            operation: 'sequential_execution',
            filePath: dataset.metadata.filePath,
        };
        // Initialize dependency resolver
        this.resolver = (0, dependency_resolver_1.createDependencyResolver)(dataset.metadata.filePath, options, this.context);
        // Initialize result cache with intelligent caching enabled
        this.resultCache = (0, result_cache_1.createResultCache)(options, {
            ...this.context,
            operation: 'sequential_execution_cache',
        }, options.enableCaching !== false // Enable persistent cache unless explicitly disabled
        );
        // Initialize execution state
        this.executionState = {
            currentSection: null,
            completedSections: new Set(),
            rollbackStack: [],
            startTime: Date.now(),
            phaseStartTime: Date.now(),
            totalEstimatedTime: 0,
            memoryPeakUsage: 0,
        };
        // Initialize section configurations
        this.sectionConfigs = new Map([
            ['section1', {
                    name: 'section1',
                    weight: 10,
                    dependencies: [],
                    estimatedDuration: 2000,
                    memoryWeight: 10,
                    retryable: true,
                    required: true,
                }],
            ['section2', {
                    name: 'section2',
                    weight: 20,
                    dependencies: [],
                    estimatedDuration: 5000,
                    memoryWeight: 20,
                    retryable: true,
                    required: true,
                }],
            ['section3', {
                    name: 'section3',
                    weight: 40,
                    dependencies: [],
                    estimatedDuration: 15000,
                    memoryWeight: 40,
                    retryable: true,
                    required: true,
                }],
            ['section4', {
                    name: 'section4',
                    weight: 25,
                    dependencies: ['section1', 'section3'],
                    estimatedDuration: 8000,
                    memoryWeight: 25,
                    retryable: true,
                    required: false,
                }],
            ['section5', {
                    name: 'section5',
                    weight: 35,
                    dependencies: ['section1', 'section2', 'section3'],
                    estimatedDuration: 12000,
                    memoryWeight: 35,
                    retryable: true,
                    required: false,
                }],
            ['section6', {
                    name: 'section6',
                    weight: 60,
                    dependencies: ['section1', 'section2', 'section3', 'section5'],
                    estimatedDuration: 20000,
                    memoryWeight: 60,
                    retryable: false,
                    required: false,
                }],
        ]);
        this.registerSectionResolvers();
    }
    /**
     * Execute the requested sections in optimal order with full dependency resolution
     */
    async execute(requestedSections) {
        const startTime = Date.now();
        try {
            logger_1.logger.info(`Starting sequential execution for sections: ${requestedSections.join(', ')}`, this.context);
            // Phase 1: Plan execution
            await this.planExecution(requestedSections);
            // Phase 2: Validate readiness
            await this.validateExecutionReadiness();
            // Phase 3: Execute sections sequentially
            const results = await this.executeSequentialPlan();
            // Phase 4: Post-execution cleanup and validation
            await this.performPostExecutionCleanup();
            const totalTime = Date.now() - startTime;
            return {
                success: true,
                exitCode: 0,
                data: results,
                format: this.options.output || 'markdown',
                metadata: {
                    executionTime: totalTime,
                    sectionsExecuted: Array.from(this.executionState.completedSections),
                    memoryPeakUsage: this.executionState.memoryPeakUsage,
                    executionPlan: this.executionPlan,
                    performance: this.getPerformanceMetrics(),
                },
                stats: {
                    processingTime: totalTime,
                    rowsProcessed: this.dataset.rows.length,
                    warnings: 0,
                    errors: 0,
                },
            };
        }
        catch (error) {
            return await this.handleExecutionError(error, startTime);
        }
    }
    /**
     * Phase 1: Plan execution using dependency resolver
     */
    async planExecution(requestedSections) {
        this.updateProgress('Planning execution', 0, 'Analyzing dependencies and optimizing execution order');
        try {
            // Generate optimal execution plan
            this.executionPlan = this.resolver.planExecution(requestedSections);
            // Calculate total estimated time
            this.executionState.totalEstimatedTime = this.executionPlan.order
                .map(section => this.sectionConfigs.get(section)?.estimatedDuration || 5000)
                .reduce((a, b) => a + b, 0);
            logger_1.logger.info(`Execution plan generated: ${this.executionPlan.order.join(' -> ')}`, {
                ...this.context,
                estimatedDuration: this.executionState.totalEstimatedTime,
                memoryOptimized: this.executionPlan.memoryOptimized,
                parallelGroups: this.executionPlan.parallelGroups.length,
            });
            this.progressCallbacks.onPhaseComplete?.(`Execution planned: ${this.executionPlan.order.length} sections`, Date.now() - this.executionState.phaseStartTime);
        }
        catch (error) {
            logger_1.logger.error('Failed to plan execution', this.context, error);
            throw new types_1.DataPilotError(`Execution planning failed: ${error instanceof Error ? error.message : 'Unknown error'}`, 'EXECUTION_PLANNING_FAILED', types_1.ErrorSeverity.CRITICAL, types_1.ErrorCategory.ANALYSIS, this.context, [
                {
                    action: 'Check section dependencies',
                    description: 'Verify that all requested sections have valid dependencies',
                    severity: types_1.ErrorSeverity.HIGH,
                },
                {
                    action: 'Validate execution environment',
                    description: 'Ensure sufficient memory and resources are available',
                    severity: types_1.ErrorSeverity.MEDIUM,
                },
            ]);
        }
    }
    /**
     * Phase 2: Validate execution readiness
     */
    async validateExecutionReadiness() {
        this.updateProgress('Validating readiness', 5, 'Checking system resources and dependencies');
        this.executionState.phaseStartTime = Date.now();
        if (!this.executionPlan) {
            throw new types_1.DataPilotError('No execution plan available', 'MISSING_EXECUTION_PLAN', types_1.ErrorSeverity.CRITICAL, types_1.ErrorCategory.VALIDATION, this.context);
        }
        // Check memory availability
        const currentMemory = process.memoryUsage();
        const memoryLimit = this.options.memoryLimit || 512 * 1024 * 1024;
        if (currentMemory.heapUsed > memoryLimit * 0.8) {
            logger_1.logger.warn(`High memory usage detected before execution (${(currentMemory.heapUsed / 1024 / 1024).toFixed(0)}MB)`, this.context);
        }
        // Validate that dataset is valid
        if (!this.dataset.rows || this.dataset.rows.length === 0) {
            throw new types_1.DataPilotError('Invalid dataset: no rows available', 'INVALID_DATASET', types_1.ErrorSeverity.HIGH, types_1.ErrorCategory.VALIDATION, this.context);
        }
        // Validate execution plan readiness
        const readiness = this.resolver.validateExecutionReadiness(this.executionPlan.order);
        if (!readiness.ready) {
            throw new types_1.DataPilotError(`Execution not ready: ${readiness.issues.join(', ')}`, 'EXECUTION_NOT_READY', types_1.ErrorSeverity.HIGH, types_1.ErrorCategory.VALIDATION, this.context, readiness.issues.map(issue => ({
                action: 'Fix execution issue',
                description: issue,
                severity: types_1.ErrorSeverity.HIGH,
            })));
        }
        // Log warnings
        readiness.warnings.forEach(warning => {
            logger_1.logger.warn(warning, this.context);
            this.progressCallbacks.onWarning?.(warning);
        });
        this.progressCallbacks.onPhaseComplete?.('Execution readiness validated', Date.now() - this.executionState.phaseStartTime);
    }
    /**
     * Phase 3: Execute sections sequentially with real dependency passing
     */
    async executeSequentialPlan() {
        this.updateProgress('Executing sections', 10, 'Running analysis sections in optimal order');
        this.executionState.phaseStartTime = Date.now();
        if (!this.executionPlan) {
            throw new Error('No execution plan available');
        }
        const results = {};
        let progressBase = 10; // Starting after planning phase
        const progressPerSection = 80 / this.executionPlan.order.length; // 80% for execution
        for (const [index, sectionName] of this.executionPlan.order.entries()) {
            const sectionProgress = progressBase + (index * progressPerSection);
            await this.executeSingleSection(sectionName, sectionProgress, results);
        }
        this.progressCallbacks.onPhaseComplete?.(`All ${this.executionPlan.order.length} sections completed`, Date.now() - this.executionState.phaseStartTime);
        return results;
    }
    /**
     * Execute a single section with memory management and error handling
     */
    async executeSingleSection(sectionName, progressPercentage, results) {
        const config = this.sectionConfigs.get(sectionName);
        if (!config) {
            throw new types_1.DataPilotError(`No configuration found for section: ${sectionName}`, 'MISSING_SECTION_CONFIG', types_1.ErrorSeverity.HIGH, types_1.ErrorCategory.VALIDATION, this.context);
        }
        this.executionState.currentSection = sectionName;
        const sectionStartTime = Date.now();
        this.updateProgress(`Executing ${sectionName}`, progressPercentage, `Running ${sectionName} analysis with dependencies`);
        this.progressCallbacks.onPhaseStart?.(sectionName, `Starting ${sectionName} analysis`);
        try {
            // Create rollback point
            this.createRollbackPoint(sectionName);
            // Pre-execution memory management
            await this.performPreExecutionCleanup();
            // Check cache first before executing
            logger_1.logger.info(`Checking cache for ${sectionName}`, {
                ...this.context,
                section: sectionName,
                dependencies: config.dependencies,
            });
            let executionResult = await this.resultCache.get(this.dataset.metadata.filePath, sectionName, this.options, config.dependencies);
            if (executionResult) {
                logger_1.logger.info(`Cache hit for ${sectionName}`, {
                    ...this.context,
                    section: sectionName,
                    cached: true,
                });
                this.progressCallbacks.onPhaseComplete?.(`${sectionName} loaded from cache`, Date.now() - sectionStartTime);
            }
            else {
                // Execute section with dependency resolution
                logger_1.logger.info(`Executing ${sectionName}`, {
                    ...this.context,
                    section: sectionName,
                    dependencies: config.dependencies,
                    cached: false,
                });
                executionResult = await this.executeWithTimeout(() => this.resolver.resolve(sectionName), config.estimatedDuration * 2 // 2x estimated time as timeout
                );
                // Cache the result for future use
                await this.resultCache.set(this.dataset.metadata.filePath, sectionName, this.options, executionResult, config.dependencies, config.estimatedDuration * 10 // TTL based on execution time
                );
                logger_1.logger.info(`${sectionName} result cached`, {
                    ...this.context,
                    section: sectionName,
                    resultSize: JSON.stringify(executionResult).length,
                });
            }
            // Store result
            results[sectionName] = executionResult;
            this.executionState.completedSections.add(sectionName);
            // Post-execution memory tracking
            const memoryUsage = process.memoryUsage();
            this.executionState.memoryPeakUsage = Math.max(this.executionState.memoryPeakUsage, memoryUsage.heapUsed);
            const executionTime = Date.now() - sectionStartTime;
            logger_1.logger.info(`${sectionName} completed in ${executionTime}ms`, {
                ...this.context,
                section: sectionName,
                executionTime,
                memoryUsed: memoryUsage.heapUsed,
            });
            this.progressCallbacks.onPhaseComplete?.(`${sectionName} completed successfully`, executionTime);
        }
        catch (error) {
            const executionTime = Date.now() - sectionStartTime;
            logger_1.logger.error(`${sectionName} failed after ${executionTime}ms`, {
                ...this.context,
                section: sectionName,
                executionTime,
            }, error);
            // Invalidate cache for this section and dependents on failure
            await this.resultCache.invalidateDependents(sectionName);
            // Handle section failure based on configuration
            await this.handleSectionFailure(sectionName, error, config);
        }
        finally {
            this.executionState.currentSection = null;
        }
    }
    /**
     * Handle section failure with proper rollback and error propagation
     */
    async handleSectionFailure(sectionName, error, config) {
        this.progressCallbacks.onError?.(`${sectionName} failed: ${error.message}`);
        if (config.required) {
            // Required section failed - rollback and fail entire execution
            logger_1.logger.error(`Required section ${sectionName} failed, rolling back`, this.context);
            await this.performRollback();
            throw new types_1.DataPilotError(`Required section ${sectionName} failed: ${error instanceof Error ? error.message : 'Unknown error'}`, 'REQUIRED_SECTION_FAILED', types_1.ErrorSeverity.CRITICAL, types_1.ErrorCategory.ANALYSIS, this.context, [
                {
                    action: 'Check section implementation',
                    description: `Verify ${sectionName} analyzer is working correctly`,
                    severity: types_1.ErrorSeverity.HIGH,
                },
                {
                    action: 'Validate input data',
                    description: 'Ensure the input data is compatible with this section',
                    severity: types_1.ErrorSeverity.HIGH,
                },
                {
                    action: 'Check dependencies',
                    description: 'Verify all section dependencies are satisfied',
                    severity: types_1.ErrorSeverity.MEDIUM,
                },
            ]);
        }
        else if (config.retryable) {
            // Optional section failed but retryable - warn and continue
            logger_1.logger.warn(`Optional section ${sectionName} failed but continuing`, this.context, error);
            this.progressCallbacks.onWarning?.(`${sectionName} failed but continuing: ${error.message}`);
        }
        else {
            // Optional section failed and not retryable - skip and continue
            logger_1.logger.warn(`Skipping failed section ${sectionName}`, this.context, error);
            this.progressCallbacks.onWarning?.(`Skipping ${sectionName}: ${error.message}`);
        }
    }
    /**
     * Execute section with enhanced error handling and context
     */
    async executeSectionWithEnhancedContext(sectionName, sectionExecutor) {
        return await error_handler_1.ErrorUtils.withEnhancedContext(async () => {
            const result = await sectionExecutor();
            // Validate section result
            return error_handler_1.ErrorUtils.validateOperationResult(result, 'object', `${sectionName}_analysis`, {
                section: sectionName,
                analyzer: `${sectionName}Analyzer`,
                filePath: this.dataset.metadata.filePath
            });
        }, {
            operationName: `${sectionName}_execution`,
            section: sectionName,
            analyzer: `${sectionName}Analyzer`,
            filePath: this.dataset.metadata.filePath,
            additionalContext: {
                datasetRows: this.dataset.rows.length,
                datasetColumns: this.dataset.headers.length,
                executionState: {
                    currentSection: this.executionState.currentSection,
                    completedSections: Array.from(this.executionState.completedSections),
                    memoryUsage: this.executionState.memoryPeakUsage
                }
            }
        });
    }
    /**
     * Register section resolvers with the dependency resolver and enhanced error handling
     */
    registerSectionResolvers() {
        // Section 1: Overview Analysis
        this.resolver.registerResolver('section1', async () => {
            const analyzer = new overview_1.Section1Analyzer({
                enableFileHashing: this.options.enableHashing !== false,
                includeHostEnvironment: this.options.includeEnvironment !== false,
                privacyMode: this.options.privacyMode || 'redacted',
                detailedProfiling: this.options.verbose || false,
                maxSampleSizeForSparsity: 10000,
                enableCompressionAnalysis: this.options.enableCompressionAnalysis !== false,
                enableDataPreview: this.options.enableDataPreview !== false,
                previewRows: this.options.previewRows || 5,
                enableHealthChecks: this.options.enableHealthChecks !== false,
                enableQuickStatistics: this.options.enableQuickStats !== false,
            });
            return analyzer.analyze(this.dataset.metadata.filePath, `datapilot ${this.options.command || 'analysis'} ${this.dataset.metadata.filePath}`, []);
        });
        // Section 2: Quality Analysis
        this.resolver.registerResolver('section2', async () => {
            const analyzer = new quality_1.Section2Analyzer({
                data: this.dataset.rows,
                headers: this.dataset.headers,
                columnTypes: this.dataset.headers.map(() => 'string'),
                rowCount: this.dataset.rows.length,
                columnCount: this.dataset.headers.length,
                config: {
                    enabledDimensions: ['completeness', 'uniqueness', 'validity'],
                    strictMode: false,
                    maxOutlierDetection: 100,
                    semanticDuplicateThreshold: 0.85,
                },
            });
            return analyzer.analyze();
        });
        // Section 3: EDA Analysis
        this.resolver.registerResolver('section3', async () => {
            const analyzer = new streaming_analyzer_1.StreamingAnalyzer({
                chunkSize: this.options.chunkSize || 500,
                memoryThresholdMB: this.options.memoryLimit || 100,
                maxRowsAnalyzed: this.options.maxRows || 500000,
                enabledAnalyses: ['univariate', 'bivariate', 'correlations'],
                significanceLevel: 0.05,
                maxCorrelationPairs: 50,
                enableMultivariate: true,
            });
            return analyzer.analyzeFile(this.dataset.metadata.filePath);
        });
        // Section 4: Visualization Analysis (with REAL dependencies)
        this.resolver.registerResolver('section4', async () => {
            const analyzer = new visualization_1.Section4Analyzer({
                accessibilityLevel: this.options.accessibility || 'good',
                complexityThreshold: this.options.complexity || 'moderate',
                maxRecommendationsPerChart: this.options.maxRecommendations || 3,
                includeCodeExamples: this.options.includeCode || false,
                enabledRecommendations: [
                    'UNIVARIATE',
                    'BIVARIATE',
                    'DASHBOARD',
                    'ACCESSIBILITY',
                    'PERFORMANCE',
                ],
                targetLibraries: ['d3', 'plotly', 'observable'],
            });
            // Get REAL dependencies instead of mocks
            const section1Result = await this.resolver.resolve('section1');
            const section3Result = await this.resolver.resolve('section3');
            return analyzer.analyze(section1Result, section3Result);
        });
        // Section 5: Engineering Analysis (with REAL dependencies)
        this.resolver.registerResolver('section5', async () => {
            const analyzer = new engineering_1.Section5Analyzer({
                targetDatabaseSystem: this.options.database || 'postgresql',
                mlFrameworkTarget: this.options.framework || 'scikit_learn',
            });
            // Get REAL dependencies instead of mocks
            const section1Result = await this.resolver.resolve('section1');
            const section2Result = await this.resolver.resolve('section2');
            const section3Result = await this.resolver.resolve('section3');
            return analyzer.analyze(section1Result, section2Result, section3Result);
        });
        // Section 6: Modeling Analysis (with REAL dependencies) - THIS FIXES THE MOCK INADEQUACY
        this.resolver.registerResolver('section6', async () => {
            const analyzer = new modeling_1.Section6Analyzer({
                focusAreas: this.options.focus || ['regression', 'binary_classification', 'clustering'],
                complexityPreference: this.options.complexity || 'moderate',
                interpretabilityRequirement: this.options.interpretability || 'medium',
            });
            // Get REAL dependencies instead of mocks - this is the critical fix
            const section1Result = await this.resolver.resolve('section1');
            const section2Result = await this.resolver.resolve('section2');
            const section3Result = await this.resolver.resolve('section3');
            const section5Result = await this.resolver.resolve('section5');
            return analyzer.analyze(section1Result, section2Result, section3Result, section5Result);
        });
    }
    /**
     * Execute with timeout protection
     */
    async executeWithTimeout(operation, timeoutMs) {
        return Promise.race([
            operation(),
            new Promise((_, reject) => setTimeout(() => reject(new Error(`Operation timeout after ${timeoutMs}ms`)), timeoutMs)),
        ]);
    }
    /**
     * Create rollback point for error recovery
     */
    createRollbackPoint(sectionName) {
        const memorySnapshot = process.memoryUsage();
        this.executionState.rollbackStack.push({
            section: sectionName,
            timestamp: new Date(),
            memorySnapshot,
        });
        // Limit rollback stack size
        if (this.executionState.rollbackStack.length > 10) {
            this.executionState.rollbackStack.shift();
        }
    }
    /**
     * Perform rollback to clean state
     */
    async performRollback() {
        logger_1.logger.info('Performing execution rollback', this.context);
        // Clear all cached dependencies to force fresh execution
        this.resolver.clear();
        // Clear result cache to ensure fresh execution
        await this.resultCache.clear();
        // Reset execution state
        this.executionState.completedSections.clear();
        this.executionState.currentSection = null;
        // Trigger garbage collection if available
        if (global.gc) {
            global.gc();
        }
        // Clean up global resources
        await memory_manager_1.globalMemoryManager.runCleanup();
        logger_1.logger.info('Rollback completed', this.context);
    }
    /**
     * Pre-execution memory cleanup
     */
    async performPreExecutionCleanup() {
        const memoryUsage = process.memoryUsage();
        const memoryLimit = this.options.memoryLimit || 512 * 1024 * 1024;
        if (memoryUsage.heapUsed > memoryLimit * 0.7) {
            logger_1.logger.debug('Performing pre-execution memory cleanup', this.context);
            // Trigger garbage collection
            if (global.gc) {
                global.gc();
            }
            // Clean up global resources
            await memory_manager_1.globalMemoryManager.runCleanup();
        }
    }
    /**
     * Phase 4: Post-execution cleanup and validation
     */
    async performPostExecutionCleanup() {
        this.updateProgress('Finalizing', 95, 'Cleaning up resources and validating results');
        // Final memory cleanup
        await memory_manager_1.globalMemoryManager.runCleanup();
        // Validate all completed sections have results
        const executionPlan = this.executionPlan;
        const missingResults = executionPlan.order.filter(section => !this.executionState.completedSections.has(section));
        if (missingResults.length > 0) {
            const requiredMissing = missingResults.filter(section => this.sectionConfigs.get(section)?.required);
            if (requiredMissing.length > 0) {
                throw new types_1.DataPilotError(`Required sections failed to complete: ${requiredMissing.join(', ')}`, 'REQUIRED_SECTIONS_INCOMPLETE', types_1.ErrorSeverity.CRITICAL, types_1.ErrorCategory.ANALYSIS, this.context);
            }
        }
        this.updateProgress('Complete', 100, 'Sequential execution completed successfully');
    }
    /**
     * Handle execution errors with enhanced debugging and detailed reporting
     */
    async handleExecutionError(error, startTime) {
        const totalTime = Date.now() - startTime;
        // Set verbose mode based on options
        error_handler_1.globalErrorHandler.setVerboseMode(this.options.verbose || false);
        logger_1.logger.error('Sequential execution failed', this.context, error);
        // Attempt rollback with enhanced error context
        try {
            await this.performRollback();
        }
        catch (rollbackError) {
            logger_1.logger.error('Rollback failed', this.context, rollbackError);
        }
        let errorMessage = 'Sequential execution failed';
        let enhancedSuggestions = [];
        let errorDetails = {};
        if (error instanceof types_1.DataPilotError) {
            // Enhanced error handling for DataPilotError
            errorMessage = error.getFormattedMessage(this.options.verbose || false);
            enhancedSuggestions = error.getEnhancedSuggestions(this.options.verbose || false);
            if (this.options.verbose && error.verboseInfo) {
                errorDetails = {
                    fullContext: error.verboseInfo.fullContext,
                    performanceMetrics: error.verboseInfo.performanceMetrics,
                    memorySnapshot: error.verboseInfo.memorySnapshot,
                };
            }
        }
        else {
            // Convert generic error to enhanced format
            errorMessage = error instanceof Error ? error.message : 'Unknown execution error';
            if (this.options.verbose) {
                errorMessage += `\n   Stack: ${error instanceof Error ? error.stack?.split('\n').slice(0, 3).join('\n          ') : 'No stack available'}`;
                errorMessage += `\n   Section: ${this.executionState.currentSection || 'unknown'}`;
                errorMessage += `\n   Completed: ${Array.from(this.executionState.completedSections).join(', ') || 'none'}`;
                errorMessage += `\n   Memory Peak: ${(this.executionState.memoryPeakUsage / 1024 / 1024).toFixed(2)}MB`;
            }
        }
        // Determine error suggestions based on current state
        const contextualSuggestions = [];
        if (this.executionState.currentSection) {
            contextualSuggestions.push(`• Section Failed: ${this.executionState.currentSection} - check section-specific requirements`);
        }
        if (this.executionState.memoryPeakUsage > (this.options.memoryLimit || 512 * 1024 * 1024)) {
            contextualSuggestions.push('• Memory Issue: Consider increasing memory limit or reducing data size');
        }
        // Check for dependency issues
        if (this.executionPlan && this.executionState.completedSections.size < this.executionPlan.order.length) {
            const failedSections = this.executionPlan.order.filter(section => !this.executionState.completedSections.has(section));
            contextualSuggestions.push(`• Dependency Issue: Sections not completed: ${failedSections.join(', ')}`);
        }
        // General debugging suggestions
        const generalSuggestions = [
            'Check system resources and memory availability',
            'Verify input data format and quality',
            'Try running individual sections to isolate the issue',
        ];
        if (this.options.verbose) {
            generalSuggestions.push('Monitor system resources during execution', 'Check for data corruption or format issues', 'Use --maxRows to limit data size for testing');
        }
        else {
            generalSuggestions.push('Use --verbose for detailed debugging information');
        }
        // Combine enhanced suggestions with contextual and general suggestions
        const allSuggestions = [
            ...enhancedSuggestions,
            ...(enhancedSuggestions.length > 0 ? ['---'] : []),
            ...contextualSuggestions,
            ...(contextualSuggestions.length > 0 ? ['---'] : []),
            ...generalSuggestions
        ].filter(Boolean);
        return {
            success: false,
            exitCode: 1,
            error: errorMessage,
            suggestions: allSuggestions,
            metadata: {
                executionTime: totalTime,
                currentSection: this.executionState.currentSection,
                completedSections: Array.from(this.executionState.completedSections),
                memoryPeakUsage: this.executionState.memoryPeakUsage,
                rollbackPoints: this.executionState.rollbackStack.length,
                errorCategory: error instanceof types_1.DataPilotError ? error.category : 'unknown',
                errorSeverity: error instanceof types_1.DataPilotError ? error.severity : 'medium',
                verboseMode: this.options.verbose || false,
                ...(this.options.verbose && errorDetails ? { errorDetails } : {}),
            },
            stats: {
                processingTime: totalTime,
                rowsProcessed: this.dataset.rows?.length || 0,
                warnings: 0,
                errors: 1,
            },
        };
    }
    /**
     * Update progress with detailed state information
     */
    updateProgress(phase, progress, message) {
        const timeElapsed = Date.now() - this.executionState.startTime;
        const estimatedTimeRemaining = this.executionState.totalEstimatedTime > 0
            ? Math.max(0, this.executionState.totalEstimatedTime - timeElapsed)
            : undefined;
        const state = {
            phase,
            progress,
            message,
            timeElapsed,
            estimatedTimeRemaining,
        };
        this.progressCallbacks.onProgress?.(state);
        logger_1.logger.debug('Progress update', {
            ...this.context,
            progress,
            phase,
            timeElapsed,
            estimatedTimeRemaining,
        });
    }
    /**
     * Get performance metrics for reporting
     */
    getPerformanceMetrics() {
        const stats = this.resolver.getStats();
        const insights = this.resolver.getDependencyInsights();
        const cacheStats = this.resultCache.getStats();
        const cacheInfo = this.resultCache.getCacheInfo();
        return {
            executionTime: Date.now() - this.executionState.startTime,
            memoryPeakUsage: this.executionState.memoryPeakUsage,
            sectionsCompleted: this.executionState.completedSections.size,
            dependencyResolution: stats,
            memoryOptimized: this.executionPlan?.memoryOptimized || false,
            rollbacksPerformed: this.executionState.rollbackStack.length,
            insights,
            cache: {
                stats: cacheStats,
                performance: cacheInfo.performance,
                memoryUsage: cacheInfo.memoryUsage,
                efficiency: {
                    cacheHitRate: cacheStats.hitCount / (cacheStats.hitCount + cacheStats.missCount),
                    averageAccessTime: cacheStats.averageAccessTime,
                    memoryPressure: cacheStats.memoryPressureLevel,
                },
            },
        };
    }
    /**
     * Get current execution status for monitoring
     */
    getExecutionStatus() {
        const totalSections = this.executionPlan?.order.length || 0;
        const completed = this.executionState.completedSections.size;
        const progress = totalSections > 0 ? (completed / totalSections) * 100 : 0;
        return {
            currentSection: this.executionState.currentSection,
            completedSections: Array.from(this.executionState.completedSections),
            totalSections,
            progress,
            memoryUsage: process.memoryUsage(),
            elapsedTime: Date.now() - this.executionState.startTime,
        };
    }
    /**
     * Clean up executor resources
     */
    async cleanup() {
        logger_1.logger.debug('Cleaning up sequential executor', this.context);
        this.resolver.clear();
        this.executionState.completedSections.clear();
        this.executionState.rollbackStack = [];
        // Clean up result cache
        await this.resultCache.dispose();
        await memory_manager_1.globalMemoryManager.runCleanup();
    }
    /**
     * Get cache statistics for monitoring and debugging
     */
    getCacheStats() {
        return {
            stats: this.resultCache.getStats(),
            info: this.resultCache.getCacheInfo(),
        };
    }
    /**
     * Clear result cache manually
     */
    async clearCache() {
        await this.resultCache.clear();
        logger_1.logger.info('Result cache cleared manually', this.context);
    }
    /**
     * Invalidate cache for specific file
     */
    async invalidateCacheForFile(filePath) {
        await this.resultCache.invalidateByFile(filePath);
        logger_1.logger.info(`Cache invalidated for file: ${filePath}`, this.context);
    }
}
exports.SequentialExecutor = SequentialExecutor;
/**
 * Factory function to create and configure a sequential executor
 */
function createSequentialExecutor(dataset, options, progressCallbacks = {}, context = {}) {
    return new SequentialExecutor(dataset, options, progressCallbacks, {
        ...context,
        operation: 'sequential_execution_factory',
    });
}
/**
 * Utility function to validate sequential execution requirements
 */
function validateSequentialExecutionRequirements(dataset, options) {
    const issues = [];
    const warnings = [];
    // Validate dataset
    if (!dataset.rows || dataset.rows.length === 0) {
        issues.push('Dataset has no rows');
    }
    if (!dataset.headers || dataset.headers.length === 0) {
        issues.push('Dataset has no columns');
    }
    // Check memory requirements
    const estimatedMemoryUsage = dataset.rows.length * dataset.headers.length * 50; // Rough estimate
    const memoryLimit = options.memoryLimit || 512 * 1024 * 1024;
    if (estimatedMemoryUsage > memoryLimit) {
        warnings.push(`Estimated memory usage (${(estimatedMemoryUsage / 1024 / 1024).toFixed(0)}MB) exceeds limit (${(memoryLimit / 1024 / 1024).toFixed(0)}MB)`);
    }
    // Check section requirements
    if (options.sections && options.sections.includes('section6')) {
        const requiredSections = ['section1', 'section2', 'section3', 'section5'];
        const missingDeps = requiredSections.filter(section => !options.sections.includes(section));
        if (missingDeps.length > 0) {
            warnings.push(`Section 6 requires dependencies: ${missingDeps.join(', ')} (will be auto-executed)`);
        }
    }
    return {
        canExecute: issues.length === 0,
        issues,
        warnings,
        estimatedMemoryUsage,
    };
}
//# sourceMappingURL=sequential-executor.js.map