package dev.lions.unionflow.server.api.enums.notification;

/**
 * Énumération des statuts de notification dans UnionFlow
 *
 * <p>Cette énumération définit les différents états qu'une notification peut avoir tout au long de
 * son cycle de vie, de la création à l'archivage.
 *
 * @author UnionFlow Team
 * @version 1.0
 * @since 2025-01-16
 */
public enum StatutNotification {

  // === STATUTS DE CRÉATION ===
  BROUILLON(
      "Brouillon",
      "draft",
      "La notification est en cours de création",
      "edit",
      "#9E9E9E",
      false,
      false),

  PROGRAMMEE(
      "Programmée",
      "scheduled",
      "La notification est programmée pour envoi ultérieur",
      "schedule",
      "#FF9800",
      false,
      false),

  EN_ATTENTE(
      "En attente",
      "pending",
      "La notification est en attente d'envoi",
      "hourglass_empty",
      "#FF9800",
      false,
      false),

  // === STATUTS D'ENVOI ===
  EN_COURS_ENVOI(
      "En cours d'envoi",
      "sending",
      "La notification est en cours d'envoi",
      "send",
      "#2196F3",
      false,
      false),

  ENVOYEE(
      "Envoyée",
      "sent",
      "La notification a été envoyée avec succès",
      "check_circle",
      "#4CAF50",
      true,
      false),

  ECHEC_ENVOI(
      "Échec d'envoi",
      "failed",
      "L'envoi de la notification a échoué",
      "error",
      "#F44336",
      true,
      true),

  PARTIELLEMENT_ENVOYEE(
      "Partiellement envoyée",
      "partial",
      "La notification a été envoyée à certains destinataires seulement",
      "warning",
      "#FF9800",
      true,
      true),

  // === STATUTS DE RÉCEPTION ===
  RECUE(
      "Reçue",
      "received",
      "La notification a été reçue par l'appareil",
      "download_done",
      "#4CAF50",
      true,
      false),

  AFFICHEE(
      "Affichée",
      "displayed",
      "La notification a été affichée à l'utilisateur",
      "visibility",
      "#2196F3",
      true,
      false),

  OUVERTE(
      "Ouverte",
      "opened",
      "L'utilisateur a ouvert la notification",
      "open_in_new",
      "#4CAF50",
      true,
      false),

  IGNOREE(
      "Ignorée",
      "ignored",
      "La notification a été ignorée par l'utilisateur",
      "visibility_off",
      "#9E9E9E",
      true,
      false),

  // === STATUTS D'INTERACTION ===
  LUE(
      "Lue",
      "read",
      "La notification a été lue par l'utilisateur",
      "mark_email_read",
      "#4CAF50",
      true,
      false),

  NON_LUE(
      "Non lue",
      "unread",
      "La notification n'a pas encore été lue",
      "mark_email_unread",
      "#FF9800",
      true,
      false),

  MARQUEE_IMPORTANTE(
      "Marquée importante",
      "starred",
      "L'utilisateur a marqué la notification comme importante",
      "star",
      "#FF9800",
      true,
      false),

  ACTION_EXECUTEE(
      "Action exécutée",
      "action_done",
      "L'utilisateur a exécuté l'action demandée",
      "task_alt",
      "#4CAF50",
      true,
      false),

  // === STATUTS DE GESTION ===
  SUPPRIMEE(
      "Supprimée",
      "deleted",
      "La notification a été supprimée par l'utilisateur",
      "delete",
      "#F44336",
      false,
      false),

  ARCHIVEE(
      "Archivée", "archived", "La notification a été archivée", "archive", "#9E9E9E", false, false),

  EXPIREE(
      "Expirée",
      "expired",
      "La notification a dépassé sa durée de vie",
      "schedule",
      "#9E9E9E",
      false,
      false),

  ANNULEE(
      "Annulée",
      "cancelled",
      "L'envoi de la notification a été annulé",
      "cancel",
      "#F44336",
      false,
      true),

  // === STATUTS D'ERREUR ===
  ERREUR_TECHNIQUE(
      "Erreur technique",
      "error",
      "Une erreur technique a empêché le traitement",
      "bug_report",
      "#F44336",
      false,
      true),

  DESTINATAIRE_INVALIDE(
      "Destinataire invalide",
      "invalid_recipient",
      "Le destinataire n'est pas valide",
      "person_off",
      "#F44336",
      false,
      true),

  TOKEN_INVALIDE(
      "Token invalide",
      "invalid_token",
      "Le token FCM du destinataire est invalide",
      "key_off",
      "#F44336",
      false,
      true),

  QUOTA_DEPASSE(
      "Quota dépassé",
      "quota_exceeded",
      "Le quota d'envoi a été dépassé",
      "block",
      "#F44336",
      false,
      true);

  private final String libelle;
  private final String code;
  private final String description;
  private final String icone;
  private final String couleur;
  private final boolean visibleUtilisateur;
  private final boolean necessiteAttention;

  /**
   * Constructeur de l'énumération StatutNotification
   *
   * @param libelle Le libellé affiché à l'utilisateur
   * @param code Le code technique du statut
   * @param description La description détaillée du statut
   * @param icone L'icône Material Design
   * @param couleur La couleur hexadécimale
   * @param visibleUtilisateur true si visible à l'utilisateur final
   * @param necessiteAttention true si le statut nécessite une attention particulière
   */
  StatutNotification(
      String libelle,
      String code,
      String description,
      String icone,
      String couleur,
      boolean visibleUtilisateur,
      boolean necessiteAttention) {
    this.libelle = libelle;
    this.code = code;
    this.description = description;
    this.icone = icone;
    this.couleur = couleur;
    this.visibleUtilisateur = visibleUtilisateur;
    this.necessiteAttention = necessiteAttention;
  }

  /**
   * Retourne le libellé du statut
   *
   * @return Le libellé affiché à l'utilisateur
   */
  public String getLibelle() {
    return libelle;
  }

  /**
   * Retourne le code technique du statut
   *
   * @return Le code technique
   */
  public String getCode() {
    return code;
  }

  /**
   * Retourne la description du statut
   *
   * @return La description détaillée
   */
  public String getDescription() {
    return description;
  }

  /**
   * Retourne l'icône du statut
   *
   * @return L'icône Material Design
   */
  public String getIcone() {
    return icone;
  }

  /**
   * Retourne la couleur du statut
   *
   * @return Le code couleur hexadécimal
   */
  public String getCouleur() {
    return couleur;
  }

  /**
   * Vérifie si le statut est visible à l'utilisateur final
   *
   * @return true si visible à l'utilisateur
   */
  public boolean isVisibleUtilisateur() {
    return visibleUtilisateur;
  }

  /**
   * Vérifie si le statut nécessite une attention particulière
   *
   * @return true si le statut nécessite attention
   */
  public boolean isNecessiteAttention() {
    return necessiteAttention;
  }

  /**
   * Vérifie si le statut indique un succès
   *
   * @return true si le statut indique un succès
   */
  public boolean isSucces() {
    return this == ENVOYEE
        || this == RECUE
        || this == AFFICHEE
        || this == OUVERTE
        || this == LUE
        || this == ACTION_EXECUTEE;
  }

  /**
   * Vérifie si le statut indique une erreur
   *
   * @return true si le statut indique une erreur
   */
  public boolean isErreur() {
    return this == ECHEC_ENVOI
        || this == ERREUR_TECHNIQUE
        || this == DESTINATAIRE_INVALIDE
        || this == TOKEN_INVALIDE
        || this == QUOTA_DEPASSE;
  }

  /**
   * Vérifie si le statut indique un état en cours
   *
   * @return true si le statut indique un traitement en cours
   */
  public boolean isEnCours() {
    return this == PROGRAMMEE || this == EN_ATTENTE || this == EN_COURS_ENVOI;
  }

  /**
   * Vérifie si le statut indique un état final
   *
   * @return true si le statut est final (pas de transition possible)
   */
  public boolean isFinal() {
    return this == SUPPRIMEE
        || this == ARCHIVEE
        || this == EXPIREE
        || this == ANNULEE
        || isErreur();
  }

  /**
   * Vérifie si le statut permet la modification
   *
   * @return true si la notification peut encore être modifiée
   */
  public boolean permetModification() {
    return this == BROUILLON || this == PROGRAMMEE;
  }

  /**
   * Vérifie si le statut permet l'annulation
   *
   * @return true si la notification peut être annulée
   */
  public boolean permetAnnulation() {
    return this == PROGRAMMEE || this == EN_ATTENTE;
  }

  /**
   * Retourne la priorité d'affichage du statut
   *
   * @return La priorité (1=haute, 5=basse)
   */
  public int getPrioriteAffichage() {
    if (isErreur()) return 1;
    if (necessiteAttention) return 2;
    if (isEnCours()) return 3;
    if (isSucces()) return 4;
    return 5;
  }

  /**
   * Retourne les statuts suivants possibles
   *
   * @return Un tableau des statuts de transition possibles
   */
  public StatutNotification[] getStatutsSuivantsPossibles() {
    return switch (this) {
      case BROUILLON -> new StatutNotification[] {PROGRAMMEE, EN_ATTENTE, ANNULEE};
      case PROGRAMMEE -> new StatutNotification[] {EN_ATTENTE, EN_COURS_ENVOI, ANNULEE};
      case EN_ATTENTE -> new StatutNotification[] {EN_COURS_ENVOI, ECHEC_ENVOI, ANNULEE};
      case EN_COURS_ENVOI -> new StatutNotification[] {ENVOYEE, PARTIELLEMENT_ENVOYEE, ECHEC_ENVOI};
      case ENVOYEE -> new StatutNotification[] {RECUE, ECHEC_ENVOI};
      case RECUE -> new StatutNotification[] {AFFICHEE, IGNOREE};
      case AFFICHEE -> new StatutNotification[] {OUVERTE, LUE, NON_LUE, IGNOREE};
      case OUVERTE -> new StatutNotification[] {LUE, ACTION_EXECUTEE, MARQUEE_IMPORTANTE};
      case NON_LUE -> new StatutNotification[] {LUE, OUVERTE, SUPPRIMEE, ARCHIVEE};
      case LUE ->
          new StatutNotification[] {ACTION_EXECUTEE, MARQUEE_IMPORTANTE, SUPPRIMEE, ARCHIVEE};
      default -> new StatutNotification[] {};
    };
  }

  /**
   * Trouve un statut par son code
   *
   * @param code Le code du statut
   * @return Le statut correspondant ou null si non trouvé
   */
  public static StatutNotification parCode(String code) {
    for (StatutNotification statut : values()) {
      if (statut.getCode().equals(code)) {
        return statut;
      }
    }
    return null;
  }

  /**
   * Retourne tous les statuts visibles à l'utilisateur
   *
   * @return Un tableau des statuts visibles
   */
  public static StatutNotification[] getStatutsVisibles() {
    return java.util.Arrays.stream(values())
        .filter(StatutNotification::isVisibleUtilisateur)
        .toArray(StatutNotification[]::new);
  }

  /**
   * Retourne tous les statuts d'erreur
   *
   * @return Un tableau des statuts d'erreur
   */
  public static StatutNotification[] getStatutsErreur() {
    return java.util.Arrays.stream(values())
        .filter(StatutNotification::isErreur)
        .toArray(StatutNotification[]::new);
  }
}
