// ========================================
// SMART TOUCH CORE - Orchestrateur SelectiveSmartTouch
// Responsabilité: Orchestration complète Analyse → Améliorations ciblées
// Architecture: Analyse intelligente PUIS améliorations précises (contrôle total)
// ========================================

const { logSh } = require('../ErrorReporting');
const { tracer } = require('../trace');
const { SmartAnalysisLayer } = require('./SmartAnalysisLayer');
const { SmartTechnicalLayer } = require('./SmartTechnicalLayer');
const { SmartStyleLayer } = require('./SmartStyleLayer');
const { SmartReadabilityLayer } = require('./SmartReadabilityLayer');
const { GlobalBudgetManager } = require('./GlobalBudgetManager');  // ✅ NOUVEAU: Budget global

/**
 * SMART TOUCH CORE
 * Orchestrateur principal: Analyse → Technical → Style → Readability (ciblé)
 */
class SmartTouchCore {
  constructor() {
    this.name = 'SelectiveSmartTouch';

    // Instancier les layers
    this.analysisLayer = new SmartAnalysisLayer();
    this.technicalLayer = new SmartTechnicalLayer();
    this.styleLayer = new SmartStyleLayer();
    this.readabilityLayer = new SmartReadabilityLayer();
  }

  /**
   * APPLIQUER SMART TOUCH COMPLET
   * @param {object} content - Map {tag: texte}
   * @param {object} config - Configuration
   * @returns {object} - Résultat avec stats détaillées
   */
  async apply(content, config = {}) {
    return await tracer.run('SmartTouchCore.apply()', async () => {
      const {
        mode = 'full',          // 'analysis_only', 'technical_only', 'style_only', 'readability_only', 'full'
        intensity = 1.0,
        csvData = null,
        llmProvider = 'gpt-4o-mini',  // ✅ LLM à utiliser (extrait du pipeline config)
        skipAnalysis = false,   // Si true, applique sans analyser (mode legacy)
        layersOrder = ['technical', 'style', 'readability'],  // Ordre d'application personnalisable
        charsPerExpression = 4000  // ✅ NOUVEAU: Caractères par expression familière (configurable)
      } = config;

      await tracer.annotate({
        selectiveSmartTouch: true,
        mode,
        intensity,
        elementsCount: Object.keys(content).length,
        personality: csvData?.personality?.nom
      });

      const startTime = Date.now();
      logSh(`🧠 SELECTIVE SMART TOUCH START: ${Object.keys(content).length} éléments | Mode: ${mode}`, 'INFO');

      try {
        let currentContent = { ...content };
        const stats = {
          mode,
          analysisResults: {},
          layersApplied: [],
          totalModifications: 0,
          elementsProcessed: Object.keys(content).length,
          elementsImproved: 0,
          duration: 0
        };

        // === ✅ FIX: INITIALISER BUDGET GLOBAL AVANT TOUT (scope global) ===
        const budgetConfig = {
          charsPerExpression: config.charsPerExpression || 4000  // Configurable via pipeline
        };
        const budgetManager = new GlobalBudgetManager(csvData?.personality, currentContent, budgetConfig);
        const allTags = Object.keys(currentContent);
        budgetManager.distributeRandomly(allTags);

        logSh(`💰 Budget global initialisé: ${JSON.stringify(budgetManager.budget)}`, 'INFO');
        logSh(`🎲 Budget distribué sur ${allTags.length} tags`, 'INFO');

        // ========================================
        // PHASE 1: ANALYSE INTELLIGENTE
        // ========================================
        if (!skipAnalysis) {
          logSh(`\n📊 === PHASE 1: ANALYSE INTELLIGENTE ===`, 'INFO');

          const analysisResults = await this.analysisLayer.analyzeBatch(currentContent, {
            mc0: csvData?.mc0,
            personality: csvData?.personality,
            llmProvider  // ✅ Passer LLM à l'analyse batch
          });

          stats.analysisResults = analysisResults;

          // Résumer analyse
          const summary = this.analysisLayer.summarizeBatchAnalysis(analysisResults);
          logSh(`   📋 Résumé analyse: ${summary.needsImprovement}/${summary.totalElements} éléments nécessitent amélioration`, 'INFO');
          logSh(`   📊 Score moyen: ${summary.averageScore.toFixed(2)} | Améliorations totales: ${summary.totalImprovements}`, 'INFO');
          logSh(`   🎯 Besoins: Technical=${summary.commonIssues.technical} | Style=${summary.commonIssues.style} | Readability=${summary.commonIssues.readability}`, 'INFO');

          // Si mode analysis_only, retourner ici
          if (mode === 'analysis_only') {
            const duration = Date.now() - startTime;
            logSh(`✅ SELECTIVE SMART TOUCH (ANALYSIS ONLY) terminé: ${duration}ms`, 'INFO');

            return {
              content: currentContent,
              stats: {
                ...stats,
                duration,
                analysisOnly: true
              },
              modifications: 0,
              analysisResults
            };
          }

          // ========================================
          // PHASE 2: AMÉLIORATIONS CIBLÉES
          // ========================================
          logSh(`\n🔧 === PHASE 2: AMÉLIORATIONS CIBLÉES ===`, 'INFO');

          // Déterminer quelles couches appliquer
          const layersToApply = this.determineLayersToApply(mode, layersOrder);

          // === DÉTECTION CONTEXTE GLOBALE (1 seule fois) ===
          const contentContext = this.analysisLayer.detectContentContext(
            Object.values(currentContent).join(' '),
            csvData?.personality
          );

          // === ✅ FIX: SÉLECTIONNER 10% SEGMENTS UNE SEULE FOIS (GLOBAL) ===
          logSh(`\n🎯 === SÉLECTION 10% SEGMENTS GLOBAUX ===`, 'INFO');

          const percentageToImprove = intensity * 0.1;
          const segmentsByTag = {};

          // Pré-calculer segments et sélection pour chaque tag UNE SEULE FOIS
          for (const [tag, text] of Object.entries(currentContent)) {
            const analysis = analysisResults[tag];
            if (!analysis) continue;

            // Analyser par segments
            const segments = this.analysisLayer.analyzeBySegments(text, {
              mc0: csvData?.mc0,
              personality: csvData?.personality
            });

            // Sélectionner les X% segments les plus faibles
            const weakestSegments = this.analysisLayer.selectWeakestSegments(
              segments,
              percentageToImprove
            );

            segmentsByTag[tag] = {
              segments,
              weakestSegments,
              analysis
            };

            logSh(`   📊 [${tag}] ${segments.length} segments, ${weakestSegments.length} sélectionnés (${(percentageToImprove * 100).toFixed(0)}%)`, 'INFO');
          }

          // === APPLIQUER TOUTES LES LAYERS SUR LES MÊMES SEGMENTS SÉLECTIONNÉS ===
          const improvedTags = new Set();  // ✅ FIX: Tracker les tags améliorés (pas de duplicata)

          for (const layerName of layersToApply) {
            const layerStartTime = Date.now();
            logSh(`\n   🎯 Couche: ${layerName}`, 'INFO');

            let layerModifications = 0;
            const layerResults = {};

            // Appliquer la couche sur chaque élément (en réutilisant les MÊMES segments sélectionnés)
            for (const [tag, text] of Object.entries(currentContent)) {
              const tagData = segmentsByTag[tag];
              if (!tagData) continue;

              try {
                // ✅ Utiliser les segments PRÉ-SÉLECTIONNÉS (pas de nouvelle sélection)
                const { segments, weakestSegments, analysis } = tagData;

                // Appliquer amélioration UNIQUEMENT sur segments déjà sélectionnés
                const result = await this.applyLayerToSegments(
                  layerName,
                  segments,
                  weakestSegments,
                  analysis,
                  {
                    mc0: csvData?.mc0,
                    personality: csvData?.personality,
                    intensity,
                    contentContext,  // Passer contexte aux layers
                    llmProvider,  // ✅ Passer LLM choisi dans pipeline
                    budgetManager,  // ✅ NOUVEAU: Passer budget manager
                    currentTag: tag  // ✅ NOUVEAU: Tag actuel pour tracking budget
                  }
                );

                if (!result.skipped && result.content !== text) {
                  currentContent[tag] = result.content;
                  layerModifications += result.modifications || 0;
                  improvedTags.add(tag);  // ✅ FIX: Ajouter au Set (pas de duplicata)
                }

                layerResults[tag] = result;

              } catch (error) {
                logSh(`      ❌ [${tag}] Échec ${layerName}: ${error.message}`, 'ERROR');
              }
            }

            const layerDuration = Date.now() - layerStartTime;

            stats.layersApplied.push({
              name: layerName,
              modifications: layerModifications,
              duration: layerDuration
            });

            stats.totalModifications += layerModifications;

            logSh(`   ✅ ${layerName} terminé: ${layerModifications} modifications (${layerDuration}ms)`, 'INFO');
          }

          // ✅ FIX: Mettre à jour le compteur d'éléments améliorés APRÈS toutes les layers
          stats.elementsImproved = improvedTags.size;

        } else {
          // Mode skipAnalysis: appliquer sans analyse (legacy fallback)
          logSh(`⚠️ Mode skipAnalysis activé: application directe sans analyse préalable`, 'WARNING');

          // TODO: Implémenter mode legacy si nécessaire
          logSh(`❌ Mode skipAnalysis non implémenté pour SmartTouch (requiert analyse)`, 'ERROR');
        }

        // ========================================
        // RÉSULTATS FINAUX
        // ========================================
        const duration = Date.now() - startTime;
        stats.duration = duration;

        // === ✅ NOUVEAU: Rapport budget final ===
        const budgetReport = budgetManager?.getReport();
        if (budgetReport) {
          stats.budgetReport = budgetReport;

          logSh(`\n💰 === RAPPORT BUDGET EXPRESSIONS ===`, 'INFO');
          logSh(`   📊 Budget total: ${budgetReport.budget.total}`, 'INFO');
          logSh(`   ✅ Consommé: ${budgetReport.totalConsumed} (${budgetReport.percentageUsed}%)`, 'INFO');
          logSh(`   💸 Restant: ${budgetReport.remaining}`, 'INFO');
          if (budgetReport.overBudget) {
            logSh(`   ⚠️ DÉPASSEMENT BUDGET !`, 'WARN');
          }
        }

        logSh(`\n✅ === SELECTIVE SMART TOUCH TERMINÉ ===`, 'INFO');
        logSh(`   📊 ${stats.elementsImproved}/${stats.elementsProcessed} éléments améliorés`, 'INFO');
        logSh(`   🔄 ${stats.totalModifications} modifications totales`, 'INFO');
        logSh(`   ⏱️  Durée: ${duration}ms`, 'INFO');
        logSh(`   🎯 Couches appliquées: ${stats.layersApplied.map(l => l.name).join(' → ')}`, 'INFO');

        await tracer.event('SelectiveSmartTouch terminé', stats);

        return {
          content: currentContent,
          stats,
          modifications: stats.totalModifications,
          analysisResults: stats.analysisResults,
          budgetReport  // ✅ NOUVEAU: Inclure rapport budget
        };

      } catch (error) {
        const duration = Date.now() - startTime;
        logSh(`❌ SELECTIVE SMART TOUCH ÉCHOUÉ après ${duration}ms: ${error.message}`, 'ERROR');

        return {
          content,  // Fallback: contenu original
          stats: {
            error: error.message,
            duration,
            fallback: true
          },
          modifications: 0,
          fallback: true
        };
      }
    }, { content: Object.keys(content), config });
  }

  /**
   * DÉTERMINER COUCHES À APPLIQUER
   */
  determineLayersToApply(mode, layersOrder) {
    switch (mode) {
      case 'technical_only':
        return ['technical'];
      case 'style_only':
        return ['style'];
      case 'readability_only':
        return ['readability'];
      case 'full':
      default:
        return layersOrder;  // Ordre personnalisable
    }
  }

  /**
   * APPLIQUER UNE COUCHE SPÉCIFIQUE
   */
  async applyLayer(layerName, content, analysis, context) {
    switch (layerName) {
      case 'technical':
        return await this.technicalLayer.applyTargeted(content, analysis, context);
      case 'style':
        return await this.styleLayer.applyTargeted(content, analysis, context);
      case 'readability':
        return await this.readabilityLayer.applyTargeted(content, analysis, context);
      default:
        throw new Error(`Couche inconnue: ${layerName}`);
    }
  }

  /**
   * APPLIQUER COUCHE SUR SEGMENTS SÉLECTIONNÉS UNIQUEMENT (10% système)
   * @param {string} layerName - Nom de la couche
   * @param {array} allSegments - Tous les segments du texte
   * @param {array} weakestSegments - Segments sélectionnés à améliorer
   * @param {object} analysis - Analyse globale
   * @param {object} context - Contexte
   * @returns {object} - { content: texte réassemblé, modifications, ... }
   */
  async applyLayerToSegments(layerName, allSegments, weakestSegments, analysis, context) {
    // Si aucun segment à améliorer, retourner texte original
    if (weakestSegments.length === 0) {
      const originalContent = allSegments.map(s => s.content).join(' ');
      return {
        content: originalContent,
        modifications: 0,
        skipped: true,
        reason: 'No weak segments identified'
      };
    }

    // Créer Map des indices des segments à améliorer pour lookup rapide
    const weakIndices = new Set(weakestSegments.map(s => s.index));

    // === AMÉLIORER UNIQUEMENT LES SEGMENTS FAIBLES ===
    const improvedSegments = [];
    let totalModifications = 0;

    for (const segment of allSegments) {
      if (weakIndices.has(segment.index)) {
        // AMÉLIORER ce segment
        try {
          const result = await this.applyLayer(layerName, segment.content, analysis, context);

          improvedSegments.push({
            ...segment,
            content: result.skipped ? segment.content : result.content,
            improved: !result.skipped
          });

          totalModifications += result.modifications || 0;

        } catch (error) {
          logSh(`      ⚠️ Échec amélioration segment ${segment.index}: ${error.message}`, 'WARN');
          // Fallback: garder segment original
          improvedSegments.push({
            ...segment,
            content: segment.content,  // ✅ FIX: Copier content original
            improved: false
          });
        }
      } else {
        // GARDER segment intact
        improvedSegments.push({
          ...segment,
          content: segment.content,  // ✅ FIX: Copier content original
          improved: false
        });
      }
    }

    // === RÉASSEMBLER TEXTE COMPLET ===
    const reassembledContent = improvedSegments.map(s => s.content).join(' ');

    // Nettoyer espaces multiples
    const cleanedContent = reassembledContent.replace(/\s{2,}/g, ' ').trim();

    const improvedCount = improvedSegments.filter(s => s.improved).length;

    logSh(`      ✅ ${improvedCount}/${allSegments.length} segments améliorés (${totalModifications} modifs)`, 'DEBUG');

    return {
      content: cleanedContent,
      modifications: totalModifications,
      segmentsImproved: improvedCount,
      segmentsTotal: allSegments.length,
      skipped: false
    };
  }

  /**
   * MODES DISPONIBLES
   */
  static getAvailableModes() {
    return [
      {
        name: 'analysis_only',
        description: 'Analyse uniquement (sans amélioration)',
        layers: []
      },
      {
        name: 'technical_only',
        description: 'Améliorations techniques ciblées uniquement',
        layers: ['technical']
      },
      {
        name: 'style_only',
        description: 'Améliorations style ciblées uniquement',
        layers: ['style']
      },
      {
        name: 'readability_only',
        description: 'Améliorations lisibilité ciblées uniquement',
        layers: ['readability']
      },
      {
        name: 'full',
        description: 'Analyse + toutes améliorations ciblées (recommandé)',
        layers: ['technical', 'style', 'readability']
      }
    ];
  }
}

module.exports = { SmartTouchCore };
