/**
 * ErrorHandler - Gestion centralisée des erreurs
 * 
 * Responsabilités:
 * - Messages d'erreur spécifiques par type
 * - Retry avec backoff pour erreurs réseau
 * - Rollback automatique en cas d'erreur d'état
 * - Logging de toutes les erreurs
 * - Maintenir l'interface fonctionnelle après erreurs non critiques
 * 
 * Validates: Requirements 14.1, 14.2, 14.3, 14.4, 14.5, 14.6, 14.7
 */
class ErrorHandler {
  constructor(stateManager) {
    this.stateManager = stateManager;
    this.errorLog = [];
  }

  /**
   * Gérer une erreur
   * Validates: Requirements 14.1, 14.2, 14.6
   */
  handleError(error, context = '', critical = false) {
    // Logger l'erreur
    this.logError(error, context);
    
    // Déterminer le type d'erreur
    const errorType = this.classifyError(error);
    
    // Obtenir le message approprié
    const message = this.getErrorMessage(errorType, context);
    
    // Afficher l'erreur à l'utilisateur
    this.showError(message, critical);
    
    // Si erreur critique, tenter un rollback
    if (critical) {
      this.attemptRollback();
    }
    
    return { type: errorType, message, critical };
  }

  /**
   * Classifier le type d'erreur
   */
  classifyError(error) {
    if (error.message && error.message.includes('Network')) {
      return 'network';
    }
    if (error.message && error.message.includes('HTTP')) {
      const match = error.message.match(/HTTP (\d+)/);
      if (match) {
        const status = parseInt(match[1]);
        if (status === 401) return 'unauthorized';
        if (status === 403) return 'forbidden';
        if (status === 404) return 'not_found';
        if (status >= 500) return 'server';
      }
      return 'http';
    }
    if (error.name === 'TypeError') return 'type';
    if (error.name === 'ReferenceError') return 'reference';
    return 'unknown';
  }

  /**
   * Obtenir le message d'erreur approprié
   * Validates: Requirements 14.2
   */
  getErrorMessage(errorType, context) {
    const messages = {
      'network': `Erreur réseau lors de ${context}. Vérifiez votre connexion.`,
      'unauthorized': 'Session expirée. Veuillez vous reconnecter.',
      'forbidden': 'Accès interdit. Vous n\'avez pas les permissions nécessaires.',
      'not_found': `${context} introuvable.`,
      'server': 'Erreur serveur. Veuillez réessayer plus tard.',
      'http': `Erreur lors de ${context}.`,
      'type': `Erreur de type de données lors de ${context}.`,
      'reference': `Erreur de référence lors de ${context}.`,
      'unknown': `Erreur inattendue lors de ${context}.`
    };
    
    return messages[errorType] || messages['unknown'];
  }

  /**
   * Afficher une erreur à l'utilisateur
   */
  showError(message, critical = false) {
    // Créer une notification d'erreur
    const notification = document.createElement('div');
    notification.className = `error-notification ${critical ? 'critical' : 'warning'}`;
    notification.innerHTML = `
      <div class="error-icon">${critical ? '❌' : '⚠️'}</div>
      <div class="error-message">${this.escapeHTML(message)}</div>
      <button class="error-close" onclick="this.parentElement.remove()">✕</button>
    `;
    
    // Ajouter au DOM
    let container = document.getElementById('error-container');
    if (!container) {
      container = document.createElement('div');
      container.id = 'error-container';
      document.body.appendChild(container);
    }
    
    container.appendChild(notification);
    
    // Auto-fermer après 5 secondes si non critique
    if (!critical) {
      setTimeout(() => {
        if (notification.parentElement) {
          notification.remove();
        }
      }, 5000);
    }
  }

  /**
   * Logger une erreur
   * Validates: Requirements 14.6
   */
  logError(error, context) {
    const logEntry = {
      timestamp: new Date().toISOString(),
      context,
      message: error.message,
      stack: error.stack,
      type: error.name
    };
    
    this.errorLog.push(logEntry);
    console.error(`[${logEntry.timestamp}] Error in ${context}:`, error);
    
    // Limiter la taille du log à 100 entrées
    if (this.errorLog.length > 100) {
      this.errorLog.shift();
    }
  }

  /**
   * Tenter un rollback de l'état
   * Validates: Requirements 14.3
   */
  attemptRollback() {
    try {
      // Cloner l'état actuel avant rollback
      const currentState = this.stateManager.cloneState();
      
      // Tenter de restaurer l'état précédent
      const previousState = this.getPreviousState();
      if (previousState) {
        this.stateManager.restoreState(previousState);
        console.log('State rolled back successfully');
        this.showError('État restauré à la version précédente', false);
      }
    } catch (rollbackError) {
      console.error('Rollback failed:', rollbackError);
      this.logError(rollbackError, 'rollback');
    }
  }

  /**
   * Obtenir l'état précédent (simplifié)
   */
  getPreviousState() {
    // Dans une implémentation complète, on garderait un historique des états
    // Pour l'instant, retourner l'état par défaut
    return this.stateManager.getDefaultState();
  }

  /**
   * Retry avec backoff exponentiel
   * Validates: Requirements 14.4
   */
  async retryWithBackoff(fn, maxRetries = 3, baseDelay = 1000) {
    for (let i = 0; i < maxRetries; i++) {
      try {
        return await fn();
      } catch (error) {
        if (i === maxRetries - 1) {
          throw error;
        }
        
        const delay = baseDelay * Math.pow(2, i);
        console.log(`Retry ${i + 1}/${maxRetries} after ${delay}ms`);
        await this.sleep(delay);
      }
    }
  }

  /**
   * Attendre un délai
   */
  sleep(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
  }

  /**
   * Vérifier si l'interface est fonctionnelle
   * Validates: Requirements 14.7
   */
  checkInterfaceHealth() {
    const checks = {
      stateManager: !!this.stateManager,
      dom: !!document.getElementById('app'),
      localStorage: this.testLocalStorage()
    };
    
    const healthy = Object.values(checks).every(check => check);
    
    if (!healthy) {
      console.warn('Interface health check failed:', checks);
    }
    
    return { healthy, checks };
  }

  /**
   * Tester localStorage
   */
  testLocalStorage() {
    try {
      const test = '__test__';
      localStorage.setItem(test, test);
      localStorage.removeItem(test);
      return true;
    } catch (e) {
      return false;
    }
  }

  /**
   * Obtenir le log des erreurs
   */
  getErrorLog() {
    return this.errorLog;
  }

  /**
   * Effacer le log des erreurs
   */
  clearErrorLog() {
    this.errorLog = [];
  }

  /**
   * Échapper le HTML
   */
  escapeHTML(text) {
    const div = document.createElement('div');
    div.textContent = text;
    return div.innerHTML;
  }
}

// Export pour utilisation dans d'autres modules
if (typeof module !== 'undefined' && module.exports) {
  module.exports = ErrorHandler;
}
