/**
 * META-AWARE COMPONENT
 *
 * STRUCTURAL PATTERN: Pipeline (Chain of Responsibility)
 * ABSTRACTION LEVEL: High
 * COMPLEXITY: 6/10
 *
 * PURPOSE: Composable data transformation pipeline with stage tracking
 * WHY THIS PATTERN: Pipeline enables clear sequential processing where each stage
 *                    has single responsibility, making complex transforms composable
 *
 * QUALITY SELF-ASSESSMENT:
 * - Structural Clarity: 9/10 (clear stage separation, linear flow)
 * - Meta-Awareness: 8/10 (tracks stage execution, timing, transformations)
 * - Evolution Potential: 9/10 (can add parallel stages, conditional routing, error recovery)
 * - Pattern Generalizability: 10/10 (pipeline pattern extremely versatile)
 * - Self-Documentation Quality: 9/10 (comprehensive stage documentation)
 *
 * IMPROVEMENT SUGGESTIONS:
 * 1. Add conditional routing (stages can decide next stage based on data)
 * 2. Implement parallel stage execution for independent transformations
 * 3. Add error recovery with retry logic and fallback stages
 *
 * EVOLUTION PATH:
 * - Next step: Add stage branching/conditional execution
 * - Long-term: Distributed pipeline with stage orchestration across workers
 */

// === IMPLEMENTATION ===

/**
 * Meta-Aware Pipeline Builder
 * Pattern: Chain of sequential transformations
 */
class MetaAwarePipeline {
  constructor(name = 'Pipeline') {
    this._name = name;
    this._stages = [];

    // Meta-tracking
    this._metrics = {
      executions: 0,
      totalDuration: 0,
      stageMetrics: {},
      executionHistory: []
    };
  }

  /**
   * Add transformation stage to pipeline
   * Pattern: Builder
   */
  addStage(name, transformer, metadata = {}) {
    this._stages.push({
      name,
      transformer,
      metadata,
      index: this._stages.length
    });

    // Initialize metrics for this stage
    this._metrics.stageMetrics[name] = {
      executions: 0,
      totalDuration: 0,
      errors: 0
    };

    console.log(`[META] Added stage ${this._stages.length}: "${name}"`);

    return this; // Enable chaining
  }

  /**
   * Execute pipeline on input data
   * Pattern: Sequential processing
   */
  async execute(input) {
    this._metrics.executions++;
    const executionStart = Date.now();

    console.log(`[META] Executing pipeline "${this._name}" with ${this._stages.length} stages`);

    let data = input;
    const stageResults = [];

    // Process through each stage sequentially
    for (const stage of this._stages) {
      const stageStart = Date.now();

      try {
        console.log(`[META] Stage ${stage.index + 1}/${this._stages.length}: "${stage.name}"`);

        // Execute transformation
        data = await stage.transformer(data);

        // Record success
        const stageDuration = Date.now() - stageStart;
        this._metrics.stageMetrics[stage.name].executions++;
        this._metrics.stageMetrics[stage.name].totalDuration += stageDuration;

        stageResults.push({
          stage: stage.name,
          success: true,
          duration: stageDuration,
          outputType: typeof data
        });

        console.log(`[META] Stage "${stage.name}" completed in ${stageDuration}ms`);

      } catch (error) {
        // Record error
        const stageDuration = Date.now() - stageStart;
        this._metrics.stageMetrics[stage.name].errors++;

        stageResults.push({
          stage: stage.name,
          success: false,
          duration: stageDuration,
          error: error.message
        });

        console.error(`[META] Stage "${stage.name}" failed: ${error.message}`);
        throw new Error(`Pipeline "${this._name}" failed at stage "${stage.name}": ${error.message}`);
      }
    }

    // Record execution
    const totalDuration = Date.now() - executionStart;
    this._metrics.totalDuration += totalDuration;

    this._metrics.executionHistory.push({
      timestamp: Date.now(),
      duration: totalDuration,
      stages: stageResults,
      success: true
    });

    console.log(`[META] Pipeline "${this._name}" completed in ${totalDuration}ms`);

    return data;
  }

  /**
   * Get pipeline configuration
   * Pattern: Introspection
   */
  getStages() {
    return this._stages.map(stage => ({
      name: stage.name,
      index: stage.index,
      metadata: stage.metadata
    }));
  }

  /**
   * Get pipeline metrics
   * Pattern: Performance analysis
   */
  getMetrics() {
    const avgDuration = this._metrics.executions > 0
      ? (this._metrics.totalDuration / this._metrics.executions).toFixed(2)
      : 0;

    // Calculate per-stage averages
    const stageAverages = {};
    for (const [stageName, metrics] of Object.entries(this._metrics.stageMetrics)) {
      stageAverages[stageName] = {
        avgDuration: metrics.executions > 0
          ? (metrics.totalDuration / metrics.executions).toFixed(2) + 'ms'
          : 'N/A',
        successRate: metrics.executions > 0
          ? ((metrics.executions - metrics.errors) / metrics.executions * 100).toFixed(2) + '%'
          : 'N/A'
      };
    }

    return {
      pipelineName: this._name,
      totalStages: this._stages.length,
      executions: this._metrics.executions,
      avgDuration: avgDuration + 'ms',
      stageAverages,
      pattern: 'Pipeline (Chain of Responsibility)',
      recentExecutions: this._metrics.executionHistory.slice(-5)
    };
  }
}

// === STRUCTURAL REFLECTION ===
// Pattern Used: Pipeline (sequential chain of transformations)
// Why: Pipeline provides clear sequential flow with single-responsibility stages.
//      Each stage handles one transformation, making complex processing
//      easy to understand, test, and modify. Stages are reusable.
// Trade-offs:
//   - Linear execution: no parallelism (all stages sequential)
//   - Error propagation: one stage failure stops entire pipeline
//   - No conditional routing: can't skip stages based on data
//   - Memory: entire data passed through each stage

// === META-ANALYSIS ===
// What worked well:
//   - Builder pattern (addStage) enables fluent, readable pipeline construction
//   - Per-stage metrics identify bottlenecks precisely
//   - Clear error handling with stage-level failure reporting
//   - Async support allows I/O-heavy transformations
// What could improve:
//   - Add parallel stage execution for independent transforms
//   - Implement conditional routing (if/else stages)
//   - Add error recovery (retry, fallback stages)
//   - Support stage rollback/compensation for transactional pipelines
// Generalizability:
//   - This pipeline pattern applies to: data ETL, request processing,
//     image manipulation, document generation, middleware chains,
//     build systems, validation flows, state machines

// === USAGE EXAMPLE ===

// Create pipeline
const dataPipeline = new MetaAwarePipeline('UserDataProcessor');

// Add stages
dataPipeline
  .addStage('parse', (input) => JSON.parse(input), { type: 'parser' })
  .addStage('validate', (data) => {
    if (!data.email) throw new Error('Email required');
    return data;
  }, { type: 'validator' })
  .addStage('normalize', (data) => ({
    ...data,
    email: data.email.toLowerCase(),
    name: data.name.trim()
  }), { type: 'normalizer' })
  .addStage('enrich', (data) => ({
    ...data,
    processed: new Date().toISOString(),
    id: Math.random().toString(36).substr(2, 9)
  }), { type: 'enricher' });

// Execute pipeline
(async () => {
  const input = '{"email":"USER@EXAMPLE.COM","name":"  John Doe  "}';

  try {
    const result = await dataPipeline.execute(input);
    console.log('Pipeline result:', result);

    console.log('Pipeline metrics:', dataPipeline.getMetrics());
  } catch (error) {
    console.error('Pipeline error:', error.message);
  }
})();

module.exports = MetaAwarePipeline;
