// ========================================
// SELECTIVE CORE - MOTEUR MODULAIRE
// Responsabilité: Moteur selective enhancement réutilisable sur tout contenu
// Architecture: Couches applicables à la demande
// ========================================

const { logSh } = require('../ErrorReporting');
const { tracer } = require('../trace');
const { TrendManager } = require('../trend-prompts/TrendManager');

/**
 * MAIN ENTRY POINT - APPLICATION COUCHE SELECTIVE ENHANCEMENT
 * Input: contenu existant + configuration selective
 * Output: contenu avec couche selective appliquée
 */
async function applySelectiveLayer(existingContent, config = {}) {
  return await tracer.run('SelectiveCore.applySelectiveLayer()', async () => {
    const {
      layerType = 'technical', // 'technical' | 'transitions' | 'style' | 'all'
      llmProvider = 'auto',     // 'claude-sonnet-4-5' | 'gpt4' | 'gemini-pro' | 'mistral-small' | 'auto'
      analysisMode = true,      // Analyser avant d'appliquer
      preserveStructure = true,
      csvData = null,
      context = {},
      trendId = null,           // ID de tendance à appliquer
      trendManager = null       // Instance TrendManager (optionnel)
    } = config;

    // Initialiser TrendManager si tendance spécifiée
    let activeTrendManager = trendManager;
    if (trendId && !activeTrendManager) {
      activeTrendManager = new TrendManager();
      await activeTrendManager.setTrend(trendId);
    }

    await tracer.annotate({
      selectiveLayer: true,
      layerType,
      llmProvider,
      analysisMode,
      elementsCount: Object.keys(existingContent).length
    });

    const startTime = Date.now();
    logSh(`🔧 APPLICATION COUCHE SELECTIVE: ${layerType} (${llmProvider})`, 'INFO');
    logSh(`   📊 ${Object.keys(existingContent).length} éléments | Mode: ${analysisMode ? 'analysé' : 'direct'}`, 'INFO');

    try {
      let enhancedContent = {};
      let layerStats = {};

      // Sélection automatique du LLM si 'auto'
      const selectedLLM = selectOptimalLLM(layerType, llmProvider);

      // 🆕 LOG: LLM sélectionné et pourquoi
      if (llmProvider === 'auto') {
        logSh(`   🤖 Auto-sélection LLM: ${selectedLLM} (optimal pour ${layerType})`, 'INFO');
      } else {
        logSh(`   🤖 LLM spécifié: ${selectedLLM}`, 'DEBUG');
      }
      
      // Application selon type de couche avec configuration tendance
      switch (layerType) {
        case 'technical':
          logSh(`   🔬 Branche: Technical Enhancement`, 'DEBUG');
          const technicalConfig = activeTrendManager ?
            activeTrendManager.getLayerConfig('technical', { ...config, llmProvider: selectedLLM }) :
            { ...config, llmProvider: selectedLLM };
          logSh(`   📝 Config technique: LLM=${technicalConfig.llmProvider}, Intensity=${technicalConfig.intensity || 'default'}`, 'DEBUG');
          const technicalResult = await applyTechnicalEnhancement(existingContent, technicalConfig);
          enhancedContent = technicalResult.content;
          layerStats = technicalResult.stats;
          logSh(`   ✅ Technical enhancement terminé: ${layerStats.modificationsCount || 0} modifications`, 'DEBUG');
          break;

        case 'transitions':
          logSh(`   🔗 Branche: Transition Enhancement`, 'DEBUG');
          const transitionConfig = activeTrendManager ?
            activeTrendManager.getLayerConfig('transitions', { ...config, llmProvider: selectedLLM }) :
            { ...config, llmProvider: selectedLLM };
          logSh(`   📝 Config transitions: LLM=${transitionConfig.llmProvider}, Intensity=${transitionConfig.intensity || 'default'}`, 'DEBUG');
          const transitionResult = await applyTransitionEnhancement(existingContent, transitionConfig);
          enhancedContent = transitionResult.content;
          layerStats = transitionResult.stats;
          logSh(`   ✅ Transition enhancement terminé: ${layerStats.modificationsCount || 0} modifications`, 'DEBUG');
          break;

        case 'style':
          logSh(`   🎨 Branche: Style Enhancement`, 'DEBUG');
          const styleConfig = activeTrendManager ?
            activeTrendManager.getLayerConfig('style', { ...config, llmProvider: selectedLLM }) :
            { ...config, llmProvider: selectedLLM };
          logSh(`   📝 Config style: LLM=${styleConfig.llmProvider}, Intensity=${styleConfig.intensity || 'default'}`, 'DEBUG');
          const styleResult = await applyStyleEnhancement(existingContent, styleConfig);
          enhancedContent = styleResult.content;
          layerStats = styleResult.stats;
          logSh(`   ✅ Style enhancement terminé: ${layerStats.modificationsCount || 0} modifications`, 'DEBUG');
          break;
          
        case 'all':
          const allResult = await applyAllSelectiveLayers(existingContent, config);
          enhancedContent = allResult.content;
          layerStats = allResult.stats;
          break;
          
        default:
          throw new Error(`Type de couche selective inconnue: ${layerType}`);
      }

      const duration = Date.now() - startTime;
      const stats = {
        layerType,
        llmProvider: selectedLLM,
        elementsProcessed: Object.keys(existingContent).length,
        elementsEnhanced: countEnhancedElements(existingContent, enhancedContent),
        duration,
        ...layerStats
      };

      logSh(`✅ COUCHE SELECTIVE APPLIQUÉE: ${stats.elementsEnhanced}/${stats.elementsProcessed} améliorés (${duration}ms)`, 'INFO');

      await tracer.event('Couche selective appliquée', stats);

      return {
        content: enhancedContent,
        stats,
        modifications: stats.elementsEnhanced,  // ✅ AJOUTÉ: Mapping pour PipelineExecutor
        original: existingContent,
        config: { ...config, llmProvider: selectedLLM }
      };

    } catch (error) {
      const duration = Date.now() - startTime;
      logSh(`❌ COUCHE SELECTIVE ÉCHOUÉE après ${duration}ms: ${error.message}`, 'ERROR');
      
      // Fallback: retourner contenu original
      logSh(`🔄 Fallback: contenu original conservé`, 'WARNING');
      return {
        content: existingContent,
        stats: { fallback: true, duration },
        original: existingContent,
        config,
        error: error.message
      };
    }
  }, { existingContent: Object.keys(existingContent), config });
}

/**
 * APPLICATION TECHNIQUE MODULAIRE
 */
async function applyTechnicalEnhancement(content, config = {}) {
  const { TechnicalLayer } = require('./TechnicalLayer');
  const layer = new TechnicalLayer();
  return await layer.apply(content, config);
}

/**
 * APPLICATION TRANSITIONS MODULAIRE
 */
async function applyTransitionEnhancement(content, config = {}) {
  const { TransitionLayer } = require('./TransitionLayer');
  const layer = new TransitionLayer();
  return await layer.apply(content, config);
}

/**
 * APPLICATION STYLE MODULAIRE
 */
async function applyStyleEnhancement(content, config = {}) {
  const { StyleLayer } = require('./StyleLayer');
  const layer = new StyleLayer();
  return await layer.apply(content, config);
}

/**
 * APPLICATION TOUTES COUCHES SÉQUENTIELLES
 */
async function applyAllSelectiveLayers(content, config = {}) {
  logSh(`🔄 Application séquentielle toutes couches selective`, 'DEBUG');
  
  let currentContent = content;
  const allStats = {
    steps: [],
    totalDuration: 0,
    totalEnhancements: 0
  };
  
  const steps = [
    { name: 'technical', llm: 'gpt-4o-mini' },
    { name: 'transitions', llm: 'gemini-pro' },
    { name: 'style', llm: 'mistral-small' }
  ];
  
  for (const step of steps) {
    try {
      logSh(`   🔧 Étape: ${step.name} (${step.llm})`, 'DEBUG');
      
      const stepResult = await applySelectiveLayer(currentContent, {
        ...config,
        layerType: step.name,
        llmProvider: step.llm
      });
      
      currentContent = stepResult.content;
      
      allStats.steps.push({
        name: step.name,
        llm: step.llm,
        ...stepResult.stats
      });
      
      allStats.totalDuration += stepResult.stats.duration;
      allStats.totalEnhancements += stepResult.stats.elementsEnhanced;
      
    } catch (error) {
      logSh(`   ❌ Étape ${step.name} échouée: ${error.message}`, 'ERROR');
      
      allStats.steps.push({
        name: step.name,
        llm: step.llm,
        error: error.message,
        duration: 0,
        elementsEnhanced: 0
      });
    }
  }
  
  return {
    content: currentContent,
    stats: allStats
  };
}

/**
 * ANALYSE BESOIN D'ENHANCEMENT
 */
async function analyzeEnhancementNeeds(content, config = {}) {
  logSh(`🔍 Analyse besoins selective enhancement`, 'DEBUG');
  
  const analysis = {
    technical: { needed: false, score: 0, elements: [] },
    transitions: { needed: false, score: 0, elements: [] },
    style: { needed: false, score: 0, elements: [] },
    recommendation: 'none'
  };
  
  // Analyser chaque élément
  Object.entries(content).forEach(([tag, text]) => {
    // Analyse technique (termes techniques manquants)
    const technicalNeed = assessTechnicalNeed(text, config.csvData);
    if (technicalNeed.score > 0.3) {
      analysis.technical.needed = true;
      analysis.technical.score += technicalNeed.score;
      analysis.technical.elements.push({ tag, score: technicalNeed.score, reason: technicalNeed.reason });
    }
    
    // Analyse transitions (fluidité)
    const transitionNeed = assessTransitionNeed(text);
    if (transitionNeed.score > 0.4) {
      analysis.transitions.needed = true;
      analysis.transitions.score += transitionNeed.score;
      analysis.transitions.elements.push({ tag, score: transitionNeed.score, reason: transitionNeed.reason });
    }
    
    // Analyse style (personnalité)
    const styleNeed = assessStyleNeed(text, config.csvData?.personality);
    if (styleNeed.score > 0.3) {
      analysis.style.needed = true;
      analysis.style.score += styleNeed.score;
      analysis.style.elements.push({ tag, score: styleNeed.score, reason: styleNeed.reason });
    }
  });
  
  // Normaliser scores
  const elementCount = Object.keys(content).length;
  analysis.technical.score = analysis.technical.score / elementCount;
  analysis.transitions.score = analysis.transitions.score / elementCount;
  analysis.style.score = analysis.style.score / elementCount;
  
  // Recommandation
  const scores = [
    { type: 'technical', score: analysis.technical.score },
    { type: 'transitions', score: analysis.transitions.score },
    { type: 'style', score: analysis.style.score }
  ].sort((a, b) => b.score - a.score);
  
  if (scores[0].score > 0.6) {
    analysis.recommendation = scores[0].type;
  } else if (scores[0].score > 0.4) {
    analysis.recommendation = 'light_' + scores[0].type;
  }
  
  logSh(`   📊 Analyse: Tech=${analysis.technical.score.toFixed(2)} | Trans=${analysis.transitions.score.toFixed(2)} | Style=${analysis.style.score.toFixed(2)}`, 'DEBUG');
  logSh(`   💡 Recommandation: ${analysis.recommendation}`, 'DEBUG');
  
  return analysis;
}

// ============= HELPER FUNCTIONS =============

/**
 * Sélectionner LLM optimal selon type de couche
 */
function selectOptimalLLM(layerType, llmProvider) {
  if (llmProvider !== 'auto') return llmProvider;
  
  const optimalMapping = {
    'technical': 'gpt-4o-mini',    // OpenAI GPT-4o Mini excellent pour précision technique
    'transitions': 'gemini-pro',   // Gemini bon pour fluidité
    'style': 'mistral-small',       // Mistral excellent pour style personnalité
    'all': 'claude-sonnet-4-5'           // Claude polyvalent pour tout
  };
  
  return optimalMapping[layerType] || 'claude-sonnet-4-5';
}

/**
 * Compter éléments améliorés
 */
function countEnhancedElements(original, enhanced) {
  let count = 0;
  
  Object.keys(original).forEach(tag => {
    if (enhanced[tag] && enhanced[tag] !== original[tag]) {
      count++;
    }
  });
  
  return count;
}

/**
 * Évaluer besoin technique
 */
function assessTechnicalNeed(content, csvData) {
  let score = 0;
  let reason = [];
  
  // Manque de termes techniques spécifiques
  if (csvData?.mc0) {
    const technicalTerms = ['dibond', 'pmma', 'aluminium', 'fraisage', 'impression', 'gravure', 'découpe'];
    const contentLower = content.toLowerCase();
    const foundTerms = technicalTerms.filter(term => contentLower.includes(term));
    
    if (foundTerms.length === 0 && content.length > 100) {
      score += 0.4;
      reason.push('manque_termes_techniques');
    }
  }
  
  // Vocabulaire trop générique
  const genericWords = ['produit', 'solution', 'service', 'qualité', 'offre'];
  const genericCount = genericWords.filter(word => content.toLowerCase().includes(word)).length;
  
  if (genericCount > 2) {
    score += 0.3;
    reason.push('vocabulaire_générique');
  }
  
  // Manque de précision dimensionnelle/technique
  if (content.length > 50 && !(/\d+\s*(mm|cm|m|%|°)/.test(content))) {
    score += 0.2;
    reason.push('manque_précision_technique');
  }
  
  return { score: Math.min(1, score), reason: reason.join(',') };
}

/**
 * Évaluer besoin transitions
 */
function assessTransitionNeed(content) {
  let score = 0;
  let reason = [];
  
  const sentences = content.split(/[.!?]+/).filter(s => s.trim().length > 10);
  
  if (sentences.length < 2) return { score: 0, reason: '' };
  
  // Connecteurs répétitifs
  const connectors = ['par ailleurs', 'en effet', 'de plus', 'cependant'];
  let repetitiveConnectors = 0;
  
  connectors.forEach(connector => {
    const matches = (content.match(new RegExp(connector, 'gi')) || []);
    if (matches.length > 1) repetitiveConnectors++;
  });
  
  if (repetitiveConnectors > 1) {
    score += 0.4;
    reason.push('connecteurs_répétitifs');
  }
  
  // Transitions abruptes (phrases sans connecteurs logiques)
  let abruptTransitions = 0;
  for (let i = 1; i < sentences.length; i++) {
    const sentence = sentences[i].trim().toLowerCase();
    const hasConnector = connectors.some(conn => sentence.startsWith(conn)) ||
                        /^(puis|ensuite|également|aussi|donc|ainsi)/.test(sentence);
    
    if (!hasConnector && sentence.length > 30) {
      abruptTransitions++;
    }
  }
  
  if (abruptTransitions / sentences.length > 0.6) {
    score += 0.3;
    reason.push('transitions_abruptes');
  }
  
  return { score: Math.min(1, score), reason: reason.join(',') };
}

/**
 * Évaluer besoin style
 */
function assessStyleNeed(content, personality) {
  let score = 0;
  let reason = [];
  
  if (!personality) {
    score += 0.2;
    reason.push('pas_personnalité');
    return { score, reason: reason.join(',') };
  }
  
  // Style générique (pas de personnalité visible)
  const personalityWords = (personality.vocabulairePref || '').toLowerCase().split(',');
  const contentLower = content.toLowerCase();
  
  const personalityFound = personalityWords.some(word => 
    word.trim() && contentLower.includes(word.trim())
  );
  
  if (!personalityFound && content.length > 50) {
    score += 0.4;
    reason.push('style_générique');
  }
  
  // Niveau technique inadapté
  if (personality.niveauTechnique === 'accessible' && /\b(optimisation|implémentation|méthodologie)\b/i.test(content)) {
    score += 0.3;
    reason.push('trop_technique');
  }
  
  return { score: Math.min(1, score), reason: reason.join(',') };
}

module.exports = {
  applySelectiveLayer,              // ← MAIN ENTRY POINT MODULAIRE
  applyTechnicalEnhancement,
  applyTransitionEnhancement, 
  applyStyleEnhancement,
  applyAllSelectiveLayers,
  analyzeEnhancementNeeds,
  selectOptimalLLM
};