// ========================================
// STYLE LAYER - COUCHE STYLE MODULAIRE
// Responsabilité: Adaptation personnalité modulaire réutilisable
// LLM: Mistral (excellence style et personnalité)
// ========================================

const { callLLM } = require('../LLMManager');
const { logSh } = require('../ErrorReporting');
const { tracer } = require('../trace');
const { chunkArray, sleep } = require('./SelectiveUtils');

/**
 * COUCHE STYLE MODULAIRE
 */
class StyleLayer {
  constructor() {
    this.name = 'StyleEnhancement';
    this.defaultLLM = 'mistral';
    this.priority = 3; // Priorité basse - appliqué en dernier
  }

  /**
   * MAIN METHOD - Appliquer amélioration style
   */
  async apply(content, config = {}) {
    return await tracer.run('StyleLayer.apply()', async () => {
      const {
        llmProvider = this.defaultLLM,
        intensity = 1.0,          // 0.0-2.0 intensité d'amélioration
        analysisMode = true,      // Analyser avant d'appliquer
        csvData = null,
        preserveStructure = true,
        targetStyle = null        // Style spécifique à appliquer
      } = config;

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

      const startTime = Date.now();
      logSh(`🎨 STYLE LAYER: Amélioration personnalité (${llmProvider})`, 'INFO');
      logSh(`   📊 ${Object.keys(content).length} éléments | Style: ${csvData?.personality?.nom || 'standard'}`, 'INFO');

      try {
        let enhancedContent = {};
        let elementsProcessed = 0;
        let elementsEnhanced = 0;

        // Vérifier présence personnalité
        if (!csvData?.personality && !targetStyle) {
          logSh(`⚠️ STYLE LAYER: Pas de personnalité définie, style générique appliqué`, 'WARNING');
        }

        if (analysisMode) {
          // 1. Analyser éléments nécessitant amélioration style
          const analysis = await this.analyzeStyleNeeds(content, csvData, targetStyle);
          
          logSh(`   📋 Analyse: ${analysis.candidates.length}/${Object.keys(content).length} éléments candidats`, 'DEBUG');
          
          if (analysis.candidates.length === 0) {
            logSh(`✅ STYLE LAYER: Style déjà cohérent`, 'INFO');
            return {
              content,
              stats: { 
                processed: Object.keys(content).length, 
                enhanced: 0, 
                analysisSkipped: true, 
                duration: Date.now() - startTime 
              }
            };
          }

          // 2. Améliorer les éléments sélectionnés
          const improvedResults = await this.enhanceStyleElements(
            analysis.candidates, 
            csvData, 
            { llmProvider, intensity, preserveStructure, targetStyle }
          );

          // 3. Merger avec contenu original
          enhancedContent = { ...content };
          Object.keys(improvedResults).forEach(tag => {
            if (improvedResults[tag] !== content[tag]) {
              enhancedContent[tag] = improvedResults[tag];
              elementsEnhanced++;
            }
          });
          
          elementsProcessed = analysis.candidates.length;

        } else {
          // Mode direct : améliorer tous les éléments textuels
          const textualElements = Object.entries(content)
            .filter(([tag, text]) => text.length > 50 && !tag.includes('FAQ_Question'))
            .map(([tag, text]) => ({ tag, content: text, styleIssues: ['adaptation_générale'] }));
          
          if (textualElements.length === 0) {
            return { content, stats: { processed: 0, enhanced: 0, duration: Date.now() - startTime } };
          }
          
          const improvedResults = await this.enhanceStyleElements(
            textualElements, 
            csvData, 
            { llmProvider, intensity, preserveStructure, targetStyle }
          );
          
          enhancedContent = { ...content };
          Object.keys(improvedResults).forEach(tag => {
            if (improvedResults[tag] !== content[tag]) {
              enhancedContent[tag] = improvedResults[tag];
              elementsEnhanced++;
            }
          });
          
          elementsProcessed = textualElements.length;
        }

        const duration = Date.now() - startTime;
        const stats = {
          processed: elementsProcessed,
          enhanced: elementsEnhanced,
          total: Object.keys(content).length,
          enhancementRate: (elementsEnhanced / Math.max(elementsProcessed, 1)) * 100,
          duration,
          llmProvider,
          intensity,
          personalityApplied: csvData?.personality?.nom || targetStyle || 'générique'
        };

        logSh(`✅ STYLE LAYER TERMINÉE: ${elementsEnhanced}/${elementsProcessed} stylisés (${duration}ms)`, 'INFO');

        await tracer.event('Style layer appliquée', stats);

        return { content: enhancedContent, stats };

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

  /**
   * ANALYSER BESOINS STYLE
   */
  async analyzeStyleNeeds(content, csvData, targetStyle = null) {
    logSh(`🎨 Analyse besoins style`, 'DEBUG');
    
    const analysis = {
      candidates: [],
      globalScore: 0,
      styleIssues: {
        genericLanguage: 0,
        personalityMismatch: 0,
        inconsistentTone: 0,
        missingVocabulary: 0
      }
    };

    const personality = csvData?.personality;
    const expectedStyle = targetStyle || personality;

    // Analyser chaque élément
    Object.entries(content).forEach(([tag, text]) => {
      const elementAnalysis = this.analyzeStyleElement(text, expectedStyle, csvData);
      
      if (elementAnalysis.needsImprovement) {
        analysis.candidates.push({
          tag,
          content: text,
          styleIssues: elementAnalysis.issues,
          score: elementAnalysis.score,
          improvements: elementAnalysis.improvements
        });
        
        analysis.globalScore += elementAnalysis.score;
        
        // Compter types d'issues
        elementAnalysis.issues.forEach(issue => {
          if (analysis.styleIssues.hasOwnProperty(issue)) {
            analysis.styleIssues[issue]++;
          }
        });
      }
    });

    analysis.globalScore = analysis.globalScore / Math.max(Object.keys(content).length, 1);
    
    logSh(`   📊 Score global style: ${analysis.globalScore.toFixed(2)}`, 'DEBUG');
    logSh(`   🎭 Issues style: ${JSON.stringify(analysis.styleIssues)}`, 'DEBUG');
    
    return analysis;
  }

  /**
   * AMÉLIORER ÉLÉMENTS STYLE SÉLECTIONNÉS
   */
  async enhanceStyleElements(candidates, csvData, config) {
    logSh(`🎨 Amélioration ${candidates.length} éléments style`, 'DEBUG');
    
    const results = {};
    const chunks = chunkArray(candidates, 5); // Chunks optimisés pour Mistral
    
    for (let chunkIndex = 0; chunkIndex < chunks.length; chunkIndex++) {
      const chunk = chunks[chunkIndex];
      
      try {
        logSh(`   📦 Chunk style ${chunkIndex + 1}/${chunks.length}: ${chunk.length} éléments`, 'DEBUG');
        
        const enhancementPrompt = this.createStyleEnhancementPrompt(chunk, csvData, config);
        
        const response = await callLLM(config.llmProvider, enhancementPrompt, {
          temperature: 0.8, // Créativité élevée pour style
          maxTokens: 3000
        }, csvData?.personality);
        
        const chunkResults = this.parseStyleResponse(response, chunk);
        Object.assign(results, chunkResults);
        
        logSh(`   ✅ Chunk style ${chunkIndex + 1}: ${Object.keys(chunkResults).length} stylisés`, 'DEBUG');
        
        // Délai entre chunks
        if (chunkIndex < chunks.length - 1) {
          await sleep(1800);
        }
        
      } catch (error) {
        logSh(`   ❌ Chunk style ${chunkIndex + 1} échoué: ${error.message}`, 'ERROR');
        
        // Fallback: conserver contenu original
        chunk.forEach(element => {
          results[element.tag] = element.content;
        });
      }
    }
    
    return results;
  }

  // ============= HELPER METHODS =============

  /**
   * Analyser élément style individuel
   */
  analyzeStyleElement(text, expectedStyle, csvData) {
    let score = 0;
    const issues = [];
    const improvements = [];
    
    // Si pas de style attendu, score faible
    if (!expectedStyle) {
      return { needsImprovement: false, score: 0.1, issues: ['pas_style_défini'], improvements: [] };
    }
    
    // 1. Analyser langage générique
    const genericScore = this.analyzeGenericLanguage(text);
    if (genericScore > 0.4) {
      score += 0.3;
      issues.push('genericLanguage');
      improvements.push('personnaliser_vocabulaire');
    }
    
    // 2. Analyser adéquation personnalité
    if (expectedStyle.vocabulairePref) {
      const personalityScore = this.analyzePersonalityAlignment(text, expectedStyle);
      if (personalityScore < 0.3) {
        score += 0.4;
        issues.push('personalityMismatch');
        improvements.push('appliquer_style_personnalité');
      }
    }
    
    // 3. Analyser cohérence de ton
    const toneScore = this.analyzeToneConsistency(text, expectedStyle);
    if (toneScore > 0.5) {
      score += 0.2;
      issues.push('inconsistentTone');
      improvements.push('unifier_ton');
    }
    
    // 4. Analyser vocabulaire spécialisé
    if (expectedStyle.niveauTechnique) {
      const vocabScore = this.analyzeVocabularyLevel(text, expectedStyle);
      if (vocabScore > 0.4) {
        score += 0.1;
        issues.push('missingVocabulary');
        improvements.push('ajuster_niveau_vocabulaire');
      }
    }
    
    return {
      needsImprovement: score > 0.3,
      score,
      issues,
      improvements
    };
  }

  /**
   * Analyser langage générique
   */
  analyzeGenericLanguage(text) {
    const genericPhrases = [
      'nos solutions', 'notre expertise', 'notre savoir-faire', 
      'nous vous proposons', 'nous mettons à votre disposition',
      'qualité optimale', 'service de qualité', 'expertise reconnue'
    ];
    
    let genericCount = 0;
    genericPhrases.forEach(phrase => {
      if (text.toLowerCase().includes(phrase)) genericCount++;
    });
    
    const wordCount = text.split(/\s+/).length;
    return Math.min(1, (genericCount / Math.max(wordCount / 50, 1)));
  }

  /**
   * Analyser alignement personnalité
   */
  analyzePersonalityAlignment(text, personality) {
    if (!personality.vocabulairePref) return 1;

    // Convertir en string si ce n'est pas déjà le cas
    const vocabPref = typeof personality.vocabulairePref === 'string'
      ? personality.vocabulairePref
      : String(personality.vocabulairePref);

    const preferredWords = vocabPref.toLowerCase().split(',');
    const contentLower = text.toLowerCase();
    
    let alignmentScore = 0;
    preferredWords.forEach(word => {
      if (word.trim() && contentLower.includes(word.trim())) {
        alignmentScore++;
      }
    });
    
    return Math.min(1, alignmentScore / Math.max(preferredWords.length, 1));
  }

  /**
   * Analyser cohérence de ton
   */
  analyzeToneConsistency(text, expectedStyle) {
    const sentences = text.split(/[.!?]+/).filter(s => s.trim().length > 10);
    if (sentences.length < 2) return 0;
    
    const tones = sentences.map(sentence => this.detectSentenceTone(sentence));
    const expectedTone = this.getExpectedTone(expectedStyle);
    
    let inconsistencies = 0;
    tones.forEach(tone => {
      if (tone !== expectedTone && tone !== 'neutral') {
        inconsistencies++;
      }
    });
    
    return inconsistencies / tones.length;
  }

  /**
   * Analyser niveau vocabulaire
   */
  analyzeVocabularyLevel(text, expectedStyle) {
    const technicalWords = text.match(/\b\w{8,}\b/g) || [];
    const expectedLevel = expectedStyle.niveauTechnique || 'standard';
    
    const techRatio = technicalWords.length / text.split(/\s+/).length;
    
    switch (expectedLevel) {
      case 'accessible':
        return techRatio > 0.1 ? techRatio : 0; // Trop technique
      case 'expert':
        return techRatio < 0.05 ? 1 - techRatio : 0; // Pas assez technique
      default:
        return techRatio > 0.15 || techRatio < 0.02 ? Math.abs(0.08 - techRatio) : 0;
    }
  }

  /**
   * Détecter ton de phrase
   */
  detectSentenceTone(sentence) {
    const lowerSentence = sentence.toLowerCase();
    
    if (/\b(excellent|remarquable|exceptionnel|parfait)\b/.test(lowerSentence)) return 'enthusiastic';
    if (/\b(il convient|nous recommandons|il est conseillé)\b/.test(lowerSentence)) return 'formal';
    if (/\b(sympa|cool|nickel|top)\b/.test(lowerSentence)) return 'casual';
    if (/\b(technique|précision|spécification)\b/.test(lowerSentence)) return 'technical';
    
    return 'neutral';
  }

  /**
   * Obtenir ton attendu selon personnalité
   */
  getExpectedTone(personality) {
    if (!personality || !personality.style) return 'neutral';
    
    const style = personality.style.toLowerCase();
    
    if (style.includes('technique') || style.includes('expert')) return 'technical';
    if (style.includes('commercial') || style.includes('vente')) return 'enthusiastic';
    if (style.includes('décontracté') || style.includes('moderne')) return 'casual';
    if (style.includes('professionnel') || style.includes('formel')) return 'formal';
    
    return 'neutral';
  }

  /**
   * Créer prompt amélioration style
   */
  createStyleEnhancementPrompt(chunk, csvData, config) {
    const personality = csvData?.personality || config.targetStyle;
    
    let prompt = `MISSION: Adapte UNIQUEMENT le style et la personnalité de ces contenus.

CONTEXTE: Article SEO ${csvData?.mc0 || 'signalétique personnalisée'}
${personality ? `PERSONNALITÉ CIBLE: ${personality.nom} (${personality.style})` : 'STYLE: Professionnel standard'}
${personality?.description ? `DESCRIPTION: ${personality.description}` : ''}
INTENSITÉ: ${config.intensity} (0.5=léger, 1.0=standard, 1.5=intensif)

CONTENUS À STYLISER:

${chunk.map((item, i) => `[${i + 1}] "${item.content}"
PROBLÈMES STYLE: ${item.styleIssues.join(', ')}`).join('\n\n')}

PROFIL PERSONNALITÉ ${personality?.nom || 'Standard'}:
${personality ? `- Style: ${personality.style}
- Niveau: ${personality.niveauTechnique || 'standard'}
- Vocabulaire préféré: ${personality.vocabulairePref || 'professionnel'}
- Connecteurs: ${personality.connecteursPref || 'variés'}
${personality.specificites ? `- Spécificités: ${personality.specificites}` : ''}` : '- Style professionnel web standard'}

OBJECTIFS STYLE:
- Appliquer personnalité ${personality?.nom || 'standard'} de façon naturelle
- Utiliser vocabulaire et expressions caractéristiques
- Maintenir cohérence de ton sur tout le contenu
- Adapter niveau technique selon profil (${personality?.niveauTechnique || 'standard'})
- Style web ${personality?.style || 'professionnel'} mais authentique

CONSIGNES STRICTES:
- NE CHANGE PAS le fond du message ni les informations factuelles
- GARDE même structure et longueur approximative (±15%)
- Applique SEULEMENT style et personnalité sur la forme
- RESPECTE impérativement le niveau ${personality?.niveauTechnique || 'standard'}
- ÉVITE exagération qui rendrait artificiel
- JAMAIS de répétitions de paragraphes entiers
- ⚠️ MAINTIENS un TON PROFESSIONNEL même avec personnalité décontractée
- ⚠️ LIMITE l'usage des connecteurs familiers ("du coup", "voilà", "écoutez") à 1-2 MAX par texte

TECHNIQUES STYLE:
${personality?.vocabulairePref ? `- Intégrer naturellement: ${personality.vocabulairePref}` : '- Vocabulaire professionnel équilibré'}
- Adapter registre de langue selon ${personality?.style || 'professionnel'}
- Expressions et tournures caractéristiques personnalité
- Ton cohérent: ${this.getExpectedTone(personality)} mais naturel
- Connecteurs préférés: ${personality?.connecteursPref || 'variés et naturels'} - MAIS AVEC PARCIMONIE (max 1-2 par texte)

RÈGLES VOCABULAIRE:
- ✅ BON: "Pour entretenir votre plaque, nettoyez-la régulièrement" → pro et direct
- ❌ MAUVAIS: "Écoutez, pour entretenir votre plaque, donc du coup, voilà ce qu'il faut faire" → trop familier
- ✅ BON: 1-2 touches de personnalité par paragraphe maximum
- ❌ MAUVAIS: Bombarder chaque phrase de marqueurs oraux excessifs

FORMAT RÉPONSE:
[1] Contenu avec style personnalisé
[2] Contenu avec style personnalisé
etc...

IMPORTANT: Réponds UNIQUEMENT par les contenus stylisés, SANS balises TAG, SANS métadonnées, SANS explications.`;

    return prompt;
  }

  /**
   * Parser réponse style
   */
  parseStyleResponse(response, chunk) {
    const results = {};
    const regex = /\[(\d+)\]\s*([^[]*?)(?=\n\[\d+\]|$)/gs;
    let match;
    let index = 0;
    
    while ((match = regex.exec(response)) && index < chunk.length) {
      let styledContent = match[2].trim();
      const element = chunk[index];
      
      // Nettoyer contenu stylisé
      styledContent = this.cleanStyleContent(styledContent);
      
      if (styledContent && styledContent.length > 10) {
        results[element.tag] = styledContent;
        logSh(`✅ Stylisé [${element.tag}]: "${styledContent.substring(0, 60)}..."`, 'DEBUG');
      } else {
        results[element.tag] = element.content; // Fallback
        logSh(`⚠️ Fallback style [${element.tag}]: amélioration invalide`, 'WARNING');
      }
      
      index++;
    }
    
    // Compléter les manquants
    while (index < chunk.length) {
      const element = chunk[index];
      results[element.tag] = element.content;
      index++;
    }
    
    return results;
  }

  /**
   * Nettoyer contenu style généré
   */
  cleanStyleContent(content) {
    if (!content) return content;

    // ✅ Supprimer balises TAG résiduelles
    content = content.replace(/^TAG:\s*[^\s]+\s+/gi, '');
    content = content.replace(/\bTAG:\s*[^\s]+\s+/gi, '');
    content = content.replace(/^CONTENU:\s*/gi, '');
    content = content.replace(/^PROBLÈMES STYLE:\s*/gi, '');

    // Supprimer préfixes indésirables
    content = content.replace(/^(voici\s+)?le\s+contenu\s+(stylisé|adapté|personnalisé)\s*[:.]?\s*/gi, '');
    content = content.replace(/^(avec\s+)?style\s+[^:]*\s*[:.]?\s*/gi, '');
    content = content.replace(/^(dans\s+le\s+style\s+de\s+)[^:]*[:.]?\s*/gi, '');

    // Nettoyer formatage
    content = content.replace(/\*\*[^*]+\*\*/g, ''); // Gras markdown
    content = content.replace(/\s{2,}/g, ' '); // Espaces multiples
    content = content.trim();

    return content;
  }
}

module.exports = { StyleLayer };