// ========================================
// TECHNICAL LAYER - COUCHE TECHNIQUE MODULAIRE
// Responsabilité: Amélioration technique modulaire réutilisable
// LLM: GPT-4o-mini (précision technique optimale)
// ========================================

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

/**
 * COUCHE TECHNIQUE MODULAIRE
 */
class TechnicalLayer {
  constructor() {
    this.name = 'TechnicalEnhancement';
    this.defaultLLM = 'gpt-4o-mini';
    this.priority = 1; // Haute priorité - appliqué en premier généralement
  }

  /**
   * MAIN METHOD - Appliquer amélioration technique
   */
  async apply(content, config = {}) {
    return await tracer.run('TechnicalLayer.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,
        targetTerms = null        // Termes techniques ciblés
      } = config;

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

      const startTime = Date.now();
      logSh(`⚙️ TECHNICAL LAYER: Amélioration technique (${llmProvider})`, 'INFO');
      logSh(`   📊 ${Object.keys(content).length} éléments | Intensité: ${intensity}`, 'INFO');

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

        if (analysisMode) {
          // 1. Analyser éléments nécessitant amélioration technique
          const analysis = await this.analyzeTechnicalNeeds(content, csvData, targetTerms);
          
          logSh(`   📋 Analyse: ${analysis.candidates.length}/${Object.keys(content).length} éléments candidats`, 'DEBUG');
          
          if (analysis.candidates.length === 0) {
            logSh(`✅ TECHNICAL LAYER: Aucune amélioration nécessaire`, '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.enhanceTechnicalElements(
            analysis.candidates, 
            csvData, 
            { llmProvider, intensity, preserveStructure }
          );

          // 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
          enhancedContent = await this.enhanceAllElementsDirect(
            content, 
            csvData, 
            { llmProvider, intensity, preserveStructure }
          );
          
          elementsProcessed = Object.keys(content).length;
          elementsEnhanced = this.countDifferences(content, enhancedContent);
        }

        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
        };

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

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

        return { content: enhancedContent, stats };

      } catch (error) {
        const duration = Date.now() - startTime;
        logSh(`❌ TECHNICAL LAYER ÉCHOUÉE après ${duration}ms: ${error.message}`, 'ERROR');
        throw error;
      }
    }, { content: Object.keys(content), config });
  }

  /**
   * ANALYSER BESOINS TECHNIQUES
   */
  async analyzeTechnicalNeeds(content, csvData, targetTerms = null) {
    logSh(`🔍 Analyse besoins techniques`, 'DEBUG');
    
    const analysis = {
      candidates: [],
      technicalTermsFound: [],
      missingTerms: [],
      globalScore: 0
    };

    // Définir termes techniques selon contexte
    const contextualTerms = this.getContextualTechnicalTerms(csvData?.mc0, targetTerms);
    
    // Analyser chaque élément
    Object.entries(content).forEach(([tag, text]) => {
      const elementAnalysis = this.analyzeTechnicalElement(text, contextualTerms, csvData);
      
      if (elementAnalysis.needsImprovement) {
        analysis.candidates.push({
          tag,
          content: text,
          technicalTerms: elementAnalysis.foundTerms,
          missingTerms: elementAnalysis.missingTerms,
          score: elementAnalysis.score,
          improvements: elementAnalysis.improvements
        });
        
        analysis.globalScore += elementAnalysis.score;
      }
      
      analysis.technicalTermsFound.push(...elementAnalysis.foundTerms);
    });

    analysis.globalScore = analysis.globalScore / Math.max(Object.keys(content).length, 1);
    analysis.technicalTermsFound = [...new Set(analysis.technicalTermsFound)];
    
    logSh(`   📊 Score global technique: ${analysis.globalScore.toFixed(2)}`, 'DEBUG');
    
    return analysis;
  }

  /**
   * AMÉLIORER ÉLÉMENTS TECHNIQUES SÉLECTIONNÉS
   */
  async enhanceTechnicalElements(candidates, csvData, config) {
    logSh(`🛠️ Amélioration ${candidates.length} éléments techniques`, 'DEBUG');
    logSh(`🔍 Candidates reçus: ${JSON.stringify(candidates.map(c => c.tag))}`, 'DEBUG');
    
    const results = {};
    const chunks = chunkArray(candidates, 4); // Chunks de 4 pour GPT-4
    
    for (let chunkIndex = 0; chunkIndex < chunks.length; chunkIndex++) {
      const chunk = chunks[chunkIndex];
      
      try {
        logSh(`   📦 Chunk technique ${chunkIndex + 1}/${chunks.length}: ${chunk.length} éléments`, 'DEBUG');
        
        const enhancementPrompt = this.createTechnicalEnhancementPrompt(chunk, csvData, config);
        
        const response = await callLLM(config.llmProvider, enhancementPrompt, {
          temperature: 0.4, // Précision technique
          maxTokens: 3000
        }, csvData?.personality);
        
        const chunkResults = this.parseTechnicalResponse(response, chunk);
        Object.assign(results, chunkResults);
        
        logSh(`   ✅ Chunk technique ${chunkIndex + 1}: ${Object.keys(chunkResults).length} améliorés`, 'DEBUG');
        
        // Délai entre chunks
        if (chunkIndex < chunks.length - 1) {
          await sleep(1500);
        }
        
      } catch (error) {
        logSh(`   ❌ Chunk technique ${chunkIndex + 1} échoué: ${error.message}`, 'ERROR');
        
        // Fallback: conserver contenu original
        chunk.forEach(element => {
          results[element.tag] = element.content;
        });
      }
    }
    
    return results;
  }

  /**
   * AMÉLIORER TOUS ÉLÉMENTS MODE DIRECT
   */
  async enhanceAllElementsDirect(content, csvData, config) {
    const allElements = Object.entries(content).map(([tag, text]) => ({
      tag,
      content: text,
      technicalTerms: [],
      improvements: ['amélioration_générale_technique'],
      missingTerms: []  // Ajout de la propriété manquante
    }));
    
    return await this.enhanceTechnicalElements(allElements, csvData, config);
  }

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

  /**
   * Analyser élément technique individuel
   */
  analyzeTechnicalElement(text, contextualTerms, csvData) {
    let score = 0;
    const foundTerms = [];
    const missingTerms = [];
    const improvements = [];
    
    // 1. Détecter termes techniques présents
    contextualTerms.forEach(term => {
      if (text.toLowerCase().includes(term.toLowerCase())) {
        foundTerms.push(term);
      } else if (text.length > 100) { // Seulement pour textes longs
        missingTerms.push(term);
      }
    });
    
    // 2. Évaluer manque de précision technique
    if (foundTerms.length === 0 && text.length > 80) {
      score += 0.4;
      improvements.push('ajout_termes_techniques');
    }
    
    // 3. Détecter vocabulaire trop générique
    const genericWords = ['produit', 'solution', 'service', 'offre', 'article'];
    const genericCount = genericWords.filter(word => 
      text.toLowerCase().includes(word)
    ).length;
    
    if (genericCount > 1) {
      score += 0.3;
      improvements.push('spécialisation_vocabulaire');
    }
    
    // 4. Manque de données techniques (dimensions, etc.)
    if (text.length > 50 && !(/\d+\s*(mm|cm|m|%|°|kg|g)/.test(text))) {
      score += 0.2;
      improvements.push('ajout_données_techniques');
    }
    
    // 5. Contexte métier spécifique
    if (csvData?.mc0 && !text.toLowerCase().includes(csvData.mc0.toLowerCase().split(' ')[0])) {
      score += 0.1;
      improvements.push('intégration_contexte_métier');
    }
    
    return {
      needsImprovement: score > 0.3,
      score,
      foundTerms,
      missingTerms: missingTerms.slice(0, 3), // Limiter à 3 termes manquants
      improvements
    };
  }

  /**
   * Obtenir termes techniques contextuels
   */
  getContextualTechnicalTerms(mc0, targetTerms) {
    // Termes de base signalétique
    const baseTerms = [
      'dibond', 'aluminium', 'PMMA', 'acrylique', 'plexiglas',
      'impression', 'gravure', 'découpe', 'fraisage', 'perçage',
      'adhésif', 'fixation', 'visserie', 'support'
    ];
    
    // Termes spécifiques selon contexte
    const contextualTerms = [];
    
    if (mc0) {
      const mc0Lower = mc0.toLowerCase();
      
      if (mc0Lower.includes('plaque')) {
        contextualTerms.push('épaisseur 3mm', 'format standard', 'finition brossée', 'anodisation');
      }
      
      if (mc0Lower.includes('signalétique')) {
        contextualTerms.push('norme ISO', 'pictogramme', 'contraste visuel', 'lisibilité');
      }
      
      if (mc0Lower.includes('personnalisée')) {
        contextualTerms.push('découpe forme', 'impression numérique', 'quadrichromie', 'pantone');
      }
    }
    
    // Ajouter termes ciblés si fournis
    if (targetTerms && Array.isArray(targetTerms)) {
      contextualTerms.push(...targetTerms);
    }
    
    return [...baseTerms, ...contextualTerms];
  }

  /**
   * Créer prompt amélioration technique
   */
  createTechnicalEnhancementPrompt(chunk, csvData, config) {
    const personality = csvData?.personality;

    let prompt = `MISSION: Améliore UNIQUEMENT la précision technique de ces contenus.

CONTEXTE: ${csvData?.mc0 || 'Signalétique personnalisée'} - Secteur: impression/signalétique
${personality ? `PERSONNALITÉ: ${personality.nom} (${personality.style})` : ''}
INTENSITÉ: ${config.intensity} (0.5=léger, 1.0=standard, 1.5=intensif)

ÉLÉMENTS À AMÉLIORER TECHNIQUEMENT:

${chunk.map((item, i) => `[${i + 1}] "${item.content}"
AMÉLIORATIONS SUGGÉRÉES: ${item.improvements.join(', ')}
${item.missingTerms.length > 0 ? `TERMES UTILES (à intégrer si pertinent): ${item.missingTerms.join(', ')}` : ''}`).join('\n\n')}

CONSIGNES TECHNIQUES:
- GARDE exactement le même message et ton${personality ? ` ${personality.style}` : ''}
- AJOUTE précision technique NATURELLE sans sur-techniciser
- INTÈGRE termes métier SEULEMENT si utiles au lecteur: matériaux, dimensions, normes
- RESTE ACCESSIBLE au grand public - privilégie clarté sur technicité excessive
- ÉVITE absolument le jargon pompeux ("plaque numérologique domestique" → "numéro de maison")
- PRESERVE longueur approximative (±15%)
- JAMAIS de répétitions de paragraphes entiers

RÈGLES VOCABULAIRE TECHNIQUE:
- ✅ BON: "plaque en aluminium 3mm" → clair et précis
- ❌ MAUVAIS: "support métallique en alliage d'aluminium anodisé de calibre 3mm" → pompeux
- ✅ BON: "impression UV haute qualité" → informatif
- ❌ MAUVAIS: "procédé d'impression par rayonnement ultraviolet avec encres polymériques" → trop technique
- ✅ BON: Mentionner 1-2 détails techniques utiles par paragraphe
- ❌ MAUVAIS: Bombarder chaque phrase de termes techniques

VOCABULAIRE TECHNIQUE AUTORISÉ (utiliser avec modération):
- Matériaux basiques: dibond, aluminium, PVC, acrylique
- Procédés simples: impression UV, gravure laser, découpe numérique
- Dimensions standards: 3mm, 30x20cm, format A4
- ÉVITER: PMMA coulé, fraisage CNC, anodisation, spécifications ISO (sauf si vraiment pertinent)

FORMAT RÉPONSE:
[1] Contenu amélioré avec précision technique modérée
[2] Contenu amélioré avec précision technique modérée
etc...

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

    return prompt;
  }

  /**
   * Parser réponse technique
   */
  parseTechnicalResponse(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 technicalContent = match[2].trim();
      const element = chunk[index];
      
      // Nettoyer contenu technique
      technicalContent = this.cleanTechnicalContent(technicalContent);
      
      if (technicalContent && technicalContent.length > 10) {
        results[element.tag] = technicalContent;
        logSh(`✅ Amélioré technique [${element.tag}]: "${technicalContent.substring(0, 60)}..."`, 'DEBUG');
      } else {
        results[element.tag] = element.content; // Fallback
        logSh(`⚠️ Fallback technique [${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 technique généré
   */
  cleanTechnicalContent(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, '');

    // Supprimer préfixes indésirables
    content = content.replace(/^(voici\s+)?le\s+contenu\s+amélioré\s*[:.]?\s*/gi, '');
    content = content.replace(/^(avec\s+)?amélioration\s+technique\s*[:.]?\s*/gi, '');
    content = content.replace(/^(bon,?\s*)?(alors,?\s*)?pour\s+/gi, '');

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

    return content;
  }

  /**
   * Compter différences entre contenus
   */
  countDifferences(original, enhanced) {
    let count = 0;
    
    Object.keys(original).forEach(tag => {
      if (enhanced[tag] && enhanced[tag] !== original[tag]) {
        count++;
      }
    });
    
    return count;
  }
}

module.exports = { TechnicalLayer };