package dev.lions.utils;

import jakarta.faces.application.FacesMessage;
import jakarta.faces.context.FacesContext;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;

import lombok.extern.slf4j.Slf4j;

import java.util.List;
import java.util.ResourceBundle;
import java.util.Locale;

/**
 * Utilitaire pour la gestion des messages dans l'interface utilisateur.
 * Cette classe fournit des méthodes centralisées pour l'affichage de messages
 * et notifications avec support de la localisation.
 */
@Slf4j
public final class MessageUtils {

  private static final String MESSAGE_BUNDLE = "messages";
  private static final int MAX_MESSAGES = 10;

  // Constructeur privé pour empêcher l'instanciation
  private MessageUtils() {
    throw new AssertionError("Cette classe utilitaire ne doit pas être instanciée");
  }

  /**
   * Ajoute un message de succès.
   *
   * @param summary Titre du message
   * @param detail Détail du message
   */
  public static void addSuccessMessage(@NotBlank String summary, String detail) {
    log.debug("Ajout d'un message de succès : {}", summary);
    addMessage(FacesMessage.SEVERITY_INFO, summary, detail);
  }

  /**
   * Ajoute un message d'erreur.
   *
   * @param summary Titre du message
   * @param detail Détail du message
   */
  public static void addErrorMessage(@NotBlank String summary, String detail) {
    log.warn("Ajout d'un message d'erreur : {}", summary);
    addMessage(FacesMessage.SEVERITY_ERROR, summary, detail);
  }

  /**
   * Ajoute un message d'avertissement.
   *
   * @param summary Titre du message
   * @param detail Détail du message
   */
  public static void addWarningMessage(@NotBlank String summary, String detail) {
    log.debug("Ajout d'un message d'avertissement : {}", summary);
    addMessage(FacesMessage.SEVERITY_WARN, summary, detail);
  }

  /**
   * Ajoute un message avec clés de traduction.
   *
   * @param severity Niveau de gravité du message
   * @param summaryKey Clé de traduction du titre
   * @param detailKey Clé de traduction du détail
   */
  public static void addMessageWithKey(
      @NotNull FacesMessage.Severity severity,
      @NotBlank String summaryKey,
      String detailKey) {

    ResourceBundle bundle = getMessageBundle();
    String summary = getTranslation(bundle, summaryKey, summaryKey);
    String detail = detailKey != null ?
                    getTranslation(bundle, detailKey, detailKey) : null;

    addMessage(severity, summary, detail);
  }

  /**
   * Ajoute un message avec paramètres de substitution.
   *
   * @param severity Niveau de gravité du message
   * @param summaryKey Clé de traduction du titre
   * @param detailKey Clé de traduction du détail
   * @param params Paramètres de substitution
   */
  public static void addMessageWithParams(
      @NotNull FacesMessage.Severity severity,
      @NotBlank String summaryKey,
      String detailKey,
      Object... params) {

    ResourceBundle bundle = getMessageBundle();
    String summary = formatMessage(getTranslation(bundle, summaryKey, summaryKey), params);
    String detail = detailKey != null ?
                    formatMessage(getTranslation(bundle, detailKey, detailKey), params) : null;

    addMessage(severity, summary, detail);
  }

  /**
   * Vérifie s'il existe des messages d'erreur.
   *
   * @return true si des erreurs sont présentes
   */
  public static boolean hasErrorMessages() {
    return FacesContext.getCurrentInstance()
                       .getMessageList()
                       .stream()
                       .anyMatch(m -> m.getSeverity() == FacesMessage.SEVERITY_ERROR);
  }

  /**
   * Récupère tous les messages actuels.
   *
   * @return Liste des messages
   */
  public static List<FacesMessage> getCurrentMessages() {
    return FacesContext.getCurrentInstance().getMessageList();
  }

  /**
   * Efface tous les messages actuels.
   */
  public static void clearMessages() {
    FacesContext.getCurrentInstance().getMessageList().clear();
  }

  /**
   * Ajoute un message dans le contexte Faces.
   */
  private static void addMessage(
      FacesMessage.Severity severity,
      String summary,
      String detail) {

    // Limite le nombre de messages pour éviter une surcharge
    if (getCurrentMessages().size() >= MAX_MESSAGES) {
      log.warn("Nombre maximum de messages atteint ({})", MAX_MESSAGES);
      return;
    }

    FacesMessage message = new FacesMessage(severity, summary, detail);
    FacesContext.getCurrentInstance().addMessage(null, message);
  }

  /**
   * Récupère le bundle de messages pour la locale courante.
   */
  private static ResourceBundle getMessageBundle() {
    Locale locale = FacesContext.getCurrentInstance()
                                .getViewRoot()
                                .getLocale();
    return ResourceBundle.getBundle(MESSAGE_BUNDLE, locale);
  }

  /**
   * Récupère une traduction avec fallback.
   */
  private static String getTranslation(
      ResourceBundle bundle,
      String key,
      String defaultValue) {
    try {
      return bundle.getString(key);
    } catch (Exception e) {
      log.warn("Clé de traduction non trouvée : {}", key);
      return defaultValue;
    }
  }

  /**
   * Formate un message avec des paramètres.
   */
  private static String formatMessage(String message, Object... params) {
    try {
      return String.format(message, params);
    } catch (Exception e) {
      log.warn("Erreur lors du formatage du message : {}", e.getMessage());
      return message;
    }
  }
}