/**
 * ValidatorCore.js
 *
 * Orchestrateur principal du Pipeline Validator
 * Coordonne l'exécution du pipeline, l'échantillonnage et l'évaluation
 */

const { logSh } = require('../ErrorReporting');
const { tracer } = require('../trace');
const { PipelineExecutor } = require('../pipeline/PipelineExecutor');
const { SamplingEngine } = require('./SamplingEngine');
const { CriteriaEvaluator } = require('./CriteriaEvaluator');
const { v4: uuidv4 } = require('uuid');
const fs = require('fs').promises;
const path = require('path');

/**
 * Presets de validation configurables
 */
const VALIDATION_PRESETS = {
  'ultra-rapid': {
    name: 'Ultra-rapide',
    description: 'Validation minimaliste (v1.0 + v2.0, 2 critères, 3 échantillons)',
    versions: ['v1.0', 'v2.0'],
    criteria: ['qualite', 'naturalite'],
    maxSamples: 3,
    estimatedCost: 0.05,
    estimatedDuration: '30s'
  },
  'economical': {
    name: 'Économique',
    description: 'Validation légère (v1.0 + v2.0, 3 critères, 5 échantillons)',
    versions: ['v1.0', 'v2.0'],
    criteria: ['qualite', 'naturalite', 'seo'],
    maxSamples: 5,
    estimatedCost: 0.12,
    estimatedDuration: '1min'
  },
  'standard': {
    name: 'Standard',
    description: 'Validation équilibrée (3 versions, tous critères, 5 échantillons)',
    versions: ['v1.0', 'v1.2', 'v2.0'],
    criteria: ['qualite', 'verbosite', 'seo', 'repetitions', 'naturalite'],
    maxSamples: 5,
    estimatedCost: 0.30,
    estimatedDuration: '2min'
  },
  'complete': {
    name: 'Complet',
    description: 'Validation exhaustive (toutes versions, tous critères, tous échantillons)',
    versions: null, // null = toutes les versions
    criteria: ['qualite', 'verbosite', 'seo', 'repetitions', 'naturalite'],
    maxSamples: null, // null = tous les échantillons
    estimatedCost: 1.00,
    estimatedDuration: '5min'
  }
};

/**
 * Classe ValidatorCore
 */
class ValidatorCore {
  constructor(options = {}) {
    this.validationId = null;
    this.validationDir = null;
    this.executor = new PipelineExecutor();
    this.samplingEngine = new SamplingEngine();
    this.criteriaEvaluator = new CriteriaEvaluator();
    this.csvData = null;
    this.status = 'idle';
    this.progress = {
      phase: null,
      message: '',
      percentage: 0
    };
    this.validationConfig = null; // ✅ NOUVEAU: Config validation active

    // ✅ PHASE 3: WebSocket callback pour broadcast temps réel
    this.broadcastCallback = options.broadcastCallback || null;
  }

  /**
   * ✅ NOUVEAU: Obtient les presets disponibles
   */
  static getPresets() {
    return VALIDATION_PRESETS;
  }

  /**
   * ✅ NOUVEAU: Applique un preset ou une config custom
   */
  applyConfig(config) {
    // Si config est un string, utiliser le preset correspondant
    if (typeof config === 'string') {
      if (!VALIDATION_PRESETS[config]) {
        throw new Error(`Preset inconnu: ${config}`);
      }
      this.validationConfig = { preset: config, ...VALIDATION_PRESETS[config] };
    } else if (config && typeof config === 'object') {
      // Config custom
      this.validationConfig = {
        preset: 'custom',
        name: config.name || 'Custom',
        description: config.description || 'Configuration personnalisée',
        versions: config.versions || null,
        criteria: config.criteria || ['qualite', 'verbosite', 'seo', 'repetitions', 'naturalite'],
        maxSamples: config.maxSamples || null
      };
    } else {
      // Par défaut: mode complet
      this.validationConfig = { preset: 'complete', ...VALIDATION_PRESETS.complete };
    }

    logSh(`⚙️ Configuration validation: ${this.validationConfig.name}`, 'INFO');
    logSh(`   Versions: ${this.validationConfig.versions ? this.validationConfig.versions.join(', ') : 'toutes'}`, 'DEBUG');
    logSh(`   Critères: ${this.validationConfig.criteria.join(', ')}`, 'DEBUG');
    logSh(`   Max échantillons: ${this.validationConfig.maxSamples || 'tous'}`, 'DEBUG');
  }

  /**
   * Exécute une validation complète
   * @param {Object|String} config - Configuration validation (preset name ou config object)
   * @param {Object} pipelineConfig - Configuration pipeline
   * @param {number} rowNumber - Numéro de ligne Google Sheets
   * @returns {Object} - Résultats validation
   */
  async runValidation(config, pipelineConfig, rowNumber) {
    return tracer.run('ValidatorCore.runValidation', async () => {
      try {
        this.status = 'running';
        this.validationId = uuidv4();

        // ✅ NOUVEAU: Appliquer configuration
        this.applyConfig(config);

        logSh(`🚀 Démarrage validation: ${this.validationId}`, 'INFO');
        logSh(`   Pipeline: ${pipelineConfig.name} | Row: ${rowNumber}`, 'INFO');
        logSh(`   Mode: ${this.validationConfig.name}`, 'INFO');

        // ========================================
        // PHASE 1: SETUP
        // ========================================
        this.updateProgress('setup', 'Création structure dossiers...', 5);

        await this.setupValidationStructure();

        // ========================================
        // PHASE 2: EXÉCUTION PIPELINE
        // ========================================
        this.updateProgress('pipeline', 'Exécution pipeline avec sauvegarde versions...', 10);

        const pipelineResult = await this.runPipeline(pipelineConfig, rowNumber);

        if (!pipelineResult.success) {
          throw new Error('Échec exécution pipeline');
        }

        this.updateProgress('pipeline', 'Pipeline terminé avec succès', 40);

        // ========================================
        // PHASE 3: ÉCHANTILLONNAGE
        // ========================================
        this.updateProgress('sampling', 'Extraction échantillons représentatifs...', 50);

        const samplesResult = await this.runSampling(pipelineResult.versionPaths);

        this.updateProgress('sampling', `Échantillonnage terminé: ${samplesResult.summary.totalSamples} échantillons`, 60);

        // ========================================
        // PHASE 4: ÉVALUATION LLM (✅ NOUVEAU)
        // ========================================
        this.updateProgress('evaluation', 'Évaluation LLM des échantillons...', 65);

        const evaluationsResult = await this.runEvaluations(samplesResult.samples, this.csvData);

        this.updateProgress('evaluation', `Évaluations terminées: ${Object.keys(evaluationsResult).length} échantillons évalués`, 85);

        // ========================================
        // PHASE 5: SAUVEGARDE CONFIGURATION ET RÉSULTATS
        // ========================================
        this.updateProgress('saving', 'Sauvegarde configuration et métadonnées...', 88);

        await this.saveConfiguration(pipelineConfig, rowNumber, pipelineResult);
        await this.saveSamplesData(samplesResult);
        await this.saveEvaluationsData(evaluationsResult);

        // ========================================
        // PHASE 6: GÉNÉRATION RAPPORT
        // ========================================
        this.updateProgress('report', 'Génération rapport validation...', 95);

        const report = await this.generateReport(pipelineResult, samplesResult, evaluationsResult);

        this.updateProgress('completed', 'Validation terminée avec succès', 100);
        this.status = 'completed';

        logSh(`✅ Validation ${this.validationId} terminée avec succès`, 'INFO');

        return {
          success: true,
          validationId: this.validationId,
          validationDir: this.validationDir,
          report,
          versionPaths: pipelineResult.versionPaths,
          samples: samplesResult
        };

      } catch (error) {
        this.status = 'error';
        this.updateProgress('error', `Erreur: ${error.message}`, 0);

        logSh(`❌ Validation ${this.validationId} échouée: ${error.message}`, 'ERROR');

        return {
          success: false,
          validationId: this.validationId,
          error: error.message,
          status: this.status
        };
      }
    }, { validationId: this.validationId });
  }

  /**
   * Crée la structure de dossiers pour la validation
   */
  async setupValidationStructure() {
    this.validationDir = path.join(process.cwd(), 'validations', this.validationId);

    const dirs = [
      this.validationDir,
      path.join(this.validationDir, 'versions'),
      path.join(this.validationDir, 'samples'),
      path.join(this.validationDir, 'results')
    ];

    for (const dir of dirs) {
      await fs.mkdir(dir, { recursive: true });
    }

    logSh(`📁 Structure validation créée: ${this.validationDir}`, 'DEBUG');
  }

  /**
   * Exécute le pipeline avec sauvegarde toutes versions
   */
  async runPipeline(pipelineConfig, rowNumber) {
    logSh(`▶ Exécution pipeline: ${pipelineConfig.name}`, 'INFO');

    const versionsDir = path.join(this.validationDir, 'versions');

    const result = await this.executor.execute(pipelineConfig, rowNumber, {
      saveAllVersions: true,
      outputDir: versionsDir,
      stopOnError: true
    });

    // ✅ Stocker csvData pour contexte évaluations
    this.csvData = this.executor.csvData;

    logSh(`✓ Pipeline exécuté: ${result.versionPaths.length} versions sauvegardées`, 'INFO');

    return result;
  }

  /**
   * Exécute l'échantillonnage
   * ✅ MODIFIÉ: Filtre versions et limite échantillons selon config
   */
  async runSampling(versionPaths) {
    logSh(`▶ Échantillonnage: ${versionPaths.length} versions`, 'INFO');

    // ✅ Filtrer versions si config spécifie une liste
    let filteredPaths = versionPaths;
    if (this.validationConfig.versions) {
      filteredPaths = versionPaths.filter(vp => {
        const versionName = path.basename(vp, '.json');
        return this.validationConfig.versions.includes(versionName);
      });
      logSh(`   Versions filtrées: ${filteredPaths.map(vp => path.basename(vp, '.json')).join(', ')}`, 'DEBUG');
    }

    const samplesResult = await this.samplingEngine.extractSamples(filteredPaths);

    // ✅ Limiter nombre échantillons si config le spécifie
    if (this.validationConfig.maxSamples && this.validationConfig.maxSamples < Object.keys(samplesResult.samples).length) {
      const allTags = Object.keys(samplesResult.samples);
      const selectedTags = allTags.slice(0, this.validationConfig.maxSamples);

      const limitedSamples = {};
      selectedTags.forEach(tag => {
        limitedSamples[tag] = samplesResult.samples[tag];
      });

      samplesResult.samples = limitedSamples;
      samplesResult.summary.totalSamples = selectedTags.length;

      logSh(`   Échantillons limités à ${this.validationConfig.maxSamples}`, 'DEBUG');
    }

    // Sauvegarder les échantillons
    const samplesPath = path.join(this.validationDir, 'samples', 'all-samples.json');
    await this.samplingEngine.saveSamples(samplesResult, samplesPath);

    logSh(`✓ Échantillons extraits et sauvegardés`, 'INFO');

    return samplesResult;
  }

  /**
   * ✅ MODIFIÉ: Exécute les évaluations LLM avec filtrage critères
   */
  async runEvaluations(samples, csvData) {
    logSh(`▶ Évaluation LLM: ${Object.keys(samples).length} échantillons`, 'INFO');
    logSh(`   Critères actifs: ${this.validationConfig.criteria.join(', ')}`, 'DEBUG');

    // Préparer contexte pour évaluations
    const context = {
      mc0: csvData?.mc0 || '',
      t0: csvData?.t0 || '',
      personality: csvData?.personality || {}
    };

    // ✅ Passer la liste des critères à évaluer
    const evaluations = await this.criteriaEvaluator.evaluateBatch(
      samples,
      context,
      3, // maxConcurrent
      this.validationConfig.criteria // ✅ NOUVEAU: critères filtrés
    );

    // Calculer scores agrégés
    const aggregated = this.criteriaEvaluator.aggregateScores(evaluations);

    logSh(`✓ Évaluations terminées: ${Object.keys(evaluations).length} échantillons`, 'INFO');
    logSh(`   Score global moyen: ${aggregated.overall.avgScore}/10`, 'INFO');

    return {
      evaluations,
      aggregated
    };
  }

  /**
   * Sauvegarde la configuration utilisée
   */
  async saveConfiguration(pipelineConfig, rowNumber, pipelineResult) {
    const configPath = path.join(this.validationDir, 'config.json');

    const configData = {
      validationId: this.validationId,
      timestamp: new Date().toISOString(),
      pipeline: pipelineConfig,
      rowNumber,
      personality: pipelineResult.metadata.personality,
      executionLog: pipelineResult.executionLog
    };

    await fs.writeFile(configPath, JSON.stringify(configData, null, 2), 'utf8');

    logSh(`💾 Configuration sauvegardée: ${configPath}`, 'DEBUG');
  }

  /**
   * Sauvegarde les données d'échantillons
   */
  async saveSamplesData(samplesResult) {
    const samplesPath = path.join(this.validationDir, 'samples', 'summary.json');

    await fs.writeFile(samplesPath, JSON.stringify(samplesResult.summary, null, 2), 'utf8');

    logSh(`💾 Résumé échantillons sauvegardé: ${samplesPath}`, 'DEBUG');
  }

  /**
   * ✅ NOUVEAU: Sauvegarde les données d'évaluations
   */
  async saveEvaluationsData(evaluationsResult) {
    const evaluationsPath = path.join(this.validationDir, 'results', 'evaluations.json');

    await fs.writeFile(evaluationsPath, JSON.stringify(evaluationsResult, null, 2), 'utf8');

    logSh(`💾 Évaluations sauvegardées: ${evaluationsPath}`, 'DEBUG');
  }

  /**
   * ✅ MODIFIÉ: Génère le rapport de validation (avec évaluations LLM)
   */
  async generateReport(pipelineResult, samplesResult, evaluationsResult = null) {
    const reportPath = path.join(this.validationDir, 'report.json');

    const report = {
      validationId: this.validationId,
      timestamp: new Date().toISOString(),
      status: 'completed',
      pipeline: {
        name: pipelineResult.metadata.pipelineName,
        totalSteps: pipelineResult.metadata.totalSteps,
        successfulSteps: pipelineResult.metadata.successfulSteps,
        totalDuration: pipelineResult.metadata.totalDuration
      },
      versions: {
        count: pipelineResult.versionPaths.length,
        paths: pipelineResult.versionPaths
      },
      samples: {
        total: samplesResult.summary.totalSamples,
        titles: samplesResult.summary.titles,
        content: samplesResult.summary.content,
        faqs: samplesResult.summary.faqs
      },
      evaluations: evaluationsResult ? {
        totalEvaluations: evaluationsResult.aggregated.overall.totalEvaluations,
        overallScore: evaluationsResult.aggregated.overall.avgScore,
        byVersion: evaluationsResult.aggregated.byVersion,
        byCriteria: evaluationsResult.aggregated.byCriteria,
        details: `Voir ${path.join('results', 'evaluations.json')} pour détails complets`
      } : null
    };

    await fs.writeFile(reportPath, JSON.stringify(report, null, 2), 'utf8');

    logSh(`📊 Rapport validation généré: ${reportPath}`, 'INFO');

    if (evaluationsResult) {
      logSh(`   🎯 Score global: ${evaluationsResult.aggregated.overall.avgScore}/10`, 'INFO');
    }

    return report;
  }

  /**
   * Met à jour le statut de progression
   * ✅ PHASE 3: Avec broadcast WebSocket
   */
  updateProgress(phase, message, percentage) {
    this.progress = {
      phase,
      message,
      percentage
    };

    logSh(`📈 [${percentage}%] ${phase}: ${message}`, 'INFO');

    // ✅ PHASE 3: Broadcast via WebSocket si disponible
    if (this.broadcastCallback) {
      try {
        this.broadcastCallback({
          type: 'validation_progress',
          validationId: this.validationId,
          status: this.status,
          progress: {
            phase,
            message,
            percentage
          },
          timestamp: new Date().toISOString()
        });
      } catch (error) {
        logSh(`⚠️ Erreur broadcast WebSocket: ${error.message}`, 'WARN');
      }
    }
  }

  /**
   * Obtient le statut actuel
   */
  getStatus() {
    return {
      validationId: this.validationId,
      status: this.status,
      progress: this.progress
    };
  }

  /**
   * Reset l'état
   */
  reset() {
    this.validationId = null;
    this.validationDir = null;
    this.csvData = null;  // ✅ NOUVEAU: Reset csvData
    this.executor.reset();
    this.samplingEngine.reset();
    this.criteriaEvaluator.resetCache();  // ✅ NOUVEAU: Reset cache évaluations
    this.status = 'idle';
    this.progress = {
      phase: null,
      message: '',
      percentage: 0
    };
  }
}

module.exports = { ValidatorCore, VALIDATION_PRESETS };
