// ========================================
// FICHIER: ManualServer.js
// RESPONSABILITÉ: Mode MANUAL - Interface Client + API + WebSocket
// FONCTIONNALITÉS: Dashboard, tests modulaires, API complète
// ========================================

// ⏱️ Timing chargement modules (logs avant/après chaque require)
const _t0 = Date.now();
console.log(`[${new Date().toISOString()}] ⏱️ [require] Début chargement ManualServer modules...`);

const _t1 = Date.now();
const express = require('express');
console.log(`[${new Date().toISOString()}] ✓ [require] express en ${Date.now() - _t1}ms`);

const _t2 = Date.now();
const cors = require('cors');
console.log(`[${new Date().toISOString()}] ✓ [require] cors en ${Date.now() - _t2}ms`);

const _t3 = Date.now();
const path = require('path');
console.log(`[${new Date().toISOString()}] ✓ [require] path en ${Date.now() - _t3}ms`);

const _t4 = Date.now();
const WebSocket = require('ws');
console.log(`[${new Date().toISOString()}] ✓ [require] ws (WebSocket) en ${Date.now() - _t4}ms`);

const _t5 = Date.now();
const { logSh } = require('../ErrorReporting');
console.log(`[${new Date().toISOString()}] ✓ [require] ErrorReporting en ${Date.now() - _t5}ms`);

const _t6 = Date.now();
const { handleModularWorkflow, benchmarkStacks } = require('../Main');
console.log(`[${new Date().toISOString()}] ✓ [require] Main en ${Date.now() - _t6}ms`);

const _t7 = Date.now();
const { APIController } = require('../APIController');
console.log(`[${new Date().toISOString()}] ✓ [require] APIController en ${Date.now() - _t7}ms`);

const _t8 = Date.now();
const { BatchController } = require('../batch/BatchController');
console.log(`[${new Date().toISOString()}] ✓ [require] BatchController en ${Date.now() - _t8}ms`);

console.log(`[${new Date().toISOString()}] ✅ [require] TOTAL ManualServer modules chargés en ${Date.now() - _t0}ms`);

/**
 * SERVEUR MODE MANUAL
 * Interface client complète avec API, WebSocket et dashboard
 */
class ManualServer {
  
  constructor(options = {}) {
    this.config = {
      port: options.port || process.env.MANUAL_PORT || 3000,
      wsPort: options.wsPort || process.env.WS_PORT || 8081,
      host: options.host || '0.0.0.0',
      ...options
    };
    
    this.app = null;
    this.server = null;
    this.wsServer = null;
    this.activeClients = new Set();
    this.stats = {
      sessions: 0,
      requests: 0,
      testsExecuted: 0,
      startTime: Date.now(),
      lastActivity: null
    };

    this.isRunning = false;
    this.apiController = new APIController();
    this.batchController = new BatchController();

    // Cache pour status LLMs (évite d'appeler trop souvent)
    this.llmStatusCache = null;
    this.llmStatusCacheTime = null;
  }

  // ========================================
  // DÉMARRAGE ET ARRÊT
  // ========================================
  
  /**
   * Démarre le serveur MANUAL complet
   */
  async start() {
    if (this.isRunning) {
      logSh('⚠️ ManualServer déjà en cours d\'exécution', 'WARNING');
      return;
    }

    const startTime = Date.now();
    logSh('🎯 Démarrage ManualServer...', 'INFO');

    try {
      // 1. Configuration Express
      logSh('⏱️ [1/7] Configuration Express...', 'INFO');
      const t1 = Date.now();
      await this.setupExpressApp();
      logSh(`✓ Express configuré en ${Date.now() - t1}ms`, 'INFO');

      // 2. Routes API
      logSh('⏱️ [2/7] Configuration routes API...', 'INFO');
      const t2 = Date.now();
      this.setupAPIRoutes();
      logSh(`✓ Routes API configurées en ${Date.now() - t2}ms`, 'INFO');

      // 3. Interface Web
      logSh('⏱️ [3/7] Configuration interface web...', 'INFO');
      const t3 = Date.now();
      this.setupWebInterface();
      logSh(`✓ Interface web configurée en ${Date.now() - t3}ms`, 'INFO');

      // 4. WebSocket pour logs temps réel
      logSh('⏱️ [4/7] Démarrage WebSocket serveur...', 'INFO');
      const t4 = Date.now();
      await this.setupWebSocketServer();

      // ✅ PHASE 3: Injecter WebSocket server dans APIController
      if (this.wsServer) {
        this.apiController.setWebSocketServer(this.wsServer);
      }

      logSh(`✓ WebSocket démarré en ${Date.now() - t4}ms`, 'INFO');

      // 5. Démarrage serveur HTTP
      logSh('⏱️ [5/7] Démarrage serveur HTTP...', 'INFO');
      const t5 = Date.now();
      await this.startHTTPServer();
      logSh(`✓ Serveur HTTP démarré en ${Date.now() - t5}ms`, 'INFO');

      // 6. Monitoring
      logSh('⏱️ [6/7] Démarrage monitoring...', 'INFO');
      const t6 = Date.now();
      this.startMonitoring();
      logSh(`✓ Monitoring démarré en ${Date.now() - t6}ms`, 'INFO');

      // 7. Initialisation status LLMs au démarrage (en background)
      logSh('⏱️ [7/7] Initialisation LLM status (background)...', 'INFO');
      const t7 = Date.now();
      this.initializeLLMStatus();
      logSh(`✓ LLM init lancé en ${Date.now() - t7}ms`, 'INFO');

      this.isRunning = true;
      this.stats.startTime = Date.now();

      logSh(`✅ ManualServer démarré sur http://localhost:${this.config.port} (total: ${Date.now() - startTime}ms)`, 'INFO');
      logSh(`📡 WebSocket logs sur ws://localhost:${this.config.wsPort}`, 'INFO');
      
    } catch (error) {
      logSh(`❌ Erreur démarrage ManualServer: ${error.message}`, 'ERROR');
      await this.stop();
      throw error;
    }
  }

  /**
   * Arrête le serveur MANUAL
   */
  async stop() {
    if (!this.isRunning) return;

    logSh('🛑 Arrêt ManualServer...', 'INFO');

    try {
      // Arrêter le monitoring
      if (this.monitorInterval) {
        clearInterval(this.monitorInterval);
        this.monitorInterval = null;
      }

      // Arrêter le refresh status LLMs
      if (this.llmStatusInterval) {
        clearInterval(this.llmStatusInterval);
        this.llmStatusInterval = null;
      }

      // Déconnecter tous les clients WebSocket
      this.disconnectAllClients();

      // Arrêter WebSocket server
      if (this.wsServer) {
        this.wsServer.close();
        this.wsServer = null;
      }

      // Arrêter serveur HTTP
      if (this.server) {
        await new Promise((resolve) => {
          this.server.close(() => resolve());
        });
        this.server = null;
      }

      this.isRunning = false;

      logSh('✅ ManualServer arrêté', 'INFO');

    } catch (error) {
      logSh(`⚠️ Erreur arrêt ManualServer: ${error.message}`, 'WARNING');
    }
  }

  // ========================================
  // CONFIGURATION EXPRESS
  // ========================================
  
  /**
   * Configure l'application Express
   */
  async setupExpressApp() {
    this.app = express();
    
    // Middleware de base
    this.app.use(express.json({ limit: '10mb' }));
    this.app.use(express.urlencoded({ extended: true }));
    this.app.use(cors());
    
    // Middleware de logs des requêtes
    this.app.use((req, res, next) => {
      this.stats.requests++;
      this.stats.lastActivity = Date.now();
      
      logSh(`📥 ${req.method} ${req.path} - ${req.ip}`, 'TRACE');
      next();
    });
    
    // Fichiers statiques
    this.app.use(express.static(path.join(__dirname, '../../public')));
    
    // Route spécifique pour l'interface step-by-step
    this.app.get('/step-by-step', (req, res) => {
      res.sendFile(path.join(__dirname, '../../public/step-by-step.html'));
    });
    
    logSh('⚙️ Express configuré', 'DEBUG');
  }

  /**
   * Configure les routes API
   */
  setupAPIRoutes() {
    // Route de status
    this.app.get('/api/status', (req, res) => {
      res.json({
        success: true,
        mode: 'MANUAL',
        status: 'running',
        uptime: Date.now() - this.stats.startTime,
        stats: { ...this.stats },
        clients: this.activeClients.size,
        timestamp: new Date().toISOString()
      });
    });

    // Test modulaire individuel
    this.app.post('/api/test-modulaire', async (req, res) => {
      await this.handleTestModulaire(req, res);
    });

    // 🆕 Workflow modulaire avec sauvegarde par étapes
    this.app.post('/api/workflow-modulaire', async (req, res) => {
      await this.handleWorkflowModulaire(req, res);
    });

    // Benchmark modulaire complet
    this.app.post('/api/benchmark-modulaire', async (req, res) => {
      await this.handleBenchmarkModulaire(req, res);
    });

    // Configuration modulaire disponible
    this.app.get('/api/modulaire-config', (req, res) => {
      this.handleModulaireConfig(req, res);
    });

    // Stats détaillées
    this.app.get('/api/stats', (req, res) => {
      res.json({
        success: true,
        stats: {
          ...this.stats,
          uptime: Date.now() - this.stats.startTime,
          activeClients: this.activeClients.size,
          memory: process.memoryUsage(),
          timestamp: new Date().toISOString()
        }
      });
    });

    // Lancer le log viewer avec WebSocket
    this.app.post('/api/start-log-viewer', (req, res) => {
      this.handleStartLogViewer(req, res);
    });

    // ========================================
    // APIs STEP-BY-STEP
    // ========================================
    
    // Initialiser une session step-by-step
    this.app.post('/api/step-by-step/init', async (req, res) => {
      await this.handleStepByStepInit(req, res);
    });
    
    // Exécuter une étape
    this.app.post('/api/step-by-step/execute', async (req, res) => {
      await this.handleStepByStepExecute(req, res);
    });
    
    // Status d'une session
    this.app.get('/api/step-by-step/status/:sessionId', (req, res) => {
      this.handleStepByStepStatus(req, res);
    });
    
    // Reset une session
    this.app.post('/api/step-by-step/reset', (req, res) => {
      this.handleStepByStepReset(req, res);
    });
    
    // Export résultats
    this.app.get('/api/step-by-step/export/:sessionId', (req, res) => {
      this.handleStepByStepExport(req, res);
    });
    
    // Liste des sessions actives
    this.app.get('/api/step-by-step/sessions', (req, res) => {
      this.handleStepByStepSessions(req, res);
    });
    
    // API pour récupérer les personnalités
    this.app.get('/api/personalities', async (req, res) => {
      await this.handleGetPersonalities(req, res);
    });

    // 🆕 API simple pour générer un article avec mot-clé
    this.app.post('/api/generate-simple', async (req, res) => {
      await this.handleGenerateSimple(req, res);
    });

    // ========================================
    // ENDPOINTS GESTION CONFIGURATIONS
    // ========================================

    // Sauvegarder une configuration
    this.app.post('/api/config/save', async (req, res) => {
      try {
        const { name, config } = req.body;

        if (!name || !config) {
          return res.status(400).json({
            success: false,
            error: 'Nom et configuration requis'
          });
        }

        const { ConfigManager } = require('../ConfigManager');
        const configManager = new ConfigManager();

        const result = await configManager.saveConfig(name, config);

        res.json({
          success: true,
          message: `Configuration "${name}" sauvegardée`,
          savedName: result.name
        });

      } catch (error) {
        logSh(`❌ Erreur save config: ${error.message}`, 'ERROR');
        res.status(500).json({
          success: false,
          error: error.message
        });
      }
    });

    // Lister les configurations
    this.app.get('/api/config/list', async (req, res) => {
      try {
        const { ConfigManager } = require('../ConfigManager');
        const configManager = new ConfigManager();

        const configs = await configManager.listConfigs();

        res.json({
          success: true,
          configs,
          count: configs.length
        });

      } catch (error) {
        logSh(`❌ Erreur list configs: ${error.message}`, 'ERROR');
        res.status(500).json({
          success: false,
          error: error.message
        });
      }
    });

    // Charger une configuration
    this.app.get('/api/config/:name', async (req, res) => {
      try {
        const { name } = req.params;

        const { ConfigManager } = require('../ConfigManager');
        const configManager = new ConfigManager();

        const configData = await configManager.loadConfig(name);

        res.json({
          success: true,
          config: configData
        });

      } catch (error) {
        logSh(`❌ Erreur load config: ${error.message}`, 'ERROR');
        res.status(404).json({
          success: false,
          error: error.message
        });
      }
    });

    // Supprimer une configuration
    this.app.delete('/api/config/:name', async (req, res) => {
      try {
        const { name } = req.params;

        const { ConfigManager } = require('../ConfigManager');
        const configManager = new ConfigManager();

        await configManager.deleteConfig(name);

        res.json({
          success: true,
          message: `Configuration "${name}" supprimée`
        });

      } catch (error) {
        logSh(`❌ Erreur delete config: ${error.message}`, 'ERROR');
        res.status(500).json({
          success: false,
          error: error.message
        });
      }
    });

    // ========================================
    // ENDPOINTS PIPELINE MANAGEMENT
    // ========================================

    // Sauvegarder un pipeline
    this.app.post('/api/pipeline/save', async (req, res) => {
      try {
        const { pipelineDefinition } = req.body;

        if (!pipelineDefinition) {
          return res.status(400).json({
            success: false,
            error: 'pipelineDefinition requis'
          });
        }

        const { ConfigManager } = require('../ConfigManager');
        const configManager = new ConfigManager();

        const result = await configManager.savePipeline(pipelineDefinition);

        res.json({
          success: true,
          message: `Pipeline "${pipelineDefinition.name}" sauvegardé`,
          savedName: result.name
        });

      } catch (error) {
        logSh(`❌ Erreur save pipeline: ${error.message}`, 'ERROR');
        res.status(500).json({
          success: false,
          error: error.message
        });
      }
    });

    // Lister les pipelines
    this.app.get('/api/pipeline/list', async (req, res) => {
      try {
        const { ConfigManager } = require('../ConfigManager');
        const configManager = new ConfigManager();

        const pipelines = await configManager.listPipelines();

        res.json({
          success: true,
          pipelines,
          count: pipelines.length
        });

      } catch (error) {
        logSh(`❌ Erreur list pipelines: ${error.message}`, 'ERROR');
        res.status(500).json({
          success: false,
          error: error.message
        });
      }
    });

    // Obtenir modules disponibles (AVANT :name pour éviter conflit)
    this.app.get('/api/pipeline/modules', async (req, res) => {
      try {
        const { PipelineDefinition, AVAILABLE_LLM_PROVIDERS } = require('../pipeline/PipelineDefinition');

        const modules = PipelineDefinition.listModules();

        res.json({
          success: true,
          modules,
          llmProviders: AVAILABLE_LLM_PROVIDERS
        });

      } catch (error) {
        logSh(`❌ Erreur get modules: ${error.message}`, 'ERROR');
        res.status(500).json({
          success: false,
          error: error.message
        });
      }
    });

    // Obtenir templates prédéfinis (AVANT :name pour éviter conflit)
    this.app.get('/api/pipeline/templates', async (req, res) => {
      try {
        const { listTemplates, getCategories } = require('../pipeline/PipelineTemplates');

        const templates = listTemplates();
        const categories = getCategories();

        res.json({
          success: true,
          templates,
          categories
        });

      } catch (error) {
        logSh(`❌ Erreur get templates: ${error.message}`, 'ERROR');
        res.status(500).json({
          success: false,
          error: error.message
        });
      }
    });

    // Obtenir template par nom (AVANT :name pour éviter conflit)
    this.app.get('/api/pipeline/templates/:name', async (req, res) => {
      try {
        const { name } = req.params;
        const { getTemplate } = require('../pipeline/PipelineTemplates');

        const template = getTemplate(name);

        if (!template) {
          return res.status(404).json({
            success: false,
            error: `Template "${name}" non trouvé`
          });
        }

        res.json({
          success: true,
          template
        });

      } catch (error) {
        logSh(`❌ Erreur get template: ${error.message}`, 'ERROR');
        res.status(500).json({
          success: false,
          error: error.message
        });
      }
    });

    // Charger un pipeline (Route paramétrée APRÈS les routes spécifiques)
    this.app.get('/api/pipeline/:name', async (req, res) => {
      try {
        const { name } = req.params;

        const { ConfigManager } = require('../ConfigManager');
        const configManager = new ConfigManager();

        const pipeline = await configManager.loadPipeline(name);

        res.json({
          success: true,
          pipeline
        });

      } catch (error) {
        logSh(`❌ Erreur load pipeline: ${error.message}`, 'ERROR');
        res.status(404).json({
          success: false,
          error: error.message
        });
      }
    });

    // Supprimer un pipeline
    this.app.delete('/api/pipeline/:name', async (req, res) => {
      try {
        const { name } = req.params;

        const { ConfigManager } = require('../ConfigManager');
        const configManager = new ConfigManager();

        await configManager.deletePipeline(name);

        res.json({
          success: true,
          message: `Pipeline "${name}" supprimé`
        });

      } catch (error) {
        logSh(`❌ Erreur delete pipeline: ${error.message}`, 'ERROR');
        res.status(500).json({
          success: false,
          error: error.message
        });
      }
    });

    // Exécuter un pipeline
    this.app.post('/api/pipeline/execute', async (req, res) => {
      try {
        const { pipelineConfig, rowNumber, options = {} } = req.body;

        if (!pipelineConfig) {
          return res.status(400).json({
            success: false,
            error: 'pipelineConfig requis'
          });
        }

        if (!rowNumber || rowNumber < 2) {
          return res.status(400).json({
            success: false,
            error: 'rowNumber requis (minimum 2)'
          });
        }

        logSh(`🚀 Exécution pipeline: ${pipelineConfig.name} (row ${rowNumber})`, 'INFO');
        if (options.saveIntermediateSteps) {
          logSh(`   💾 Sauvegarde étapes intermédiaires ACTIVÉE`, 'INFO');
        }

        const { handleFullWorkflow } = require('../Main');

        const result = await handleFullWorkflow({
          pipelineConfig,
          rowNumber,
          options,  // ✅ Transmettre les options au workflow
          source: 'pipeline_api'
        });

        res.json({
          success: true,
          result: {
            finalContent: result.finalContent,
            executionLog: result.executionLog,
            versionHistory: result.versionHistory,  // ✅ Inclure version history
            stats: result.stats
          }
        });

      } catch (error) {
        logSh(`❌ Erreur execute pipeline: ${error.message}`, 'ERROR');
        res.status(500).json({
          success: false,
          error: error.message
        });
      }
    });

    // Valider un pipeline
    this.app.post('/api/pipeline/validate', async (req, res) => {
      try {
        const { pipelineDefinition } = req.body;

        if (!pipelineDefinition) {
          return res.status(400).json({
            success: false,
            error: 'pipelineDefinition requis'
          });
        }

        const { PipelineDefinition } = require('../pipeline/PipelineDefinition');

        const validation = PipelineDefinition.validate(pipelineDefinition);

        res.json({
          success: validation.valid,
          valid: validation.valid,
          errors: validation.errors
        });

      } catch (error) {
        logSh(`❌ Erreur validate pipeline: ${error.message}`, 'ERROR');
        res.status(500).json({
          success: false,
          error: error.message
        });
      }
    });

    // Estimer durée/coût d'un pipeline
    this.app.post('/api/pipeline/estimate', async (req, res) => {
      try {
        const { pipelineDefinition } = req.body;

        if (!pipelineDefinition) {
          return res.status(400).json({
            success: false,
            error: 'pipelineDefinition requis'
          });
        }

        const { PipelineDefinition } = require('../pipeline/PipelineDefinition');

        const summary = PipelineDefinition.getSummary(pipelineDefinition);
        const duration = PipelineDefinition.estimateDuration(pipelineDefinition);

        res.json({
          success: true,
          estimate: {
            totalSteps: summary.totalSteps,
            summary: summary.summary,
            estimatedDuration: duration.formatted,
            estimatedSeconds: duration.seconds
          }
        });

      } catch (error) {
        logSh(`❌ Erreur estimate pipeline: ${error.message}`, 'ERROR');
        res.status(500).json({
          success: false,
          error: error.message
        });
      }
    });

    // ========================================
    // ENDPOINT PRODUCTION RUN
    // ========================================

    this.app.post('/api/production-run', async (req, res) => {
      try {
        const {
          rowNumber,
          selectiveStack,
          adversarialMode,
          humanSimulationMode,
          patternBreakingMode,
          saveIntermediateSteps = true
        } = req.body;

        if (!rowNumber) {
          return res.status(400).json({
            success: false,
            error: 'rowNumber requis'
          });
        }

        logSh(`🚀 PRODUCTION RUN: Row ${rowNumber}`, 'INFO');

        // Appel handleFullWorkflow depuis Main.js
        const { handleFullWorkflow } = require('../Main');

        const result = await handleFullWorkflow({
          rowNumber,
          selectiveStack: selectiveStack || 'standardEnhancement',
          adversarialMode: adversarialMode || 'light',
          humanSimulationMode: humanSimulationMode || 'none',
          patternBreakingMode: patternBreakingMode || 'none',
          saveIntermediateSteps,
          source: 'production_web'
        });

        res.json({
          success: true,
          result: {
            wordCount: result.compiledWordCount,
            duration: result.totalDuration,
            llmUsed: result.llmUsed,
            cost: result.estimatedCost,
            slug: result.slug,
            gsheetsLink: `https://docs.google.com/spreadsheets/d/${process.env.GOOGLE_SHEETS_ID}`
          }
        });

      } catch (error) {
        logSh(`❌ Erreur production run: ${error.message}`, 'ERROR');
        res.status(500).json({
          success: false,
          error: error.message
        });
      }
    });

    // ========================================
    // 🚀 NOUVEAUX ENDPOINTS API RESTful
    // ========================================

    // === GESTION ARTICLES ===
    this.app.get('/api/articles', async (req, res) => {
      await this.apiController.getArticles(req, res);
    });

    this.app.get('/api/articles/:id', async (req, res) => {
      await this.apiController.getArticle(req, res);
    });

    this.app.post('/api/articles', async (req, res) => {
      await this.apiController.createArticle(req, res);
    });

    // ========================================
    // 🎯 BATCH PROCESSING API ENDPOINTS
    // ========================================

    // Configuration batch
    this.app.get('/api/batch/config', async (req, res) => {
      await this.batchController.getConfig(req, res);
    });

    this.app.post('/api/batch/config', async (req, res) => {
      await this.batchController.saveConfig(req, res);
    });

    // Contrôle traitement batch
    this.app.post('/api/batch/start', async (req, res) => {
      await this.batchController.startBatch(req, res);
    });

    this.app.post('/api/batch/stop', async (req, res) => {
      await this.batchController.stopBatch(req, res);
    });

    this.app.post('/api/batch/pause', async (req, res) => {
      await this.batchController.pauseBatch(req, res);
    });

    this.app.post('/api/batch/resume', async (req, res) => {
      await this.batchController.resumeBatch(req, res);
    });

    // Monitoring batch
    this.app.get('/api/batch/status', async (req, res) => {
      await this.batchController.getStatus(req, res);
    });

    this.app.get('/api/batch/progress', async (req, res) => {
      await this.batchController.getProgress(req, res);
    });

    // Templates Digital Ocean
    this.app.get('/api/batch/templates', async (req, res) => {
      await this.batchController.getTemplates(req, res);
    });

    this.app.get('/api/batch/templates/:filename', async (req, res) => {
      await this.batchController.getTemplate(req, res);
    });

    this.app.delete('/api/batch/cache', async (req, res) => {
      await this.batchController.clearCache(req, res);
    });

    // === GESTION PROJETS ===
    this.app.get('/api/projects', async (req, res) => {
      await this.apiController.getProjects(req, res);
    });

    this.app.post('/api/projects', async (req, res) => {
      await this.apiController.createProject(req, res);
    });

    // === GESTION TEMPLATES ===
    this.app.get('/api/templates', async (req, res) => {
      await this.apiController.getTemplates(req, res);
    });

    this.app.post('/api/templates', async (req, res) => {
      await this.apiController.createTemplate(req, res);
    });

    // === CONFIGURATION ===
    this.app.get('/api/config/personalities', async (req, res) => {
      await this.apiController.getPersonalitiesConfig(req, res);
    });

    // === MONITORING ===
    this.app.get('/api/health', async (req, res) => {
      await this.apiController.getHealth(req, res);
    });

    this.app.get('/api/metrics', async (req, res) => {
      await this.apiController.getMetrics(req, res);
    });

    // === LLM MONITORING API ===
    this.app.get('/api/llm/status', async (req, res) => {
      await this.handleLLMStatus(req, res);
    });

    // === PROMPT ENGINE API ===
    this.app.post('/api/generate-prompt', async (req, res) => {
      await this.apiController.generatePrompt(req, res);
    });
    this.app.get('/api/trends', async (req, res) => {
      await this.apiController.getTrends(req, res);
    });
    this.app.post('/api/trends/:trendId', async (req, res) => {
      await this.apiController.setTrend(req, res);
    });
    this.app.get('/api/prompt-engine/status', async (req, res) => {
      await this.apiController.getPromptEngineStatus(req, res);
    });

    // === WORKFLOW CONFIGURATION API ===
    this.app.get('/api/workflow/sequences', async (req, res) => {
      await this.apiController.getWorkflowSequences(req, res);
    });
    this.app.post('/api/workflow/sequences', async (req, res) => {
      await this.apiController.createWorkflowSequence(req, res);
    });
    this.app.post('/api/workflow/execute', async (req, res) => {
      await this.apiController.executeConfigurableWorkflow(req, res);
    });

    // === VALIDATION API (PHASE 3) ===
    this.app.post('/api/validation/start', async (req, res) => {
      await this.apiController.startValidation(req, res);
    });
    this.app.get('/api/validation/status/:id', async (req, res) => {
      await this.apiController.getValidationStatus(req, res);
    });
    this.app.post('/api/validation/stop/:id', async (req, res) => {
      await this.apiController.stopValidation(req, res);
    });
    this.app.get('/api/validation/list', async (req, res) => {
      await this.apiController.listValidations(req, res);
    });
    this.app.get('/api/validation/:id/report', async (req, res) => {
      await this.apiController.getValidationReport(req, res);
    });
    this.app.get('/api/validation/:id/evaluations', async (req, res) => {
      await this.apiController.getValidationEvaluations(req, res);
    });
    // ✅ NOUVEAU: Presets validation
    this.app.get('/api/validation/presets', async (req, res) => {
      await this.apiController.getValidationPresets(req, res);
    });

    // Gestion d'erreurs API
    this.app.use('/api/*', (error, req, res, next) => {
      logSh(`❌ Erreur API ${req.path}: ${error.message}`, 'ERROR');
      res.status(500).json({
        success: false,
        error: 'Erreur serveur interne',
        message: error.message,
        timestamp: new Date().toISOString()
      });
    });

    logSh('🛠️ Routes API configurées', 'DEBUG');
  }

  // ========================================
  // HANDLERS API
  // ========================================
  
  /**
   * Gère les tests modulaires individuels
   */
  async handleTestModulaire(req, res) {
    try {
      const config = req.body;
      this.stats.testsExecuted++;
      
      logSh(`🧪 Test modulaire: ${config.selectiveStack} + ${config.adversarialMode} + ${config.humanSimulationMode} + ${config.patternBreakingMode}`, 'INFO');
      
      // Validation des paramètres
      if (!config.rowNumber || config.rowNumber < 2) {
        return res.status(400).json({
          success: false,
          error: 'Numéro de ligne invalide (minimum 2)'
        });
      }

      // Exécution du test
      const result = await handleModularWorkflow({
        ...config,
        source: 'manual_server_api'
      });
      
      logSh(`✅ Test modulaire terminé: ${result.stats.totalDuration}ms`, 'INFO');
      
      res.json({
        success: true,
        message: 'Test modulaire terminé avec succès',
        stats: result.stats,
        config: config,
        timestamp: new Date().toISOString()
      });
      
    } catch (error) {
      logSh(`❌ Erreur test modulaire: ${error.message}`, 'ERROR');
      res.status(500).json({
        success: false,
        error: error.message,
        config: req.body,
        timestamp: new Date().toISOString()
      });
    }
  }

  /**
   * Gère les benchmarks modulaires
   */
  async handleBenchmarkModulaire(req, res) {
    try {
      const { rowNumber = 2 } = req.body;
      
      logSh(`📊 Benchmark modulaire ligne ${rowNumber}...`, 'INFO');
      
      if (rowNumber < 2) {
        return res.status(400).json({
          success: false,
          error: 'Numéro de ligne invalide (minimum 2)'
        });
      }

      const benchResults = await benchmarkStacks(rowNumber);
      
      const successfulTests = benchResults.filter(r => r.success);
      const avgDuration = successfulTests.length > 0 ? 
        successfulTests.reduce((sum, r) => sum + r.duration, 0) / successfulTests.length : 0;
      
      this.stats.testsExecuted += benchResults.length;
      
      logSh(`📊 Benchmark terminé: ${successfulTests.length}/${benchResults.length} tests réussis`, 'INFO');
      
      res.json({
        success: true,
        message: `Benchmark terminé: ${successfulTests.length}/${benchResults.length} tests réussis`,
        summary: {
          totalTests: benchResults.length,
          successfulTests: successfulTests.length,
          failedTests: benchResults.length - successfulTests.length,
          averageDuration: Math.round(avgDuration),
          rowNumber: rowNumber
        },
        results: benchResults,
        timestamp: new Date().toISOString()
      });
      
    } catch (error) {
      logSh(`❌ Erreur benchmark modulaire: ${error.message}`, 'ERROR');
      res.status(500).json({
        success: false,
        error: error.message,
        timestamp: new Date().toISOString()
      });
    }
  }

  /**
   * 🆕 Gère les workflows modulaires avec sauvegarde par étapes
   */
  async handleWorkflowModulaire(req, res) {
    try {
      const config = req.body;
      this.stats.testsExecuted++;
      
      // Configuration par défaut avec sauvegarde activée
      const workflowConfig = {
        rowNumber: config.rowNumber || 2,
        selectiveStack: config.selectiveStack || 'standardEnhancement',
        adversarialMode: config.adversarialMode || 'light',
        humanSimulationMode: config.humanSimulationMode || 'none',
        patternBreakingMode: config.patternBreakingMode || 'none',
        saveIntermediateSteps: config.saveIntermediateSteps !== false, // Par défaut true
        source: 'api_manual_server'
      };
      
      logSh(`🔗 Workflow modulaire avec étapes: ligne ${workflowConfig.rowNumber}`, 'INFO');
      logSh(`   📋 Config: ${workflowConfig.selectiveStack} + ${workflowConfig.adversarialMode} + ${workflowConfig.humanSimulationMode} + ${workflowConfig.patternBreakingMode}`, 'DEBUG');
      logSh(`   💾 Sauvegarde étapes: ${workflowConfig.saveIntermediateSteps ? 'ACTIVÉE' : 'DÉSACTIVÉE'}`, 'INFO');
      
      // Validation des paramètres
      if (workflowConfig.rowNumber < 2) {
        return res.status(400).json({
          success: false,
          error: 'Numéro de ligne invalide (minimum 2)'
        });
      }

      // Exécution du workflow complet
      const startTime = Date.now();
      const result = await handleModularWorkflow(workflowConfig);
      const duration = Date.now() - startTime;
      
      // Statistiques finales
      const finalStats = {
        duration,
        success: result.success,
        versionsCreated: result.stats?.versionHistory?.length || 1,
        parentArticleId: result.stats?.parentArticleId,
        finalArticleId: result.storageResult?.articleId,
        totalModifications: {
          selective: result.stats?.selectiveEnhancements || 0,
          adversarial: result.stats?.adversarialModifications || 0,
          human: result.stats?.humanSimulationModifications || 0,
          pattern: result.stats?.patternBreakingModifications || 0
        },
        finalLength: result.stats?.finalLength || 0
      };
      
      logSh(`✅ Workflow modulaire terminé: ${finalStats.versionsCreated} versions créées en ${duration}ms`, 'INFO');
      
      res.json({
        success: true,
        message: `Workflow modulaire terminé avec succès (${finalStats.versionsCreated} versions sauvegardées)`,
        config: workflowConfig,
        stats: finalStats,
        versionHistory: result.stats?.versionHistory,
        result: {
          parentArticleId: finalStats.parentArticleId,
          finalArticleId: finalStats.finalArticleId,
          duration: finalStats.duration,
          modificationsCount: Object.values(finalStats.totalModifications).reduce((sum, val) => sum + val, 0),
          finalWordCount: result.storageResult?.wordCount,
          personality: result.stats?.personality
        },
        timestamp: new Date().toISOString()
      });
      
    } catch (error) {
      logSh(`❌ Erreur workflow modulaire: ${error.message}`, 'ERROR');
      res.status(500).json({
        success: false,
        error: error.message,
        timestamp: new Date().toISOString()
      });
    }
  }

  /**
   * Retourne la configuration modulaire
   */
  handleModulaireConfig(req, res) {
    try {
      const config = {
        selectiveStacks: [
          { value: 'lightEnhancement', name: 'Light Enhancement', description: 'Améliorations légères' },
          { value: 'standardEnhancement', name: 'Standard Enhancement', description: 'Améliorations standard' },
          { value: 'fullEnhancement', name: 'Full Enhancement', description: 'Améliorations complètes' },
          { value: 'personalityFocus', name: 'Personality Focus', description: 'Focus personnalité' },
          { value: 'fluidityFocus', name: 'Fluidity Focus', description: 'Focus fluidité' },
          { value: 'adaptive', name: 'Adaptive', description: 'Adaptation automatique' }
        ],
        adversarialModes: [
          { value: 'none', name: 'None', description: 'Aucune technique adversariale' },
          { value: 'light', name: 'Light', description: 'Techniques adversariales légères' },
          { value: 'standard', name: 'Standard', description: 'Techniques adversariales standard' },
          { value: 'heavy', name: 'Heavy', description: 'Techniques adversariales intensives' },
          { value: 'adaptive', name: 'Adaptive', description: 'Adaptation automatique' }
        ],
        humanSimulationModes: [
          { value: 'none', name: 'None', description: 'Aucune simulation humaine' },
          { value: 'lightSimulation', name: 'Light Simulation', description: 'Simulation légère' },
          { value: 'standardSimulation', name: 'Standard Simulation', description: 'Simulation standard' },
          { value: 'heavySimulation', name: 'Heavy Simulation', description: 'Simulation intensive' },
          { value: 'adaptiveSimulation', name: 'Adaptive Simulation', description: 'Simulation adaptative' },
          { value: 'personalityFocus', name: 'Personality Focus', description: 'Focus personnalité' },
          { value: 'temporalFocus', name: 'Temporal Focus', description: 'Focus temporel' }
        ],
        patternBreakingModes: [
          { value: 'none', name: 'None', description: 'Aucun pattern breaking' },
          { value: 'lightPatternBreaking', name: 'Light Pattern Breaking', description: 'Pattern breaking léger' },
          { value: 'standardPatternBreaking', name: 'Standard Pattern Breaking', description: 'Pattern breaking standard' },
          { value: 'heavyPatternBreaking', name: 'Heavy Pattern Breaking', description: 'Pattern breaking intensif' },
          { value: 'adaptivePatternBreaking', name: 'Adaptive Pattern Breaking', description: 'Pattern breaking adaptatif' },
          { value: 'syntaxFocus', name: 'Syntax Focus', description: 'Focus syntaxe uniquement' },
          { value: 'connectorsFocus', name: 'Connectors Focus', description: 'Focus connecteurs uniquement' }
        ]
      };
      
      res.json({
        success: true,
        config: config,
        timestamp: new Date().toISOString()
      });
      
    } catch (error) {
      logSh(`❌ Erreur config modulaire: ${error.message}`, 'ERROR');
      res.status(500).json({
        success: false,
        error: error.message
      });
    }
  }

  /**
   * Lance le log viewer avec WebSocket
   */
  handleStartLogViewer(req, res) {
    try {
      const { spawn } = require('child_process');
      const path = require('path');
      const os = require('os');

      // Démarrer le WebSocket pour logs
      process.env.ENABLE_LOG_WS = 'true';
      const { initWebSocketServer } = require('../ErrorReporting');
      initWebSocketServer();

      // Servir le log viewer via une route HTTP au lieu d'un fichier local
      const logViewerUrl = `http://localhost:${this.config.port}/logs-viewer.html`;
      
      // Ouvrir dans le navigateur selon l'OS
      let command, args;
      switch (os.platform()) {
        case 'darwin': // macOS
          command = 'open';
          args = [logViewerUrl];
          break;
        case 'win32': // Windows
          command = 'cmd';
          args = ['/c', 'start', logViewerUrl];
          break;
        default: // Linux et WSL
          // Pour WSL, utiliser explorer.exe de Windows
          if (process.env.WSL_DISTRO_NAME) {
            command = '/mnt/c/Windows/System32/cmd.exe';
            args = ['/c', 'start', logViewerUrl];
          } else {
            command = 'xdg-open';
            args = [logViewerUrl];
          }
          break;
      }
      
      spawn(command, args, { detached: true, stdio: 'ignore' });
      
      const logPort = process.env.LOG_WS_PORT || 8082;
      logSh(`🌐 Log viewer lancé avec WebSocket sur port ${logPort}`, 'INFO');
      
      res.json({
        success: true,
        message: 'Log viewer lancé',
        wsPort: logPort,
        viewerUrl: logViewerUrl,
        timestamp: new Date().toISOString()
      });
      
    } catch (error) {
      logSh(`❌ Erreur lancement log viewer: ${error.message}`, 'ERROR');
      res.status(500).json({
        success: false,
        error: 'Erreur lancement log viewer',
        message: error.message,
        timestamp: new Date().toISOString()
      });
    }
  }

  // ========================================
  // HANDLERS STEP-BY-STEP
  // ========================================
  
  /**
   * Initialise une nouvelle session step-by-step
   */
  async handleStepByStepInit(req, res) {
    try {
      const { sessionManager } = require('../StepByStepSessionManager');
      
      const inputData = req.body;
      logSh(`🎯 Initialisation session step-by-step`, 'INFO');
      logSh(`   Input: ${JSON.stringify(inputData)}`, 'DEBUG');
      
      const session = sessionManager.createSession(inputData);
      
      res.json({
        success: true,
        sessionId: session.id,
        steps: session.steps.map(step => ({
          id: step.id,
          system: step.system,
          name: step.name,
          description: step.description,
          status: step.status
        })),
        inputData: session.inputData,
        timestamp: new Date().toISOString()
      });
      
    } catch (error) {
      logSh(`❌ Erreur init step-by-step: ${error.message}`, 'ERROR');
      res.status(500).json({
        success: false,
        error: 'Erreur initialisation session',
        message: error.message,
        timestamp: new Date().toISOString()
      });
    }
  }
  
  /**
   * Exécute une étape
   */
  async handleStepByStepExecute(req, res) {
    try {
      const { sessionManager } = require('../StepByStepSessionManager');
      const { StepExecutor } = require('../StepExecutor');
      
      const { sessionId, stepId, options = {} } = req.body;
      
      if (!sessionId || !stepId) {
        return res.status(400).json({
          success: false,
          error: 'sessionId et stepId requis',
          timestamp: new Date().toISOString()
        });
      }
      
      logSh(`🚀 Exécution étape ${stepId} pour session ${sessionId}`, 'INFO');
      
      // Récupérer la session
      const session = sessionManager.getSession(sessionId);
      
      // Trouver l'étape
      const step = session.steps.find(s => s.id === stepId);
      if (!step) {
        return res.status(400).json({
          success: false,
          error: `Étape ${stepId} introuvable`,
          timestamp: new Date().toISOString()
        });
      }
      
      // Marquer l'étape comme en cours
      step.status = 'executing';
      
      // Créer l'exécuteur et lancer l'étape
      const executor = new StepExecutor();
      
      logSh(`🚀 Execution step ${step.system} avec données: ${JSON.stringify(session.inputData)}`, 'DEBUG');
      
      // Récupérer le contenu de l'étape précédente pour chaînage
      let inputContent = null;
      if (stepId > 1) {
        const previousResult = session.results.find(r => r.stepId === stepId - 1);
        logSh(`🔍 DEBUG Chaînage: previousResult=${!!previousResult}`, 'DEBUG');
        if (previousResult) {
          logSh(`🔍 DEBUG Chaînage: previousResult.result=${!!previousResult.result}`, 'DEBUG');
          if (previousResult.result) {
            // StepExecutor retourne un objet avec une propriété 'content'
            if (previousResult.result.content) {
              inputContent = previousResult.result.content;
              logSh(`🔄 Chaînage: utilisation contenu.content étape ${stepId - 1}`, 'DEBUG');
            } else {
              // Fallback si c'est juste le contenu directement
              inputContent = previousResult.result;
              logSh(`🔄 Chaînage: utilisation contenu direct étape ${stepId - 1}`, 'DEBUG');
            }
            logSh(`🔍 DEBUG: inputContent type=${typeof inputContent}, keys=${Object.keys(inputContent || {})}`, 'DEBUG');
          } else {
            logSh(`🚨 DEBUG: previousResult.result est vide ou null !`, 'ERROR');
          }
        } else {
          logSh(`🚨 DEBUG: Pas de previousResult trouvé pour stepId=${stepId - 1}`, 'ERROR');
        }
      }
      
      // Ajouter le contenu d'entrée aux options si disponible
      const executionOptions = {
        ...options,
        inputContent: inputContent
      };
      
      const result = await executor.executeStep(step.system, session.inputData, executionOptions);
      
      logSh(`📊 Résultat step ${step.system}: success=${result.success}, content=${Object.keys(result.content || {}).length} éléments, duration=${result.stats?.duration}ms`, 'INFO');
      
      // Si pas d'erreur mais temps < 100ms, forcer une erreur pour debug
      if (result.success && result.stats?.duration < 100) {
        logSh(`⚠️ WARN: Step trop rapide (${result.stats?.duration}ms), probablement pas d'appel LLM réel`, 'WARN');
        result.debugWarning = `⚠️ Exécution suspecte: ${result.stats?.duration}ms (probablement pas d'appel LLM)`;
      }
      
      // Ajouter le résultat à la session
      sessionManager.addStepResult(sessionId, stepId, result);
      
      // Déterminer la prochaine étape
      const nextStep = session.steps.find(s => s.id === stepId + 1);
      
      res.json({
        success: true,
        stepId: stepId,
        system: step.system,
        name: step.name,
        result: {
          success: result.success,
          content: result.result,
          formatted: result.formatted,
          xmlFormatted: result.xmlFormatted,
          error: result.error,
          debugWarning: result.debugWarning
        },
        stats: result.stats,
        nextStep: nextStep ? nextStep.id : null,
        sessionStatus: session.status,
        timestamp: new Date().toISOString()
      });
      
    } catch (error) {
      logSh(`❌ Erreur exécution step-by-step: ${error.message}`, 'ERROR');
      res.status(500).json({
        success: false,
        error: 'Erreur exécution étape',
        message: error.message,
        timestamp: new Date().toISOString()
      });
    }
  }
  
  /**
   * Récupère le status d'une session
   */
  handleStepByStepStatus(req, res) {
    try {
      const { sessionManager } = require('../StepByStepSessionManager');
      const { sessionId } = req.params;
      
      const session = sessionManager.getSession(sessionId);
      
      res.json({
        success: true,
        session: {
          id: session.id,
          status: session.status,
          createdAt: new Date(session.createdAt).toISOString(),
          currentStep: session.currentStep,
          completedSteps: session.completedSteps,
          totalSteps: session.steps.length,
          inputData: session.inputData,
          steps: session.steps,
          globalStats: session.globalStats,
          results: session.results.map(r => ({
            stepId: r.stepId,
            system: r.system,
            success: r.success,
            timestamp: new Date(r.timestamp).toISOString(),
            stats: r.stats
          }))
        },
        timestamp: new Date().toISOString()
      });
      
    } catch (error) {
      logSh(`❌ Erreur status step-by-step: ${error.message}`, 'ERROR');
      res.status(500).json({
        success: false,
        error: 'Erreur récupération status',
        message: error.message,
        timestamp: new Date().toISOString()
      });
    }
  }
  
  /**
   * Reset une session
   */
  handleStepByStepReset(req, res) {
    try {
      const { sessionManager } = require('../StepByStepSessionManager');
      const { sessionId } = req.body;
      
      if (!sessionId) {
        return res.status(400).json({
          success: false,
          error: 'sessionId requis',
          timestamp: new Date().toISOString()
        });
      }
      
      const session = sessionManager.resetSession(sessionId);
      
      res.json({
        success: true,
        sessionId: session.id,
        message: 'Session reset avec succès',
        steps: session.steps,
        timestamp: new Date().toISOString()
      });
      
    } catch (error) {
      logSh(`❌ Erreur reset step-by-step: ${error.message}`, 'ERROR');
      res.status(500).json({
        success: false,
        error: 'Erreur reset session',
        message: error.message,
        timestamp: new Date().toISOString()
      });
    }
  }
  
  /**
   * Export les résultats d'une session
   */
  handleStepByStepExport(req, res) {
    try {
      const { sessionManager } = require('../StepByStepSessionManager');
      const { sessionId } = req.params;
      
      const exportData = sessionManager.exportSession(sessionId);
      
      res.setHeader('Content-Type', 'application/json');
      res.setHeader('Content-Disposition', `attachment; filename="step-by-step-${sessionId}.json"`);
      res.json(exportData);
      
    } catch (error) {
      logSh(`❌ Erreur export step-by-step: ${error.message}`, 'ERROR');
      res.status(500).json({
        success: false,
        error: 'Erreur export session',
        message: error.message,
        timestamp: new Date().toISOString()
      });
    }
  }
  
  /**
   * Liste les sessions actives
   */
  handleStepByStepSessions(req, res) {
    try {
      const { sessionManager } = require('../StepByStepSessionManager');
      
      const sessions = sessionManager.listSessions();
      
      res.json({
        success: true,
        sessions: sessions,
        total: sessions.length,
        timestamp: new Date().toISOString()
      });
      
    } catch (error) {
      logSh(`❌ Erreur list sessions step-by-step: ${error.message}`, 'ERROR');
      res.status(500).json({
        success: false,
        error: 'Erreur récupération sessions',
        message: error.message,
        timestamp: new Date().toISOString()
      });
    }
  }

  /**
   * Handler pour récupérer les personnalités disponibles
   */
  async handleGetPersonalities(req, res) {
    try {
      const { getPersonalities } = require('../BrainConfig');
      
      const personalities = await getPersonalities();
      
      res.json({
        success: true,
        personalities: personalities || [],
        total: (personalities || []).length,
        timestamp: new Date().toISOString()
      });
      
    } catch (error) {
      logSh(`❌ Erreur récupération personnalités: ${error.message}`, 'ERROR');
      res.status(500).json({
        success: false,
        error: 'Erreur récupération personnalités',
        message: error.message,
        timestamp: new Date().toISOString()
      });
    }
  }

  /**
   * Initialise le status LLMs au démarrage (en background)
   * ⚡ OPTIMISÉ: Mode rapide au démarrage, complet après 30s
   */
  async initializeLLMStatus() {
    logSh('🚀 Initialisation status LLMs (mode rapide)...', 'DEBUG');

    // ⚡ Phase 1: Vérification RAPIDE des clés API (immédiat, sans réseau)
    setImmediate(async () => {
      try {
        await this.refreshLLMStatus(true); // quickMode = true
        logSh('✅ Status LLMs (rapide) initialisé - vérification clés API OK', 'INFO');

        // ⚡ Phase 2: Test COMPLET avec appels réseau après 30 secondes
        setTimeout(async () => {
          try {
            logSh('🔄 Démarrage vérification complète status LLMs (avec tests réseau)...', 'DEBUG');
            await this.refreshLLMStatus(false); // quickMode = false
            logSh('✅ Status LLMs (complet) mis à jour avec tests réseau', 'INFO');
          } catch (error) {
            logSh(`⚠️ Erreur vérification complète LLMs: ${error.message}`, 'WARNING');
          }
        }, 30000); // Attendre 30 secondes avant le test complet

      } catch (error) {
        logSh(`⚠️ Erreur initialisation rapide status LLMs: ${error.message}`, 'WARNING');
      }
    });

    // Rafraîchir toutes les 30 minutes (1800000ms) en mode complet
    this.llmStatusInterval = setInterval(async () => {
      try {
        await this.refreshLLMStatus(false); // Mode complet pour les refreshs périodiques
      } catch (error) {
        logSh(`⚠️ Erreur refresh status LLMs: ${error.message}`, 'WARNING');
      }
    }, 1800000);
  }

  /**
   * Rafraîchit le cache du status LLMs
   * ⚡ OPTIMISÉ: Test rapide sans appels LLM réels au démarrage
   */
  async refreshLLMStatus(quickMode = false) {
    const { getLLMProvidersList } = require('../LLMManager');

    logSh(`📊 Récupération status LLMs${quickMode ? ' (mode rapide)' : ''}...`, 'DEBUG');

    const providers = getLLMProvidersList();
    const providersWithStatus = [];

    if (quickMode) {
      // ⚡ MODE RAPIDE: Vérifier juste les clés API sans appels réseau
      for (const provider of providers) {
        const hasApiKey = this.checkProviderApiKey(provider.id);

        providersWithStatus.push({
          ...provider,
          status: hasApiKey ? 'unknown' : 'no_key',
          latency: null,
          lastTest: null,
          credits: 'unlimited',
          calls: 0,
          successRate: hasApiKey ? null : 0,
          quickMode: true
        });
      }

      logSh('⚡ Status rapide LLMs (sans appels réseau) - vérification clés API uniquement', 'DEBUG');
    } else {
      // MODE COMPLET: Test réseau réel
      for (const provider of providers) {
        const startTime = Date.now();
        let status = 'offline';
        let latency = null;
        let lastTest = null;

        try {
          const { callLLM } = require('../LLMManager');
          await callLLM(provider.id, 'Test ping', { maxTokens: 10 });

          latency = Date.now() - startTime;
          status = 'online';
          lastTest = new Date().toLocaleTimeString('fr-FR');
        } catch (error) {
          logSh(`⚠️ Provider ${provider.id} offline: ${error.message}`, 'DEBUG');
          status = 'offline';
        }

        providersWithStatus.push({
          ...provider,
          status,
          latency,
          lastTest,
          credits: 'unlimited',
          calls: 0,
          successRate: status === 'online' ? 100 : 0
        });
      }
    }

    // Mettre à jour le cache
    this.llmStatusCache = {
      success: true,
      providers: providersWithStatus,
      summary: {
        total: providersWithStatus.length,
        online: providersWithStatus.filter(p => p.status === 'online').length,
        offline: providersWithStatus.filter(p => p.status === 'offline').length,
        unknown: providersWithStatus.filter(p => p.status === 'unknown').length,
        no_key: providersWithStatus.filter(p => p.status === 'no_key').length
      },
      quickMode: quickMode,
      timestamp: new Date().toISOString()
    };
    this.llmStatusCacheTime = Date.now();

    if (quickMode) {
      logSh(`⚡ Status LLMs (rapide): ${this.llmStatusCache.summary.unknown} providers avec clés, ${this.llmStatusCache.summary.no_key} sans clés`, 'INFO');
    } else {
      logSh(`✅ Status LLMs (complet): ${this.llmStatusCache.summary.online}/${this.llmStatusCache.summary.total} online`, 'INFO');
    }
  }

  /**
   * Vérifie si un provider a une clé API configurée
   */
  checkProviderApiKey(providerId) {
    const keyMap = {
      'claude-sonnet-4-5': 'ANTHROPIC_API_KEY',
      'claude-3-5-sonnet-20241022': 'ANTHROPIC_API_KEY',
      'gpt-4o': 'OPENAI_API_KEY',
      'gpt-4o-mini': 'OPENAI_API_KEY',
      'gemini-2-0-flash-exp': 'GOOGLE_API_KEY',
      'gemini-pro': 'GOOGLE_API_KEY',
      'deepseek-chat': 'DEEPSEEK_API_KEY',
      'moonshot-v1-8k': 'MOONSHOT_API_KEY',
      'mistral-small-latest': 'MISTRAL_API_KEY'
    };

    const envKey = keyMap[providerId];
    if (!envKey) return false;

    const apiKey = process.env[envKey];
    return apiKey && apiKey.length > 10;
  }

  /**
   * Handler pour status et monitoring des LLMs
   */
  async handleLLMStatus(req, res) {
    try {
      // Si on a un cache, le retourner directement
      if (this.llmStatusCache) {
        res.json(this.llmStatusCache);
      } else {
        // Pas encore de cache, retourner une réponse vide
        res.json({
          success: true,
          providers: [],
          summary: {
            total: 0,
            online: 0,
            offline: 0
          },
          timestamp: new Date().toISOString(),
          message: 'Status LLMs en cours de chargement...'
        });
      }

    } catch (error) {
      logSh(`❌ Erreur status LLMs: ${error.message}`, 'ERROR');
      res.status(500).json({
        success: false,
        error: 'Erreur récupération status LLMs',
        message: error.message,
        timestamp: new Date().toISOString()
      });
    }
  }

  /**
   * 🆕 Handler pour génération simple d'article avec mot-clé
   */
  async handleGenerateSimple(req, res) {
    try {
      const { keyword } = req.body;

      // Validation basique
      if (!keyword || typeof keyword !== 'string' || keyword.trim().length === 0) {
        return res.status(400).json({
          success: false,
          error: 'Mot-clé requis',
          message: 'Le paramètre "keyword" est obligatoire et doit être une chaîne non vide'
        });
      }

      const cleanKeyword = keyword.trim();
      logSh(`🎯 Génération simple pour mot-clé: "${cleanKeyword}"`, 'INFO');

      // Créer un template XML simple basé sur le mot-clé
      const simpleTemplate = `<?xml version="1.0" encoding="UTF-8"?>
<article>
  <h1>|Titre_Principal{{${cleanKeyword}}}{Rédige un titre H1 accrocheur pour "${cleanKeyword}"}|</h1>
  <intro>|Introduction{{${cleanKeyword}}}{Rédige une introduction engageante de 2-3 phrases pour "${cleanKeyword}"}|</intro>
  <section1>
    <h2>|Sous_Titre_1{{${cleanKeyword}}}{Rédige un sous-titre H2 pour "${cleanKeyword}"}|</h2>
    <content>|Contenu_1{{${cleanKeyword}}}{Rédige un paragraphe détaillé sur "${cleanKeyword}"}|</content>
  </section1>
  <section2>
    <h2>|Sous_Titre_2{{${cleanKeyword}}}{Rédige un autre sous-titre H2 pour "${cleanKeyword}"}|</h2>
    <content>|Contenu_2{{${cleanKeyword}}}{Rédige un autre paragraphe sur "${cleanKeyword}"}|</content>
  </section2>
  <conclusion>|Conclusion{{${cleanKeyword}}}{Rédige une conclusion pour l'article sur "${cleanKeyword}"}|</conclusion>
</article>`;

      // Préparer les données pour le workflow
      const workflowData = {
        csvData: {
          mc0: cleanKeyword,
          t0: `Guide complet sur ${cleanKeyword}`,
          personality: { nom: 'Marc', style: 'professionnel' },
          tMinus1: cleanKeyword,
          mcPlus1: `${cleanKeyword},guide ${cleanKeyword},tout savoir ${cleanKeyword}`,
          tPlus1: `Guide ${cleanKeyword},Conseils ${cleanKeyword},${cleanKeyword} pratique`
        },
        xmlTemplate: Buffer.from(simpleTemplate).toString('base64'),
        source: 'api_generate_simple'
      };

      logSh(`📝 Template créé pour "${cleanKeyword}"`, 'DEBUG');

      // Utiliser le workflow modulaire simple (juste génération de base)
      const { handleModularWorkflow } = require('../Main');

      const config = {
        selectiveStack: 'lightEnhancement',
        adversarialMode: 'none',
        humanSimulationMode: 'none',
        patternBreakingMode: 'none',
        saveVersions: false,
        source: 'api_generate_simple'
      };

      logSh(`🚀 Démarrage génération modulaire pour "${cleanKeyword}"`, 'INFO');

      const result = await handleModularWorkflow(workflowData, config);

      logSh(`✅ Génération terminée pour "${cleanKeyword}"`, 'INFO');

      // Réponse simplifiée
      res.json({
        success: true,
        keyword: cleanKeyword,
        article: {
          content: result.compiledText || result.generatedTexts || 'Contenu généré',
          title: result.generatedTexts?.Titre_Principal || `Article sur ${cleanKeyword}`,
          meta: {
            processing_time: result.processingTime || 'N/A',
            personality: result.personality?.nom || 'Marc',
            version: result.version || 'v1.0'
          }
        },
        timestamp: new Date().toISOString()
      });

    } catch (error) {
      logSh(`❌ Erreur génération simple: ${error.message}`, 'ERROR');
      logSh(`Stack: ${error.stack}`, 'DEBUG');

      res.status(500).json({
        success: false,
        error: 'Erreur lors de la génération',
        message: error.message,
        timestamp: new Date().toISOString()
      });
    }
  }

  // ========================================
  // INTERFACE WEB
  // ========================================
  
  /**
   * Configure l'interface web
   */
  setupWebInterface() {
    // Page d'accueil - Dashboard MANUAL
    this.app.get('/', (req, res) => {
      res.send(this.generateManualDashboard());
    });

    // Route pour le log viewer
    this.app.get('/logs-viewer.html', (req, res) => {
      const fs = require('fs');
      const logViewerPath = path.join(__dirname, '../../tools/logs-viewer.html');
      
      try {
        const content = fs.readFileSync(logViewerPath, 'utf-8');
        res.setHeader('Content-Type', 'text/html; charset=utf-8');
        res.send(content);
      } catch (error) {
        logSh(`❌ Erreur lecture log viewer: ${error.message}`, 'ERROR');
        res.status(500).send(`Erreur: ${error.message}`);
      }
    });

    // Route 404
    this.app.use('*', (req, res) => {
      res.status(404).json({
        success: false,
        error: 'Route non trouvée',
        path: req.originalUrl,
        mode: 'MANUAL',
        message: 'Cette route n\'existe pas en mode MANUAL'
      });
    });

    logSh('🌐 Interface web configurée', 'DEBUG');
  }

  /**
   * Génère le dashboard HTML du mode MANUAL
   */
  generateManualDashboard() {
    const uptime = Math.floor((Date.now() - this.stats.startTime) / 1000);
    
    return `
    <!DOCTYPE html>
    <html>
    <head>
        <title>SEO Generator - Mode MANUAL</title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <style>
            body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; margin: 0; padding: 20px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); min-height: 100vh; }
            .container { max-width: 1200px; margin: 0 auto; background: white; padding: 30px; border-radius: 15px; box-shadow: 0 10px 30px rgba(0,0,0,0.1); }
            .header { text-align: center; margin-bottom: 40px; }
            .header h1 { color: #2d3748; margin-bottom: 10px; }
            .mode-badge { background: #48bb78; color: white; padding: 8px 16px; border-radius: 20px; font-weight: bold; }
            .stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 20px; margin-bottom: 40px; }
            .stat-card { background: #f7fafc; padding: 20px; border-radius: 10px; text-align: center; border: 1px solid #e2e8f0; }
            .stat-number { font-size: 2em; font-weight: bold; color: #2d3748; }
            .stat-label { color: #718096; margin-top: 5px; }
            .section { margin: 30px 0; padding: 25px; border: 1px solid #e2e8f0; border-radius: 10px; background: #f9f9f9; }
            .section h2 { color: #2d3748; margin-bottom: 15px; }
            .button { display: inline-block; padding: 12px 24px; margin: 8px; background: linear-gradient(135deg, #667eea, #764ba2); color: white; text-decoration: none; border-radius: 8px; border: none; cursor: pointer; font-weight: 500; transition: all 0.2s; }
            .button:hover { transform: translateY(-2px); box-shadow: 0 5px 15px rgba(102, 126, 234, 0.4); }
            .button.success { background: linear-gradient(135deg, #48bb78, #38a169); }
            .button.warning { background: linear-gradient(135deg, #ed8936, #dd6b20); }
            .alert { padding: 15px; margin: 20px 0; border-radius: 8px; border-left: 4px solid; }
            .alert.success { background: #f0fff4; border-color: #48bb78; color: #22543d; }
            .alert.info { background: #ebf8ff; border-color: #4299e1; color: #2a4365; }
        </style>
    </head>
    <body>
        <div class="container">
            <div class="header">
                <h1>🎯 SEO Generator Server</h1>
                <span class="mode-badge">MODE MANUAL</span>
                <p style="color: #718096; margin-top: 15px;">Interface Client + API + Tests Modulaires</p>
            </div>
            
            <div class="alert success">
                <strong>✅ Mode MANUAL Actif</strong><br>
                Interface complète disponible • WebSocket temps réel • API complète
            </div>

            <div class="stats">
                <div class="stat-card">
                    <div class="stat-number">${uptime}s</div>
                    <div class="stat-label">Uptime</div>
                </div>
                <div class="stat-card">
                    <div class="stat-number">${this.stats.requests}</div>
                    <div class="stat-label">Requêtes</div>
                </div>
                <div class="stat-card">
                    <div class="stat-number">${this.activeClients.size}</div>
                    <div class="stat-label">Clients WebSocket</div>
                </div>
                <div class="stat-card">
                    <div class="stat-number">${this.stats.testsExecuted}</div>
                    <div class="stat-label">Tests Exécutés</div>
                </div>
            </div>

            <div class="section">
                <h2>🧪 Interface Test Modulaire</h2>
                <p>Interface avancée pour tester toutes les combinaisons modulaires avec logs temps réel.</p>
                <a href="/test-modulaire.html" target="_blank" class="button">🚀 Ouvrir Interface Test</a>
                <a href="/step-by-step" target="_blank" class="button">⚡ Interface Step-by-Step</a>
                <a href="/api/modulaire-config" target="_blank" class="button success">📋 Configuration API</a>
            </div>

            <div class="section">
                <h2>📊 Monitoring & API</h2>
                <p>Endpoints disponibles en mode MANUAL.</p>
                <a href="/llm-monitoring.html" target="_blank" class="button warning">🤖 LLM Monitoring</a>
                <a href="/api/status" target="_blank" class="button">📊 Status API</a>
                <a href="/api/stats" target="_blank" class="button">📈 Statistiques</a>
                <button onclick="testConnection()" class="button success">🔍 Test Connexion</button>
            </div>

            <div class="section">
                <h2>🌐 WebSocket Logs</h2>
                <p>Logs temps réel sur <strong>ws://localhost:${this.config.wsPort}</strong></p>
                <button onclick="startLogViewer()" class="button warning">🔍 Ouvrir Log Viewer</button>
                <div id="wsStatus" style="margin-top: 10px; padding: 10px; background: #e2e8f0; border-radius: 5px;">
                    Status: <span id="wsStatusText">Déconnecté</span>
                </div>
            </div>

            <div class="section">
                <h2>💡 Informations Mode MANUAL</h2>
                <ul style="color: #4a5568; line-height: 1.6;">
                    <li><strong>Interface Client</strong> : Dashboard complet et interface de test</li>
                    <li><strong>API Complète</strong> : Tests individuels, benchmarks, configuration</li>
                    <li><strong>WebSocket</strong> : Logs temps réel sur port ${this.config.wsPort}</li>
                    <li><strong>Multi-Client</strong> : Plusieurs utilisateurs simultanés</li>
                    <li><strong>Pas de GSheets</strong> : Données test simulées ou fournies</li>
                </ul>
            </div>
        </div>

        <script>
            let ws = null;
            
            function testConnection() {
                fetch('/api/status')
                    .then(res => res.json())
                    .then(data => {
                        alert('✅ Connexion OK: ' + (data.mode || 'Mode MANUAL actif') + ' - Uptime: ' + Math.floor(data.uptime/1000) + 's');
                    })
                    .catch(err => {
                        alert('❌ Erreur connexion: ' + err.message);
                    });
            }
            
            function startLogViewer() {
                fetch('/api/start-log-viewer', { method: 'POST' })
                    .then(res => res.json())
                    .then(data => {
                        if (data.success) {
                            alert('✅ Log Viewer lancé! WebSocket sur port ' + data.wsPort);
                            // Reconnecter le WebSocket pour voir les logs
                            connectWebSocket();
                        } else {
                            alert('❌ Erreur: ' + data.message);
                        }
                    })
                    .catch(err => {
                        alert('❌ Erreur lancement: ' + err.message);
                    });
            }
            
            let reconnectAttempts = 0;
            const maxReconnectDelay = 30000; // 30s max
            
            function connectWebSocket() {
                try {
                    ws = new WebSocket('ws://localhost:${this.config.wsPort}');
                    
                    ws.onopen = () => {
                        reconnectAttempts = 0; // Reset compteur
                        document.getElementById('wsStatusText').textContent = 'Connecté ✅';
                        document.getElementById('wsStatus').style.background = '#c6f6d5';
                    };
                    
                    ws.onclose = () => {
                        document.getElementById('wsStatusText').textContent = 'Déconnecté ❌';
                        document.getElementById('wsStatus').style.background = '#fed7d7';
                        
                        // Backoff exponentiel pour éviter spam
                        reconnectAttempts++;
                        const delay = Math.min(1000 * Math.pow(2, reconnectAttempts), maxReconnectDelay);
                        console.log('WebSocket fermé, reconnexion dans ' + (delay/1000) + 's (tentative ' + reconnectAttempts + ')');
                        setTimeout(connectWebSocket, delay);
                    };
                    
                } catch (error) {
                    console.warn('WebSocket non disponible:', error.message);
                    // Retry avec backoff en cas d'erreur de connexion
                    reconnectAttempts++;
                    const delay = Math.min(5000 * reconnectAttempts, maxReconnectDelay);
                    setTimeout(connectWebSocket, delay);
                }
            }
            
            // Auto-connect WebSocket
            connectWebSocket();
            
            // Refresh stats every 30s
            setInterval(() => {
                window.location.reload();
            }, 30000);
        </script>
    </body>
    </html>
    `;
  }

  // ========================================
  // WEBSOCKET SERVER
  // ========================================
  
  /**
   * Configure le serveur WebSocket pour logs temps réel
   */
  async setupWebSocketServer() {
    try {
      this.wsServer = new WebSocket.Server({ 
        port: this.config.wsPort,
        host: this.config.host
      });
      
      this.wsServer.on('connection', (ws, req) => {
        this.handleWebSocketConnection(ws, req);
      });
      
      this.wsServer.on('error', (error) => {
        logSh(`❌ Erreur WebSocket: ${error.message}`, 'ERROR');
      });
      
      logSh(`📡 WebSocket Server démarré sur ws://${this.config.host}:${this.config.wsPort}`, 'DEBUG');
      
    } catch (error) {
      logSh(`⚠️ Impossible de démarrer WebSocket: ${error.message}`, 'WARNING');
      // Continue sans WebSocket si erreur
    }
  }

  /**
   * Gère les nouvelles connexions WebSocket
   */
  handleWebSocketConnection(ws, req) {
    const clientId = `client_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
    const clientIP = req.socket.remoteAddress;
    
    const clientData = { id: clientId, ws, ip: clientIP, connectedAt: Date.now() };
    this.activeClients.add(clientData);
    this.stats.sessions++;
    
    logSh(`📡 Nouveau client WebSocket: ${clientId} (${clientIP})`, 'TRACE');
    
    // Message de bienvenue
    ws.send(JSON.stringify({
      type: 'welcome',
      message: 'Connecté aux logs temps réel SEO Generator (Mode MANUAL)',
      clientId: clientId,
      timestamp: new Date().toISOString()
    }));
    
    // Gestion fermeture
    ws.on('close', () => {
      this.activeClients.delete(clientData);
      logSh(`📡 Client WebSocket déconnecté: ${clientId}`, 'TRACE');
    });
    
    // Gestion erreurs
    ws.on('error', (error) => {
      this.activeClients.delete(clientData);
      logSh(`⚠️ Erreur client WebSocket ${clientId}: ${error.message}`, 'WARNING');
    });
  }

  /**
   * Diffuse un message à tous les clients WebSocket
   */
  broadcastToClients(logData) {
    if (this.activeClients.size === 0) return;
    
    const message = JSON.stringify({
      type: 'log',
      ...logData,
      timestamp: new Date().toISOString()
    });
    
    this.activeClients.forEach(client => {
      if (client.ws.readyState === WebSocket.OPEN) {
        try {
          client.ws.send(message);
        } catch (error) {
          // Client déconnecté, le supprimer
          this.activeClients.delete(client);
        }
      }
    });
  }

  /**
   * Déconnecte tous les clients WebSocket
   */
  disconnectAllClients() {
    this.activeClients.forEach(client => {
      try {
        client.ws.close();
      } catch (error) {
        // Ignore les erreurs de fermeture
      }
    });
    
    this.activeClients.clear();
    logSh('📡 Tous les clients WebSocket déconnectés', 'DEBUG');
  }

  // ========================================
  // SERVEUR HTTP
  // ========================================
  
  /**
   * Démarre le serveur HTTP
   */
  async startHTTPServer() {
    return new Promise((resolve, reject) => {
      try {
        this.server = this.app.listen(this.config.port, this.config.host, () => {
          resolve();
        });
        
        this.server.on('error', (error) => {
          reject(error);
        });
        
      } catch (error) {
        reject(error);
      }
    });
  }

  // ========================================
  // MONITORING
  // ========================================
  
  /**
   * Démarre le monitoring du serveur
   */
  startMonitoring() {
    const MONITOR_INTERVAL = 30000; // 30 secondes
    
    this.monitorInterval = setInterval(() => {
      this.performMonitoring();
    }, MONITOR_INTERVAL);
    
    logSh('💓 Monitoring ManualServer démarré', 'DEBUG');
  }

  /**
   * Effectue le monitoring périodique
   */
  performMonitoring() {
    const memUsage = process.memoryUsage();
    const uptime = Date.now() - this.stats.startTime;
    
    logSh(`💓 ManualServer Health - Clients: ${this.activeClients.size} | Requêtes: ${this.stats.requests} | RAM: ${Math.round(memUsage.rss / 1024 / 1024)}MB`, 'TRACE');
    
    // Nettoyage clients WebSocket morts
    this.cleanupDeadClients();
  }

  /**
   * Nettoie les clients WebSocket déconnectés
   */
  cleanupDeadClients() {
    let cleaned = 0;
    const deadClients = [];
    
    this.activeClients.forEach(client => {
      if (client.ws.readyState !== WebSocket.OPEN) {
        deadClients.push(client);
        cleaned++;
      }
    });
    
    // Supprimer les clients morts
    deadClients.forEach(client => {
      this.activeClients.delete(client);
    });
    
    if (cleaned > 0) {
      logSh(`🧹 ${cleaned} clients WebSocket morts nettoyés`, 'TRACE');
    }
  }

  // ========================================
  // ÉTAT ET CONTRÔLES
  // ========================================
  
  /**
   * Vérifie s'il y a des clients actifs
   */
  hasActiveClients() {
    return this.activeClients.size > 0;
  }

  /**
   * Retourne l'état du serveur MANUAL
   */
  getStatus() {
    return {
      isRunning: this.isRunning,
      config: { ...this.config },
      stats: {
        ...this.stats,
        uptime: Date.now() - this.stats.startTime
      },
      activeClients: this.activeClients.size,
      urls: {
        dashboard: `http://localhost:${this.config.port}`,
        testInterface: `http://localhost:${this.config.port}/test-modulaire.html`,
        apiStatus: `http://localhost:${this.config.port}/api/status`,
        websocket: `ws://localhost:${this.config.wsPort}`
      }
    };
  }
}

// ============= EXPORTS =============
module.exports = { ManualServer };