// ========================================
// ADVERSARIAL LAYERS - COUCHES MODULAIRES
// Responsabilité: Couches adversariales composables et réutilisables
// Architecture: Fonction pipeline |> layer1 |> layer2 |> layer3
// ========================================

const { logSh } = require('../ErrorReporting');
const { tracer } = require('../trace');
const { applyAdversarialLayer } = require('./AdversarialCore');

/**
 * COUCHE ANTI-GPTZEERO - Spécialisée contre GPTZero
 */
async function applyAntiGPTZeroLayer(content, options = {}) {
  return await applyAdversarialLayer(content, {
    detectorTarget: 'gptZero',
    intensity: options.intensity || 1.0,
    method: options.method || 'regeneration',
    ...options
  });
}

/**
 * COUCHE ANTI-ORIGINALITY - Spécialisée contre Originality.ai
 */
async function applyAntiOriginalityLayer(content, options = {}) {
  return await applyAdversarialLayer(content, {
    detectorTarget: 'originality',
    intensity: options.intensity || 1.1,
    method: options.method || 'hybrid',
    ...options
  });
}

/**
 * COUCHE ANTI-WINSTON - Spécialisée contre Winston AI
 */
async function applyAntiWinstonLayer(content, options = {}) {
  return await applyAdversarialLayer(content, {
    detectorTarget: 'winston',
    intensity: options.intensity || 0.9,
    method: options.method || 'enhancement',
    ...options
  });
}

/**
 * COUCHE GÉNÉRALE - Protection généraliste multi-détecteurs
 */
async function applyGeneralAdversarialLayer(content, options = {}) {
  return await applyAdversarialLayer(content, {
    detectorTarget: 'general',
    intensity: options.intensity || 0.8,
    method: options.method || 'hybrid',
    ...options
  });
}

/**
 * COUCHE LÉGÈRE - Modifications subtiles pour préserver qualité
 */
async function applyLightAdversarialLayer(content, options = {}) {
  return await applyAdversarialLayer(content, {
    detectorTarget: options.detectorTarget || 'general',
    intensity: 0.5,
    method: 'enhancement',
    preserveStructure: true,
    ...options
  });
}

/**
 * COUCHE INTENSIVE - Maximum anti-détection
 */
async function applyIntensiveAdversarialLayer(content, options = {}) {
  return await applyAdversarialLayer(content, {
    detectorTarget: options.detectorTarget || 'gptZero',
    intensity: 1.5,
    method: 'regeneration',
    preserveStructure: false,
    ...options
  });
}

/**
 * PIPELINE COMPOSABLE - Application séquentielle de couches
 */
async function applyLayerPipeline(content, layers = [], globalOptions = {}) {
  return await tracer.run('AdversarialLayers.applyLayerPipeline()', async () => {
    await tracer.annotate({
      layersPipeline: true,
      layersCount: layers.length,
      elementsCount: Object.keys(content).length
    });

    const startTime = Date.now();
    logSh(`🔄 PIPELINE COUCHES ADVERSARIALES: ${layers.length} couches`, 'INFO');

    let currentContent = content;
    const pipelineStats = {
      layers: [],
      totalDuration: 0,
      totalModifications: 0,
      success: true
    };

    try {
      for (let i = 0; i < layers.length; i++) {
        const layer = layers[i];
        const layerStartTime = Date.now();
        
        logSh(`   🎯 Couche ${i + 1}/${layers.length}: ${layer.name || layer.type || 'anonyme'}`, 'DEBUG');
        
        try {
          const layerResult = await applyLayerByConfig(currentContent, layer, globalOptions);
          
          currentContent = layerResult.content;
          
          const layerStats = {
            name: layer.name || `layer_${i + 1}`,
            type: layer.type,
            duration: Date.now() - layerStartTime,
            modificationsCount: layerResult.stats?.elementsModified || 0,
            success: true
          };
          
          pipelineStats.layers.push(layerStats);
          pipelineStats.totalModifications += layerStats.modificationsCount;
          
          logSh(`   ✅ ${layerStats.name}: ${layerStats.modificationsCount} modifs (${layerStats.duration}ms)`, 'DEBUG');
          
        } catch (error) {
          logSh(`   ❌ Couche ${i + 1} échouée: ${error.message}`, 'ERROR');
          
          pipelineStats.layers.push({
            name: layer.name || `layer_${i + 1}`,
            type: layer.type,
            duration: Date.now() - layerStartTime,
            success: false,
            error: error.message
          });
          
          // Continuer avec le contenu précédent si une couche échoue
          if (!globalOptions.stopOnError) {
            continue;
          } else {
            throw error;
          }
        }
      }

      pipelineStats.totalDuration = Date.now() - startTime;
      pipelineStats.success = pipelineStats.layers.every(layer => layer.success);

      logSh(`🔄 PIPELINE TERMINÉ: ${pipelineStats.totalModifications} modifs totales (${pipelineStats.totalDuration}ms)`, 'INFO');

      await tracer.event('Pipeline couches terminé', pipelineStats);

      return {
        content: currentContent,
        stats: pipelineStats,
        modifications: pipelineStats.totalModifications,  // ✅ AJOUTÉ: Mapping pour PipelineExecutor
        original: content
      };

    } catch (error) {
      pipelineStats.totalDuration = Date.now() - startTime;
      pipelineStats.success = false;
      
      logSh(`❌ PIPELINE COUCHES ÉCHOUÉ après ${pipelineStats.totalDuration}ms: ${error.message}`, 'ERROR');
      throw error;
    }
  }, { layers: layers.map(l => l.name || l.type), content: Object.keys(content) });
}

/**
 * COUCHES PRÉDÉFINIES - Configurations courantes
 */
const PREDEFINED_LAYERS = {
  // Stack défensif léger
  lightDefense: [
    { type: 'general', name: 'General Light', intensity: 0.6, method: 'enhancement' },
    { type: 'anti-gptZero', name: 'GPTZero Light', intensity: 0.5, method: 'enhancement' }
  ],
  
  // Stack défensif standard
  standardDefense: [
    { type: 'general', name: 'General Standard', intensity: 0.8, method: 'hybrid' },
    { type: 'anti-gptZero', name: 'GPTZero Standard', intensity: 0.9, method: 'enhancement' },
    { type: 'anti-originality', name: 'Originality Standard', intensity: 0.8, method: 'enhancement' }
  ],
  
  // Stack défensif intensif
  heavyDefense: [
    { type: 'general', name: 'General Heavy', intensity: 1.0, method: 'regeneration' },
    { type: 'anti-gptZero', name: 'GPTZero Heavy', intensity: 1.2, method: 'regeneration' },
    { type: 'anti-originality', name: 'Originality Heavy', intensity: 1.1, method: 'hybrid' },
    { type: 'anti-winston', name: 'Winston Heavy', intensity: 1.0, method: 'enhancement' }
  ],
  
  // Stack ciblé GPTZero
  gptZeroFocused: [
    { type: 'anti-gptZero', name: 'GPTZero Primary', intensity: 1.3, method: 'regeneration' },
    { type: 'general', name: 'General Support', intensity: 0.7, method: 'enhancement' }
  ],
  
  // Stack ciblé Originality
  originalityFocused: [
    { type: 'anti-originality', name: 'Originality Primary', intensity: 1.4, method: 'hybrid' },
    { type: 'general', name: 'General Support', intensity: 0.8, method: 'enhancement' }
  ]
};

/**
 * APPLIQUER STACK PRÉDÉFINI
 */
async function applyPredefinedStack(content, stackName, options = {}) {
  const stack = PREDEFINED_LAYERS[stackName];
  
  if (!stack) {
    throw new Error(`Stack prédéfini inconnu: ${stackName}. Disponibles: ${Object.keys(PREDEFINED_LAYERS).join(', ')}`);
  }
  
  logSh(`📦 APPLICATION STACK PRÉDÉFINI: ${stackName}`, 'INFO');
  
  return await applyLayerPipeline(content, stack, options);
}

/**
 * COUCHES ADAPTATIVES - S'adaptent selon le contenu
 */
async function applyAdaptiveLayers(content, options = {}) {
  const { 
    targetDetectors = ['gptZero', 'originality'],
    maxIntensity = 1.0,
    analysisMode = true 
  } = options;

  logSh(`🧠 COUCHES ADAPTATIVES: Analyse + adaptation auto`, 'INFO');

  // 1. Analyser le contenu pour détecter les risques
  const contentAnalysis = analyzeContentRisks(content);
  
  // 2. Construire pipeline adaptatif selon l'analyse
  const adaptiveLayers = [];
  
  // Niveau de base selon risque global
  const baseIntensity = Math.min(maxIntensity, contentAnalysis.globalRisk * 1.2);
  
  if (baseIntensity > 0.3) {
    adaptiveLayers.push({
      type: 'general',
      name: 'Adaptive Base',
      intensity: baseIntensity,
      method: baseIntensity > 0.7 ? 'hybrid' : 'enhancement'
    });
  }
  
  // Couches spécifiques selon détecteurs ciblés
  targetDetectors.forEach(detector => {
    const detectorRisk = contentAnalysis.detectorRisks[detector] || 0;
    
    if (detectorRisk > 0.4) {
      const intensity = Math.min(maxIntensity * 1.1, detectorRisk * 1.5);
      adaptiveLayers.push({
        type: `anti-${detector}`,
        name: `Adaptive ${detector}`,
        intensity,
        method: intensity > 0.8 ? 'regeneration' : 'enhancement'
      });
    }
  });
  
  logSh(`   🎯 ${adaptiveLayers.length} couches adaptatives générées`, 'DEBUG');
  
  if (adaptiveLayers.length === 0) {
    logSh(`   ✅ Contenu déjà optimal, aucune couche nécessaire`, 'INFO');
    return { content, stats: { adaptive: true, layersApplied: 0 }, original: content };
  }
  
  return await applyLayerPipeline(content, adaptiveLayers, options);
}

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

/**
 * Appliquer couche selon configuration
 */
async function applyLayerByConfig(content, layerConfig, globalOptions = {}) {
  const { type, intensity, method, ...layerOptions } = layerConfig;

  // ✅ FIX: Ne override que si la valeur est explicitement définie (pas undefined/null)
  const options = {
    ...globalOptions,
    ...layerOptions
  };

  // Override intensity seulement si défini dans layerConfig
  if (intensity !== undefined && intensity !== null) {
    options.intensity = intensity;
  }

  // Override method seulement si défini dans layerConfig
  if (method !== undefined && method !== null) {
    options.method = method;
  }

  switch (type) {
    case 'general':
      return await applyGeneralAdversarialLayer(content, options);
    case 'anti-gptZero':
      return await applyAntiGPTZeroLayer(content, options);
    case 'anti-originality':
      return await applyAntiOriginalityLayer(content, options);
    case 'anti-winston':
      return await applyAntiWinstonLayer(content, options);
    case 'light':
      return await applyLightAdversarialLayer(content, options);
    case 'intensive':
      return await applyIntensiveAdversarialLayer(content, options);
    default:
      throw new Error(`Type de couche inconnu: ${type}`);
  }
}

/**
 * Analyser risques du contenu pour adaptation
 */
function analyzeContentRisks(content) {
  const analysis = {
    globalRisk: 0,
    detectorRisks: {},
    riskFactors: []
  };
  
  const allContent = Object.values(content).join(' ');
  
  // Risques génériques
  let riskScore = 0;
  
  // 1. Mots typiques IA
  const aiWords = ['optimal', 'comprehensive', 'seamless', 'robust', 'leverage', 'cutting-edge', 'furthermore', 'moreover'];
  const aiWordCount = aiWords.filter(word => allContent.toLowerCase().includes(word)).length;
  
  if (aiWordCount > 2) {
    riskScore += 0.3;
    analysis.riskFactors.push(`mots_ia: ${aiWordCount}`);
  }
  
  // 2. Structure uniforme
  const contentLengths = Object.values(content).map(c => c.length);
  const avgLength = contentLengths.reduce((a, b) => a + b, 0) / contentLengths.length;
  const variance = contentLengths.reduce((sum, len) => sum + Math.pow(len - avgLength, 2), 0) / contentLengths.length;
  const uniformity = 1 - (Math.sqrt(variance) / Math.max(avgLength, 1));
  
  if (uniformity > 0.8) {
    riskScore += 0.2;
    analysis.riskFactors.push(`uniformité: ${uniformity.toFixed(2)}`);
  }
  
  // 3. Connecteurs répétitifs
  const repetitiveConnectors = ['par ailleurs', 'en effet', 'de plus', 'cependant'];
  const connectorCount = repetitiveConnectors.filter(conn => 
    (allContent.match(new RegExp(conn, 'gi')) || []).length > 1
  ).length;
  
  if (connectorCount > 2) {
    riskScore += 0.2;
    analysis.riskFactors.push(`connecteurs_répétitifs: ${connectorCount}`);
  }
  
  analysis.globalRisk = Math.min(1, riskScore);
  
  // Risques spécifiques par détecteur
  analysis.detectorRisks = {
    gptZero: analysis.globalRisk + (uniformity > 0.7 ? 0.3 : 0),
    originality: analysis.globalRisk + (aiWordCount > 3 ? 0.4 : 0),
    winston: analysis.globalRisk + (connectorCount > 2 ? 0.2 : 0)
  };
  
  return analysis;
}

/**
 * Obtenir informations sur les stacks disponibles
 */
function getAvailableStacks() {
  return Object.keys(PREDEFINED_LAYERS).map(stackName => ({
    name: stackName,
    layersCount: PREDEFINED_LAYERS[stackName].length,
    description: getStackDescription(stackName),
    layers: PREDEFINED_LAYERS[stackName]
  }));
}

/**
 * Description des stacks prédéfinis
 */
function getStackDescription(stackName) {
  const descriptions = {
    lightDefense: 'Protection légère préservant la qualité',
    standardDefense: 'Protection équilibrée multi-détecteurs',
    heavyDefense: 'Protection maximale tous détecteurs',
    gptZeroFocused: 'Optimisation spécifique anti-GPTZero',
    originalityFocused: 'Optimisation spécifique anti-Originality.ai'
  };
  
  return descriptions[stackName] || 'Stack personnalisé';
}

module.exports = {
  // Couches individuelles
  applyAntiGPTZeroLayer,
  applyAntiOriginalityLayer,
  applyAntiWinstonLayer,
  applyGeneralAdversarialLayer,
  applyLightAdversarialLayer,
  applyIntensiveAdversarialLayer,
  
  // Pipeline et stacks
  applyLayerPipeline,              // ← MAIN ENTRY POINT PIPELINE
  applyPredefinedStack,            // ← MAIN ENTRY POINT STACKS
  applyAdaptiveLayers,             // ← MAIN ENTRY POINT ADAPTATIF
  
  // Utilitaires
  getAvailableStacks,
  analyzeContentRisks,
  PREDEFINED_LAYERS
};