// ========================================
// FICHIER: StepByStepSessionManager.js
// RESPONSABILITÉ: Gestion des sessions step-by-step
// ========================================

// Pas besoin d'uuid externe, on utilise notre générateur simple
const { logSh } = require('./ErrorReporting');

/**
 * GESTIONNAIRE DE SESSIONS STEP-BY-STEP
 * Gère les sessions de test modulaire pas-à-pas avec TTL
 */
class StepByStepSessionManager {
  constructor() {
    this.sessions = new Map();
    this.TTL = 30 * 60 * 1000; // 30 minutes
    
    // Nettoyage automatique toutes les 5 minutes
    setInterval(() => this.cleanupExpiredSessions(), 5 * 60 * 1000);
    
    logSh('🎯 SessionManager initialisé', 'DEBUG');
  }

  // ========================================
  // GESTION DES SESSIONS
  // ========================================
  
  /**
   * Crée une nouvelle session
   */
  createSession(inputData) {
    const sessionId = this.generateUUID();
    const session = {
      id: sessionId,
      createdAt: Date.now(),
      lastAccessedAt: Date.now(),
      inputData: this.validateInputData(inputData),
      currentStep: 0,
      completedSteps: [],
      results: [],
      globalStats: {
        totalDuration: 0,
        totalTokens: 0,
        totalCost: 0,
        llmCalls: [],
        startTime: Date.now(),
        endTime: null
      },
      steps: this.generateStepsList(),
      status: 'initialized'
    };
    
    this.sessions.set(sessionId, session);
    logSh(`✅ Session créée: ${sessionId}`, 'INFO');
    
    return session;
  }
  
  /**
   * Récupère une session
   */
  getSession(sessionId) {
    const session = this.sessions.get(sessionId);
    if (!session) {
      throw new Error(`Session introuvable: ${sessionId}`);
    }
    
    if (this.isSessionExpired(session)) {
      this.deleteSession(sessionId);
      throw new Error(`Session expirée: ${sessionId}`);
    }
    
    session.lastAccessedAt = Date.now();
    return session;
  }
  
  /**
   * Met à jour une session
   */
  updateSession(sessionId, updates) {
    const session = this.getSession(sessionId);
    Object.assign(session, updates);
    session.lastAccessedAt = Date.now();
    
    logSh(`📝 Session mise à jour: ${sessionId}`, 'DEBUG');
    return session;
  }
  
  /**
   * Supprime une session
   */
  deleteSession(sessionId) {
    const deleted = this.sessions.delete(sessionId);
    if (deleted) {
      logSh(`🗑️ Session supprimée: ${sessionId}`, 'INFO');
    }
    return deleted;
  }
  
  /**
   * Liste toutes les sessions actives
   */
  listSessions() {
    const sessions = [];
    for (const [id, session] of this.sessions) {
      if (!this.isSessionExpired(session)) {
        sessions.push({
          id: session.id,
          createdAt: session.createdAt,
          status: session.status,
          currentStep: session.currentStep,
          totalSteps: session.steps.length,
          inputData: {
            mc0: session.inputData.mc0,
            personality: session.inputData.personality
          }
        });
      }
    }
    return sessions;
  }

  // ========================================
  // GESTION DES ÉTAPES
  // ========================================
  
  /**
   * Ajoute le résultat d'une étape
   */
  addStepResult(sessionId, stepId, result) {
    const session = this.getSession(sessionId);
    
    // Marquer l'étape comme complétée
    if (!session.completedSteps.includes(stepId)) {
      session.completedSteps.push(stepId);
    }
    
    // Ajouter le résultat
    const stepResult = {
      stepId: stepId,
      system: result.system,
      timestamp: Date.now(),
      success: result.success,
      result: result.result || null,
      error: result.error || null,
      stats: result.stats || {},
      formatted: result.formatted || null
    };
    
    session.results.push(stepResult);
    
    // Mettre à jour les stats globales
    this.updateGlobalStats(session, result.stats || {});
    
    // Mettre à jour le statut de l'étape
    const step = session.steps.find(s => s.id === stepId);
    if (step) {
      step.status = result.success ? 'completed' : 'error';
      step.duration = (result.stats && result.stats.duration) || 0;
      step.error = result.error || null;
    }
    
    // Mettre à jour currentStep si nécessaire
    if (stepId > session.currentStep) {
      session.currentStep = stepId;
    }
    
    logSh(`📊 Résultat étape ${stepId} ajouté à session ${sessionId}`, 'DEBUG');
    return session;
  }
  
  /**
   * Obtient le résultat d'une étape
   */
  getStepResult(sessionId, stepId) {
    const session = this.getSession(sessionId);
    return session.results.find(r => r.stepId === stepId) || null;
  }
  
  /**
   * Reset une session
   */
  resetSession(sessionId) {
    const session = this.getSession(sessionId);
    
    session.currentStep = 0;
    session.completedSteps = [];
    session.results = [];
    session.globalStats = {
      totalDuration: 0,
      totalTokens: 0,
      totalCost: 0,
      llmCalls: [],
      startTime: Date.now(),
      endTime: null
    };
    session.steps = this.generateStepsList();
    session.status = 'initialized';
    
    logSh(`🔄 Session reset: ${sessionId}`, 'INFO');
    return session;
  }

  // ========================================
  // HELPERS PRIVÉS
  // ========================================
  
  /**
   * Génère un UUID simple
   */
  generateUUID() {
    return Date.now().toString(36) + Math.random().toString(36).substr(2);
  }
  
  /**
   * Valide les données d'entrée
   */
  validateInputData(inputData) {
    const validated = {
      mc0: inputData.mc0 || 'mot-clé principal',
      t0: inputData.t0 || 'titre principal',
      mcPlus1: inputData.mcPlus1 || '',
      tPlus1: inputData.tPlus1 || '',
      personality: inputData.personality || 'random',
      tMinus1: inputData.tMinus1 || '',
      xmlTemplate: inputData.xmlTemplate || null
    };
    
    return validated;
  }
  
  /**
   * Génère la liste des étapes
   */
  generateStepsList() {
    return [
      {
        id: 1,
        system: 'initial-generation',
        name: 'Initial Generation',
        description: 'Génération de contenu initial avec Claude',
        status: 'pending',
        duration: 0,
        error: null
      },
      {
        id: 2,
        system: 'selective',
        name: 'Selective Enhancement', 
        description: 'Amélioration sélective (Technique → Transitions → Style)',
        status: 'pending',
        duration: 0,
        error: null
      },
      {
        id: 3,
        system: 'adversarial',
        name: 'Adversarial Generation',
        description: 'Génération adversariale anti-détection',
        status: 'pending',
        duration: 0,
        error: null
      },
      {
        id: 4,
        system: 'human-simulation',
        name: 'Human Simulation',
        description: 'Simulation comportements humains',
        status: 'pending',
        duration: 0,
        error: null
      },
      {
        id: 5,
        system: 'pattern-breaking',
        name: 'Pattern Breaking',
        description: 'Cassage de patterns IA',
        status: 'pending',
        duration: 0,
        error: null
      }
    ];
  }
  
  /**
   * Met à jour les statistiques globales
   */
  updateGlobalStats(session, stepStats) {
    const global = session.globalStats;
    
    global.totalDuration += stepStats.duration || 0;
    global.totalTokens += stepStats.tokensUsed || 0;
    global.totalCost += stepStats.cost || 0;
    
    if (stepStats.llmCalls && Array.isArray(stepStats.llmCalls)) {
      global.llmCalls.push(...stepStats.llmCalls);
    }
    
    // Marquer la fin si toutes les étapes sont complétées
    if (session.completedSteps.length === session.steps.length) {
      global.endTime = Date.now();
      session.status = 'completed';
    }
  }
  
  /**
   * Vérifie si une session est expirée
   */
  isSessionExpired(session) {
    return (Date.now() - session.lastAccessedAt) > this.TTL;
  }
  
  /**
   * Nettoie les sessions expirées
   */
  cleanupExpiredSessions() {
    let cleaned = 0;
    for (const [id, session] of this.sessions) {
      if (this.isSessionExpired(session)) {
        this.sessions.delete(id);
        cleaned++;
      }
    }
    
    if (cleaned > 0) {
      logSh(`🧹 ${cleaned} sessions expirées nettoyées`, 'DEBUG');
    }
  }

  // ========================================
  // EXPORT/IMPORT
  // ========================================
  
  /**
   * Exporte une session au format JSON
   */
  exportSession(sessionId) {
    const session = this.getSession(sessionId);
    
    return {
      session: {
        id: session.id,
        createdAt: new Date(session.createdAt).toISOString(),
        inputData: session.inputData,
        results: session.results,
        globalStats: session.globalStats,
        steps: session.steps.map(step => ({
          ...step,
          duration: step.duration ? `${step.duration}ms` : '0ms'
        }))
      },
      exportedAt: new Date().toISOString(),
      version: '1.0.0'
    };
  }
}

// Instance singleton
const sessionManager = new StepByStepSessionManager();

module.exports = {
  StepByStepSessionManager,
  sessionManager
};