// ========================================
// FICHIER: HumanSimulationCore.js
// RESPONSABILITÉ: Orchestrateur principal Human Simulation
// Niveau 5: Temporal & Personality Injection
// ========================================

const { logSh } = require('../ErrorReporting');
const { tracer } = require('../trace');
const { calculateFatigue, injectFatigueMarkers, getFatigueProfile } = require('./FatiguePatterns');
const { injectPersonalityErrors, getPersonalityErrorPatterns } = require('./PersonalityErrors');
const { applyTemporalStyle, getTemporalStyle } = require('./TemporalStyles');
const { HumanSimulationTracker } = require('./HumanSimulationTracker');
const { selectAndApplyErrors } = require('./error-profiles/ErrorSelector'); // ✅ NOUVEAU: Système erreurs graduées
const {
  analyzeContentComplexity,
  calculateReadabilityScore,
  preserveKeywords,
  validateSimulationQuality
} = require('./HumanSimulationUtils');

/**
 * CONFIGURATION PAR DÉFAUT
 * ⚠️ VALIDATION DÉSACTIVÉE - Imperfections volontaires acceptées
 */
const DEFAULT_CONFIG = {
  fatigueEnabled: true,
  personalityErrorsEnabled: true,
  temporalStyleEnabled: true,
  graduatedErrorsEnabled: true,     // ✅ NOUVEAU: Système erreurs graduées (grave/moyenne/légère)
  imperfectionIntensity: 0.5,
  naturalRepetitions: true,
  qualityThreshold: 0,              // ✅ VALIDATION DÉSACTIVÉE (threshold=0)
  maxModificationsPerElement: 3
};

/**
 * ORCHESTRATEUR PRINCIPAL - Human Simulation Layer
 * @param {object} content - Contenu généré à simuler
 * @param {object} options - Options de simulation
 * @returns {object} - { content, stats, fallback }
 */
async function applyHumanSimulationLayer(content, options = {}) {
  return await tracer.run('HumanSimulationCore.applyHumanSimulationLayer()', async () => {
    const startTime = Date.now();
    
    await tracer.annotate({
      contentKeys: Object.keys(content).length,
      elementIndex: options.elementIndex,
      totalElements: options.totalElements,
      currentHour: options.currentHour,
      personality: options.csvData?.personality?.nom
    });

    logSh(`🧠 HUMAN SIMULATION - Début traitement`, 'INFO');
    logSh(`   📊 ${Object.keys(content).length} éléments | Position: ${options.elementIndex}/${options.totalElements}`, 'DEBUG');

    try {
      // Configuration fusionnée
      const config = { ...DEFAULT_CONFIG, ...options };

      // ✅ INITIALISATION TRACKER ANTI-RÉPÉTITION
      const tracker = new HumanSimulationTracker();
      logSh(`🧠 Tracker anti-répétition initialisé`, 'DEBUG');

      // Stats de simulation
      const simulationStats = {
        elementsProcessed: 0,
        fatigueModifications: 0,
        personalityModifications: 0,
        temporalModifications: 0,
        spellingModifications: 0,
        totalModifications: 0,
        qualityScore: 0,
        fallbackUsed: false
      };

      // Contenu simulé
      let simulatedContent = { ...content };

      // ========================================
      // 1. ANALYSE CONTEXTE GLOBAL
      // ========================================
      const globalContext = await analyzeGlobalContext(content, config);
      logSh(`   🔍 Contexte: fatigue=${globalContext.fatigueLevel.toFixed(2)}, heure=${globalContext.currentHour}h, personnalité=${globalContext.personalityName}`, 'DEBUG');

      // ========================================
      // 2. TRAITEMENT PAR ÉLÉMENT
      // ========================================
      for (const [elementKey, elementContent] of Object.entries(content)) {
        await tracer.run(`HumanSimulation.processElement(${elementKey})`, async () => {
          
          logSh(`   🎯 Traitement élément: ${elementKey}`, 'DEBUG');
          
          let processedContent = elementContent;
          let elementModifications = 0;

          try {
            // 2a. Simulation Fatigue Cognitive
            if (config.fatigueEnabled && globalContext.fatigueLevel > 0.1) { // FIXÉ: Seuil plus bas (était 0.3)
              const fatigueResult = await applyFatigueSimulation(processedContent, globalContext, config);
              processedContent = fatigueResult.content;
              elementModifications += fatigueResult.modifications;
              simulationStats.fatigueModifications += fatigueResult.modifications;

              logSh(`     💤 Fatigue: ${fatigueResult.modifications} modifications (niveau: ${globalContext.fatigueLevel.toFixed(2)})`, 'DEBUG');
            }

            // 2b. Erreurs Personnalité
            if (config.personalityErrorsEnabled && globalContext.personalityProfile) {
              const personalityResult = await applyPersonalitySimulation(processedContent, globalContext, config, tracker);
              processedContent = personalityResult.content;
              elementModifications += personalityResult.modifications;
              simulationStats.personalityModifications += personalityResult.modifications;

              logSh(`     🎭 Personnalité: ${personalityResult.modifications} erreurs injectées`, 'DEBUG');
            }

            // 2c. Style Temporel
            if (config.temporalStyleEnabled && globalContext.temporalStyle) {
              const temporalResult = await applyTemporalSimulation(processedContent, globalContext, config, tracker);
              processedContent = temporalResult.content;
              elementModifications += temporalResult.modifications;
              simulationStats.temporalModifications += temporalResult.modifications;

              logSh(`     ⏰ Temporel: ${temporalResult.modifications} ajustements (${globalContext.temporalStyle.period})`, 'DEBUG');
            }

            // 2d. Erreurs Graduées Procédurales (NOUVEAU - grave 10% / moyenne 30% / légère 50%)
            if (config.graduatedErrorsEnabled) {
              const errorResult = selectAndApplyErrors(processedContent, {
                currentHour: globalContext.currentHour,
                tracker
              });
              processedContent = errorResult.content;
              elementModifications += errorResult.errorsApplied;
              simulationStats.graduatedErrors = (simulationStats.graduatedErrors || 0) + errorResult.errorsApplied;

              if (errorResult.errorsApplied > 0) {
                logSh(`     🎲 Erreurs graduées: ${errorResult.errorsApplied} (${errorResult.errorDetails.severity})`, 'DEBUG');
              }
            }

            // 2e. Validation Qualité
            const qualityCheck = validateSimulationQuality(elementContent, processedContent, config.qualityThreshold);
            
            if (qualityCheck.acceptable) {
              simulatedContent[elementKey] = processedContent;
              simulationStats.elementsProcessed++;
              simulationStats.totalModifications += elementModifications;
              
              logSh(`     ✅ Élément simulé: ${elementModifications} modifications totales`, 'DEBUG');
            } else {
              // Fallback: garder contenu original
              simulatedContent[elementKey] = elementContent;
              simulationStats.fallbackUsed = true;
              
              logSh(`     ⚠️ Qualité insuffisante, fallback vers contenu original`, 'WARNING');
            }

          } catch (elementError) {
            logSh(`     ❌ Erreur simulation élément ${elementKey}: ${elementError.message}`, 'WARNING');
            simulatedContent[elementKey] = elementContent; // Fallback
            simulationStats.fallbackUsed = true;
          }

        }, { elementKey, originalLength: elementContent?.length });
      }

      // ========================================
      // 3. CALCUL SCORE QUALITÉ GLOBAL
      // ========================================
      simulationStats.qualityScore = calculateGlobalQualityScore(content, simulatedContent);
      
      // ========================================
      // 4. RÉSULTATS FINAUX
      // ========================================
      const duration = Date.now() - startTime;
      const success = simulationStats.elementsProcessed > 0 && !simulationStats.fallbackUsed;

      logSh(`🧠 HUMAN SIMULATION - Terminé (${duration}ms)`, 'INFO');
      logSh(`   ✅ ${simulationStats.elementsProcessed}/${Object.keys(content).length} éléments simulés`, 'INFO');
      logSh(`   📊 ${simulationStats.fatigueModifications} fatigue | ${simulationStats.personalityModifications} personnalité | ${simulationStats.temporalModifications} temporel | ${simulationStats.spellingModifications || 0} fautes`, 'INFO');
      logSh(`   🎯 Score qualité: ${simulationStats.qualityScore.toFixed(2)} | Fallback: ${simulationStats.fallbackUsed ? 'OUI' : 'NON'}`, 'INFO');

      await tracer.event('Human Simulation terminée', {
        success,
        duration,
        stats: simulationStats
      });

      return {
        content: simulatedContent,
        stats: simulationStats,
        modifications: simulationStats.totalModifications,  // ✅ AJOUTÉ: Mapping pour PipelineExecutor
        fallback: simulationStats.fallbackUsed,
        qualityScore: simulationStats.qualityScore,
        duration
      };

    } catch (error) {
      const duration = Date.now() - startTime;
      logSh(`❌ HUMAN SIMULATION ÉCHOUÉE (${duration}ms): ${error.message}`, 'ERROR');
      
      await tracer.event('Human Simulation échouée', {
        error: error.message,
        duration,
        contentKeys: Object.keys(content).length
      });

      // Fallback complet
      return {
        content,
        stats: { fallbackUsed: true, error: error.message },
        fallback: true,
        qualityScore: 0,
        duration
      };
    }

  }, { 
    contentElements: Object.keys(content).length,
    elementIndex: options.elementIndex,
    personality: options.csvData?.personality?.nom 
  });
}

/**
 * ANALYSE CONTEXTE GLOBAL
 */
async function analyzeGlobalContext(content, config) {
  const elementIndex = config.elementIndex || 0;
  const totalElements = config.totalElements || Object.keys(content).length;
  const currentHour = config.currentHour || new Date().getHours();
  const personality = config.csvData?.personality;

  return {
    fatigueLevel: calculateFatigue(elementIndex, totalElements),
    fatigueProfile: personality ? getFatigueProfile(personality.nom) : null,
    personalityName: personality?.nom || 'unknown',
    personalityProfile: personality ? getPersonalityErrorPatterns(personality.nom) : null,
    temporalStyle: getTemporalStyle(currentHour),
    currentHour,
    elementIndex,
    totalElements,
    contentComplexity: analyzeContentComplexity(content)
  };
}

/**
 * APPLICATION SIMULATION FATIGUE
 */
async function applyFatigueSimulation(content, globalContext, config) {
  const fatigueResult = injectFatigueMarkers(content, globalContext.fatigueLevel, {
    profile: globalContext.fatigueProfile,
    intensity: config.imperfectionIntensity
  });

  return {
    content: fatigueResult.content,
    modifications: fatigueResult.modifications || 0
  };
}

/**
 * APPLICATION SIMULATION PERSONNALITÉ
 */
async function applyPersonalitySimulation(content, globalContext, config, tracker) {
  const personalityResult = injectPersonalityErrors(
    content,
    globalContext.personalityProfile,
    config.imperfectionIntensity,
    tracker
  );

  return {
    content: personalityResult.content,
    modifications: personalityResult.modifications || 0
  };
}

/**
 * APPLICATION SIMULATION TEMPORELLE
 */
async function applyTemporalSimulation(content, globalContext, config, tracker) {
  const temporalResult = applyTemporalStyle(content, globalContext.temporalStyle, {
    intensity: config.imperfectionIntensity,
    tracker
  });

  return {
    content: temporalResult.content,
    modifications: temporalResult.modifications || 0
  };
}


/**
 * CALCUL SCORE QUALITÉ GLOBAL
 */
function calculateGlobalQualityScore(originalContent, simulatedContent) {
  let totalScore = 0;
  let elementCount = 0;

  for (const [key, original] of Object.entries(originalContent)) {
    const simulated = simulatedContent[key];
    if (simulated) {
      const elementScore = calculateReadabilityScore(simulated) * 0.7 + 
                          preserveKeywords(original, simulated) * 0.3;
      totalScore += elementScore;
      elementCount++;
    }
  }

  return elementCount > 0 ? totalScore / elementCount : 0;
}

// ============= EXPORTS =============
module.exports = {
  applyHumanSimulationLayer,
  analyzeGlobalContext,
  applyFatigueSimulation,
  applyPersonalitySimulation,
  applyTemporalSimulation,
  calculateGlobalQualityScore,
  DEFAULT_CONFIG
};