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

/**
 * Énumération des statuts d'événements dans UnionFlow
 *
 * <p>Cette énumération définit les différents états qu'un événement peut avoir tout au long de son
 * cycle de vie, de la planification à la clôture.
 *
 * @author UnionFlow Team
 * @version 1.0
 * @since 2025-09-21
 */
public enum StatutEvenement {

  // === STATUTS DE PLANIFICATION ===
  PLANIFIE(
      "Planifié",
      "planned",
      "L'événement est planifié et en préparation",
      "#2196F3",
      "event",
      false,
      false),

  CONFIRME(
      "Confirmé",
      "confirmed",
      "L'événement est confirmé et les inscriptions sont ouvertes",
      "#4CAF50",
      "event_available",
      false,
      false),

  // === STATUTS D'EXÉCUTION ===
  EN_COURS(
      "En cours",
      "ongoing",
      "L'événement est actuellement en cours",
      "#FF9800",
      "play_circle",
      false,
      false),

  // === STATUTS FINAUX ===
  TERMINE(
      "Terminé",
      "completed",
      "L'événement s'est terminé avec succès",
      "#4CAF50",
      "check_circle",
      true,
      false),

  ANNULE("Annulé", "cancelled", "L'événement a été annulé", "#F44336", "cancel", true, true),

  REPORTE(
      "Reporté",
      "postponed",
      "L'événement a été reporté à une date ultérieure",
      "#FF5722",
      "schedule",
      false,
      false);

  private final String libelle;
  private final String code;
  private final String description;
  private final String couleur;
  private final String icone;
  private final boolean estFinal;
  private final boolean estEchec;

  StatutEvenement(
      String libelle,
      String code,
      String description,
      String couleur,
      String icone,
      boolean estFinal,
      boolean estEchec) {
    this.libelle = libelle;
    this.code = code;
    this.description = description;
    this.couleur = couleur;
    this.icone = icone;
    this.estFinal = estFinal;
    this.estEchec = estEchec;
  }

  // === GETTERS ===

  public String getLibelle() {
    return libelle;
  }

  public String getCode() {
    return code;
  }

  public String getDescription() {
    return description;
  }

  public String getCouleur() {
    return couleur;
  }

  public String getIcone() {
    return icone;
  }

  public boolean isEstFinal() {
    return estFinal;
  }

  public boolean isEstEchec() {
    return estEchec;
  }

  // === MÉTHODES UTILITAIRES ===

  /** Vérifie si l'événement peut être modifié */
  public boolean permetModification() {
    return switch (this) {
      case PLANIFIE, CONFIRME, REPORTE -> true;
      case EN_COURS, TERMINE, ANNULE -> false;
    };
  }

  /** Vérifie si l'événement peut être annulé */
  public boolean permetAnnulation() {
    return switch (this) {
      case PLANIFIE, CONFIRME, EN_COURS, REPORTE -> true;
      case TERMINE, ANNULE -> false;
    };
  }

  /** Vérifie si l'événement est en cours d'exécution */
  public boolean isEnCours() {
    return this == EN_COURS;
  }

  /** Vérifie si l'événement est terminé avec succès */
  public boolean isSucces() {
    return this == TERMINE;
  }

  /** Retourne les statuts finaux */
  public static java.util.List<StatutEvenement> getStatutsFinaux() {
    return java.util.Arrays.stream(values())
        .filter(StatutEvenement::isEstFinal)
        .collect(java.util.stream.Collectors.toList());
  }

  /** Retourne les statuts d'échec */
  public static java.util.List<StatutEvenement> getStatutsEchec() {
    return java.util.Arrays.stream(values())
        .filter(StatutEvenement::isEstEchec)
        .collect(java.util.stream.Collectors.toList());
  }

  /** Vérifie si la transition vers un autre statut est valide */
  public boolean peutTransitionnerVers(StatutEvenement nouveauStatut) {
    if (this == nouveauStatut) return false;
    if (estFinal && nouveauStatut != REPORTE) return false;

    return switch (this) {
      case PLANIFIE ->
          nouveauStatut == CONFIRME || nouveauStatut == ANNULE || nouveauStatut == REPORTE;
      case CONFIRME ->
          nouveauStatut == EN_COURS || nouveauStatut == ANNULE || nouveauStatut == REPORTE;
      case EN_COURS -> nouveauStatut == TERMINE || nouveauStatut == ANNULE;
      case REPORTE -> nouveauStatut == PLANIFIE || nouveauStatut == ANNULE;
      default -> false;
    };
  }

  /** Retourne le niveau de priorité pour l'affichage */
  public int getNiveauPriorite() {
    return switch (this) {
      case EN_COURS -> 1;
      case CONFIRME -> 2;
      case PLANIFIE -> 3;
      case REPORTE -> 4;
      case TERMINE -> 5;
      case ANNULE -> 6;
    };
  }

  // === MÉTHODES STATIQUES ===

  /** Retourne les statuts actifs (non finaux) */
  public static StatutEvenement[] getStatutsActifs() {
    return new StatutEvenement[] {PLANIFIE, CONFIRME, EN_COURS, REPORTE};
  }

  /** Trouve un statut par son code */
  public static StatutEvenement fromCode(String code) {
    if (code == null || code.trim().isEmpty()) {
      return null;
    }
    for (StatutEvenement statut : values()) {
      if (statut.code.equals(code)) {
        return statut;
      }
    }
    return null;
  }

  /** Trouve un statut par son libellé */
  public static StatutEvenement fromLibelle(String libelle) {
    if (libelle == null || libelle.trim().isEmpty()) {
      return null;
    }
    for (StatutEvenement statut : values()) {
      if (statut.libelle.equals(libelle)) {
        return statut;
      }
    }
    return null;
  }

  /** Retourne les transitions possibles depuis ce statut */
  public StatutEvenement[] getTransitionsPossibles() {
    return switch (this) {
      case PLANIFIE -> new StatutEvenement[] {CONFIRME, ANNULE, REPORTE};
      case CONFIRME -> new StatutEvenement[] {EN_COURS, ANNULE, REPORTE};
      case EN_COURS -> new StatutEvenement[] {TERMINE, ANNULE};
      case REPORTE -> new StatutEvenement[] {PLANIFIE, CONFIRME, ANNULE};
      case TERMINE, ANNULE -> new StatutEvenement[] {}; // Aucune transition possible
    };
  }
}
