// ========================================
// MÉTRIQUES DE QUALITÉ - VALIDATION OBJECTIVE
// Calculs automatisés de qualité textuelle
// ========================================

// Import du LLMManager pour validation IA complémentaire
let LLMManager;
try {
  const llmModule = require('../../lib/LLMManager');
  if (llmModule && typeof llmModule.callLLM === 'function') {
    LLMManager = llmModule;
  }
} catch (error) {
  console.warn('LLMManager non disponible pour QualityMetrics:', error.message);
}

/**
 * Système de métriques objectifs pour évaluer la qualité du contenu
 */
class QualityMetrics {
  
  /**
   * 📊 CALCUL COMPLET MÉTRIQUES - ORCHESTRATEUR PRINCIPAL
   * 
   * CE QUI EST TESTÉ :
   * ✅ Calcul 5 métriques objectives automatiques (lisibilité, vocabulaire, structure, cohérence, SEO)
   * ✅ Score global pondéré équilibré 25% par métrique
   * ✅ Validation IA complémentaire optionnelle (si LLM disponible)
   * 
   * ALGORITHMES EXÉCUTÉS :
   * - 5 calculs en parallèle des métriques objectives
   * - Pondération : (readability + vocabulary + structure + coherence) * 0.25 chacun
   * - Si LLM activé : fusion 80% objectif + 20% validation IA
   * - Retour structure unifiée avec breakdown détaillé
   */
  static async calculateMetrics(content, options = {}) {
    // Métriques objectives (calculs mathématiques)
    const objectiveMetrics = {
      readability: this.calculateReadability(content),
      vocabulary: this.calculateVocabularyRichness(content),
      structure: this.calculateStructureMetrics(content),
      coherence: this.calculateCoherenceMetrics(content),
      seo: this.calculateSEOMetrics(content),
      overall: 0
    };
    
    // Score global pondéré objectif
    objectiveMetrics.overall = Math.round(
      objectiveMetrics.readability * 0.25 +
      objectiveMetrics.vocabulary * 0.25 +
      objectiveMetrics.structure * 0.25 +
      objectiveMetrics.coherence * 0.25
    );
    
    // Validation IA complémentaire (si LLM disponible)
    if (LLMManager && options.enableLLM !== false) {
      try {
        const aiValidation = await this.validateQualityWithLLM(content, objectiveMetrics);
        
        // Fusion des métriques (privilégier les calculs objectifs)
        const enhancedMetrics = {
          ...objectiveMetrics,
          aiInsights: aiValidation,
          // Score final: 80% objectif + 20% IA
          overall: Math.round(objectiveMetrics.overall * 0.8 + aiValidation.score * 0.2)
        };
        
        return enhancedMetrics;
        
      } catch (error) {
        console.warn('Erreur validation LLM qualité:', error.message);
      }
    }
    
    return objectiveMetrics;
  }
  
  /**
   * 🤖 VALIDATION LLM COMPLÉMENTAIRE - ANALYSE QUALITATIVE IA
   * 
   * CE QUI EST TESTÉ :
   * ✅ Appel OpenAI pour validation qualitative des métriques objectives
   * ✅ Évaluation fluidité, clarté, engagement, professionnalisme
   * ✅ Fusion intelligente scores objectifs + perception IA
   * 
   * ALGORITHMES EXÉCUTÉS :
   * - Prompt structuré avec métriques objectives en contexte
   * - Demande JSON strict : score + breakdown qualitatif + feedback
   * - Parse robuste avec fallback sur échec JSON
   * - Clamp scores dans [0,100] et confidence dans [0,1]
   */
  static async validateQualityWithLLM(content, objectiveMetrics) {
    const prompt = `
MISSION: Valide la qualité de ce contenu et confirme/ajuste les métriques objectives.

MÉTRIQUES OBJECTIVES CALCULÉES:
- Lisibilité: ${objectiveMetrics.readability}/100
- Vocabulaire: ${objectiveMetrics.vocabulary}/100  
- Structure: ${objectiveMetrics.structure}/100
- Cohérence: ${objectiveMetrics.coherence}/100
- Score global: ${objectiveMetrics.overall}/100

CONTENU À ANALYSER:
---
${content.substring(0, 1000)}${content.length > 1000 ? '...[TRONQUÉ]' : ''}
---

VALIDATION QUALITATIVE:
1. FLUIDITÉ: Le texte se lit-il naturellement?
2. CLARTÉ: Les idées sont-elles bien exprimées?
3. ENGAGEMENT: Le contenu est-il intéressant?
4. PROFESSIONNALISME: Niveau de qualité rédactionnelle?

RÉPONSE JSON STRICTE:
{
  "score": 75,
  "validation": "confirmed",
  "qualitativeAssessment": {
    "fluidity": 80,
    "clarity": 75,
    "engagement": 70,
    "professionalism": 85
  },
  "feedback": "Analyse qualitative en 2-3 phrases",
  "confidence": 0.9
}

SCORE: 0-100 (qualité globale perçue par un lecteur)`;

    const response = await LLMManager.callLLM('gpt-4o-mini', prompt, {
      temperature: 0.1,
      max_tokens: 300
    });
    
    try {
      let jsonStr = response.trim();
      const jsonMatch = jsonStr.match(/\{[\s\S]*\}/);
      if (jsonMatch) {
        jsonStr = jsonMatch[0];
      }
      
      const parsed = JSON.parse(jsonStr);
      
      return {
        score: Math.max(0, Math.min(100, parsed.score || 50)),
        validation: parsed.validation || 'partial',
        qualitative: parsed.qualitativeAssessment || {},
        feedback: parsed.feedback || 'Analyse non disponible',
        confidence: Math.max(0, Math.min(1, parsed.confidence || 0.5)),
        source: 'llm'
      };
      
    } catch (error) {
      console.warn('Erreur parsing réponse LLM qualité:', error.message);
      return {
        score: objectiveMetrics.overall, // Fallback sur score objectif
        feedback: `Erreur parsing: ${error.message}`,
        confidence: 0.1,
        source: 'fallback'
      };
    }
  }
  
  /**
   * 📚 MÉTRIQUES LISIBILITÉ - ALGORITHME FLESCH-KINCAID FRANÇAIS
   * 
   * CE QUI EST TESTÉ :
   * ✅ Comptage précis phrases, mots, syllabes avec regex françaises
   * ✅ Formule Flesch adaptée : 206.835 - (1.015 * mots/phrase) - (84.6 * syllabes/mot)
   * ✅ Normalisation [0,100] avec Math.max/Math.min
   * 
   * ALGORITHMES EXÉCUTÉS :
   * - Comptage phrases : split(/[.!?]+/) + filter longueur>0
   * - Comptage syllabes : regex voyelles françaises [aeiouyàâäéèêëïîôöùûü]
   * - Ajustements français : -1 si mot finit par 'e', corrections 'eau'/'oui'
   * - Score final arrondi Math.round()
   */
  static calculateReadability(content) {
    const sentences = this.countSentences(content);
    const words = this.countWords(content);
    const syllables = this.estimateSyllables(content);
    
    if (sentences === 0 || words === 0) return 0;
    
    // Adaptation française de Flesch-Kincaid
    const avgWordsPerSentence = words / sentences;
    const avgSyllablesPerWord = syllables / words;
    
    // Formule adaptée pour le français
    let readabilityScore = 206.835 - (1.015 * avgWordsPerSentence) - (84.6 * avgSyllablesPerWord);
    
    // Normalisation 0-100
    readabilityScore = Math.max(0, Math.min(100, readabilityScore));
    
    return Math.round(readabilityScore);
  }
  
  /**
   * 📝 RICHESSE VOCABULAIRE - ALGORITHME DE DIVERSITÉ LEXICALE
   * 
   * CE QUI EST TESTÉ :
   * ✅ Ratio mots uniques vs mots totaux (diversité lexicale)
   * ✅ Bonus longueur moyenne des mots (complexité vocabulaire)
   * ✅ Pénalité répétitions excessives (>3 occurrences)
   * 
   * ALGORITHMES EXÉCUTÉS :
   * - Calcul uniqueness = Set(words.lowercase).size / words.length
   * - Bonus longueur = Math.min((avgWordLength - 3) * 10, 20) // max 20pts
   * - Pénalité répétition = (count-3)*2 pour chaque mot>3 occurrences
   * - Score final = (uniqueness * 80) + bonus - penalty, clamp [0,100]
   */
  static calculateVocabularyRichness(content) {
    const words = this.getWords(content);
    const uniqueWords = new Set(words.map(w => w.toLowerCase()));
    
    if (words.length === 0) return 0;
    
    // Ratio mots uniques / mots totaux
    const uniquenessRatio = uniqueWords.size / words.length;
    
    // Bonus pour la longueur des mots
    const avgWordLength = words.reduce((sum, word) => sum + word.length, 0) / words.length;
    const lengthBonus = Math.min((avgWordLength - 3) * 10, 20); // Max 20 points bonus
    
    // Pénalité pour répétitions excessives
    const repetitionPenalty = this.calculateRepetitionPenalty(words);
    
    let richness = (uniquenessRatio * 80) + lengthBonus - repetitionPenalty;
    richness = Math.max(0, Math.min(100, richness));
    
    return Math.round(richness);
  }
  
  /**
   * 🏢 MÉTRIQUES STRUCTURE - ANALYSE ARCHITECTURE TEXTUELLE
   * 
   * CE QUI EST TESTÉ :
   * ✅ Présence et qualité des paragraphes (split \n\n)
   * ✅ Longueur optimale paragraphes [100-800 chars]
   * ✅ Détection listes/énumérations (bonus structure)
   * ✅ Variabilité longueur phrases (coefficient variation)
   * 
   * ALGORITHMES EXÉCUTÉS :
   * - Score base = 100, décrément selon défauts
   * - -20pts si <2 paragraphes, -15pts si >800 chars/parag, -10pts si <100
   * - +5pts si listes détectées : regex /[-•*]\s/ ou /\d+\.\s/
   * - +15pts max selon variation = écart-type(longueurs) / moyenne
   */
  static calculateStructureMetrics(content) {
    let score = 100;
    
    // Vérification paragraphes
    const paragraphs = content.split('\n\n').filter(p => p.trim().length > 0);
    if (paragraphs.length < 2) score -= 20;
    
    // Longueur des paragraphes
    const avgParagraphLength = paragraphs.reduce((sum, p) => sum + p.length, 0) / paragraphs.length;
    if (avgParagraphLength > 800) score -= 15; // Paragraphes trop longs
    if (avgParagraphLength < 100) score -= 10; // Paragraphes trop courts
    
    // Présence de listes ou énumérations
    const hasLists = /[-•*]\s/.test(content) || /\d+\.\s/.test(content);
    if (hasLists) score += 5;
    
    // Variété dans la longueur des phrases
    const sentences = this.getSentences(content);
    const sentenceLengthVariation = this.calculateVariation(sentences.map(s => s.length));
    score += Math.min(sentenceLengthVariation * 10, 15);
    
    return Math.max(0, Math.min(100, Math.round(score)));
  }
  
  /**
   * 🔗 MÉTRIQUES COHÉRENCE - ANALYSE CONNECTEURS LOGIQUES
   * 
   * CE QUI EST TESTÉ :
   * ✅ Détection 24 connecteurs français (donc, ainsi, cependant, etc.)
   * ✅ Calcul ratio connecteurs/phrases (optimum 0.2-0.4)
   * ✅ Scoring selon courbe : parfait à 0.2-0.4, dégradé en dehors
   * 
   * ALGORITHMES EXÉCUTÉS :
   * - Liste connecteurs = ['donc', 'ainsi', 'par conséquent', ...] (24 total)
   * - Comptage = words.filter(w => connectors.includes(w.toLowerCase()))
   * - Ratio = connectorCount / sentences.length
   * - Score : si [0.2,0.4]=100pts, si <0.2=50+(ratio*250), si >0.4=100-((ratio-0.4)*100)
   */
  static calculateCoherenceMetrics(content) {
    const words = this.getWords(content);
    const sentences = this.getSentences(content);
    
    if (sentences.length < 2) return 50;
    
    // Mots de liaison français
    const connectors = [
      'donc', 'ainsi', 'par conséquent', 'en effet', 'cependant', 'néanmoins',
      'toutefois', 'd\'ailleurs', 'en outre', 'de plus', 'également', 'aussi',
      'enfin', 'finalement', 'en conclusion', 'premièrement', 'deuxièmement',
      'mais', 'or', 'car', 'parce que', 'puisque', 'comme', 'si', 'bien que'
    ];
    
    // Comptage des connecteurs
    const connectorCount = words.filter(word => 
      connectors.includes(word.toLowerCase())
    ).length;
    
    const connectorRatio = connectorCount / sentences.length;
    
    // Score basé sur la densité de connecteurs (optimum autour de 0.2-0.4)
    let coherenceScore;
    if (connectorRatio >= 0.2 && connectorRatio <= 0.4) {
      coherenceScore = 100;
    } else if (connectorRatio < 0.2) {
      coherenceScore = 50 + (connectorRatio * 250); // Manque de connecteurs
    } else {
      coherenceScore = 100 - ((connectorRatio - 0.4) * 100); // Trop de connecteurs
    }
    
    return Math.max(0, Math.min(100, Math.round(coherenceScore)));
  }
  
  /**
   * 🔍 MÉTRIQUES SEO - ANALYSE OPTIMISATION MOTEURS RECHERCHE
   * 
   * CE QUI EST TESTÉ :
   * ✅ Longueur contenu optimale [300-2000 mots] selon standards SEO
   * ✅ Présence titres HTML ou Markdown (<h1-6> ou #)
   * ✅ Détection suroptimisation mots-clés (>5% = pénalité)
   * 
   * ALGORITHMES EXÉCUTÉS :
   * - Score base = 100, pénalités selon défauts
   * - Longueur : -30pts si <300 mots, -15pts si <500, -10pts si >2000
   * - Titres : -20pts si pas de regex /<h[1-6]>/ ni /^#{1,6}\s/
   * - Densité mots-clés : -15pts si estimateKeywordDensity() > 0.05
   */
  static calculateSEOMetrics(content) {
    let score = 100;
    
    // Longueur du contenu
    const wordCount = this.countWords(content);
    if (wordCount < 300) score -= 30;
    else if (wordCount < 500) score -= 15;
    else if (wordCount > 2000) score -= 10;
    
    // Présence de titres (simulation)
    const hasTitles = /<h[1-6]>/.test(content) || /^#{1,6}\s/.test(content);
    if (!hasTitles) score -= 20;
    
    // Densité des mots-clés (éviter la suroptimisation)
    const keywordDensity = this.estimateKeywordDensity(content);
    if (keywordDensity > 0.05) score -= 15; // Plus de 5% = suroptimisation
    
    return Math.max(0, Math.min(100, Math.round(score)));
  }
  
  /**
   * 🔢 COMPTAGE PHRASES - UTILITAIRE PARSING TEXTUEL
   * 
   * CE QUI EST TESTÉ :
   * ✅ Split sur ponctuations finales [.!?] avec support multiples
   * ✅ Filtrage phrases vides (trim().length > 0)
   * ✅ Comptage précis pour calculs lisibilité
   * 
   * ALGORITHME EXÉCUTÉ :
   * - Regex split : /[.!?]+/ pour gérer '...', '!!', '?!' etc.
   * - Filter : s => s.trim().length > 0 pour ignorer phrases vides
   * - Return count final pour ratios mots/phrases
   */
  static countSentences(content) {
    return content.split(/[.!?]+/).filter(s => s.trim().length > 0).length;
  }
  
  static countWords(content) {
    return this.getWords(content).length;
  }
  
  static getWords(content) {
    return content
      .toLowerCase()
      .replace(/[^\w\s-]/g, ' ')
      .split(/\s+/)
      .filter(word => word.length > 0);
  }
  
  static getSentences(content) {
    return content.split(/[.!?]+/).filter(s => s.trim().length > 0);
  }
  
  /**
   * 🗣️ ESTIMATION SYLLABES - ALGORITHME PHONÉTIQUE FRANÇAIS
   * 
   * CE QUI EST TESTÉ :
   * ✅ Comptage voyelles françaises avec accents complets
   * ✅ Ajustements linguistiques : -1 si finit par 'e', corrections diphtongues
   * ✅ Minimum 1 syllabe par mot (pas de mots à 0 syllabe)
   * 
   * ALGORITHMES EXÉCUTÉS :
   * - Regex voyelles = /[aeiouyàâäéèêëïîôöùûü]/gi
   * - Correction 'e' final : if (word.endsWith('e') && syllables>1) syllables--
   * - Correction diphtongues : if ('eau'||'oui') syllables--
   * - Math.max(1, syllables) pour éviter 0
   */
  static estimateSyllables(content) {
    const words = this.getWords(content);
    let totalSyllables = 0;
    
    words.forEach(word => {
      // Approximation simple pour le français
      let syllables = word.match(/[aeiouyàâäéèêëïîôöùûü]/gi);
      syllables = syllables ? syllables.length : 1;
      
      // Ajustements pour le français
      if (word.endsWith('e') && syllables > 1) syllables--;
      if (word.includes('eau') || word.includes('oui')) syllables--;
      
      totalSyllables += Math.max(1, syllables);
    });
    
    return totalSyllables;
  }
  
  /**
   * ⛔ CALCUL PÉNALITÉ RÉPÉTITIONS - DÉTECTEUR REDONDANCE
   * 
   * CE QUI EST TESTÉ :
   * ✅ Comptage fréquence mots significatifs (longueur>3)
   * ✅ Pénalité progressive : 2pts par occurrence au-delà de 3
   * ✅ Plafond max 30pts pour éviter pénalités excessives
   * 
   * ALGORITHMES EXÉCUTÉS :
   * - Filter mots : word.length > 3 pour ignorer articles/prépositions
   * - Map fréquences : wordCount[lower] = (wordCount[lower] || 0) + 1
   * - Pénalité = Σ((count-3)*2) pour chaque mot avec count>3
   * - Return Math.min(penalty, 30) pour plafonner
   */
  static calculateRepetitionPenalty(words) {
    const wordCount = {};
    words.forEach(word => {
      const lower = word.toLowerCase();
      if (lower.length > 3) { // Ignorer les mots trop courts
        wordCount[lower] = (wordCount[lower] || 0) + 1;
      }
    });
    
    let penalty = 0;
    Object.values(wordCount).forEach(count => {
      if (count > 3) {
        penalty += (count - 3) * 2; // 2 points de pénalité par répétition excessive
      }
    });
    
    return Math.min(penalty, 30); // Max 30 points de pénalité
  }
  
  /**
   * 📊 CALCUL VARIATION - COEFFICIENT DE VARIATION STATISTIQUE
   * 
   * CE QUI EST TESTÉ :
   * ✅ Calcul écart-type des longueurs de phrases
   * ✅ Coefficient variation = σ/μ (normalisation par moyenne)
   * ✅ Mesure diversité structurelle du texte
   * 
   * ALGORITHMES EXÉCUTÉS :
   * - Moyenne : avg = Σ(numbers) / numbers.length
   * - Variance : variance = Σ((n-avg)²) / length
   * - Écart-type : σ = Math.sqrt(variance)
   * - Coefficient : cv = σ/avg (variation relative)
   */
  static calculateVariation(numbers) {
    if (numbers.length < 2) return 0;
    
    const avg = numbers.reduce((sum, n) => sum + n, 0) / numbers.length;
    const variance = numbers.reduce((sum, n) => sum + Math.pow(n - avg, 2), 0) / numbers.length;
    
    return Math.sqrt(variance) / avg; // Coefficient de variation
  }
  
  /**
   * 🎯 ESTIMATION DENSITÉ MOTS-CLÉS - DÉTECTEUR SUROPTIMISATION
   * 
   * CE QUI EST TESTÉ :
   * ✅ Détection mot le plus répété (potentiel mot-clé)
   * ✅ Calcul ratio fréquence_max / total_mots
   * ✅ Seuil alerte >5% pour détecter suroptimisation SEO
   * 
   * ALGORITHMES EXÉCUTÉS :
   * - Filter mots significatifs : word.length > 4
   * - Comptage fréquences : wordFreq[word] = count
   * - Recherche maximum : Math.max(...Object.values(wordFreq))
   * - Densité = maxFreq / totalWords (ratio [0,1])
   */
  static estimateKeywordDensity(content) {
    const words = this.getWords(content);
    const totalWords = words.length;
    
    if (totalWords === 0) return 0;
    
    // Recherche de répétitions potentielles de mots-clés
    const wordFreq = {};
    words.forEach(word => {
      if (word.length > 4) { // Mots significatifs
        wordFreq[word] = (wordFreq[word] || 0) + 1;
      }
    });
    
    // Trouver le mot le plus répété (potentiel mot-clé)
    const maxFreq = Math.max(...Object.values(wordFreq));
    
    return maxFreq / totalWords;
  }
  
  /**
   * ⚡ ANALYSE RAPIDE DASHBOARD - PRESET PERFORMANCE OPTIMISÉ
   * 
   * CE QUI EST TESTÉ :
   * ✅ Calculs basiques sans appel LLM (temps <1 seconde)
   * ✅ Stats essentielles : mots, phrases, lisibilité, ratios
   * ✅ Classification lisibilité textuelle (Très facile à Très difficile)
   * 
   * ALGORITHMES EXÉCUTÉS :
   * - Comptages directs : countWords(), countSentences()
   * - Ratio : Math.round(words/sentences) pour moyenne
   * - Lisibilité : calculateReadability() + classification textuelle
   * - Structure optimisée pour affichage dashboard temps réel
   */
  static quickAnalysis(content) {
    const words = this.countWords(content);
    const sentences = this.countSentences(content);
    const readability = this.calculateReadability(content);
    
    return {
      wordCount: words,
      sentenceCount: sentences,
      avgWordsPerSentence: sentences > 0 ? Math.round(words / sentences) : 0,
      readabilityScore: readability,
      readabilityLevel: this.getReadabilityLevel(readability)
    };
  }
  
  /**
   * 📈 NIVEAU LISIBILITÉ TEXTUEL - CLASSIFICATEUR SEUILS
   * 
   * CE QUI EST TESTÉ :
   * ✅ Conversion score numérique [0-100] en niveau lisible humain
   * ✅ 7 niveaux définis selon standards éducatifs français
   * ✅ Seuils optimisés pour compréhension intuitive
   * 
   * ALGORITHME EXÉCUTÉ :
   * - Classification par seuils : ≥90='Très facile', ≥80='Facile', etc.
   * - Ordre décroissant : 90,80,70,60,50,30 puis 'Très difficile'
   * - Correspondance standards Flesch-Kincaid adaptés français
   */
  static getReadabilityLevel(score) {
    if (score >= 90) return 'Très facile';
    if (score >= 80) return 'Facile';
    if (score >= 70) return 'Assez facile';
    if (score >= 60) return 'Standard';
    if (score >= 50) return 'Assez difficile';
    if (score >= 30) return 'Difficile';
    return 'Très difficile';
  }
}

module.exports = { QualityMetrics };