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

import static org.assertj.core.api.Assertions.assertThat;

import dev.lions.unionflow.server.api.enums.abonnement.StatutAbonnement;
import dev.lions.unionflow.server.api.enums.abonnement.StatutFormule;
import dev.lions.unionflow.server.api.enums.abonnement.TypeFormule;
import dev.lions.unionflow.server.api.enums.evenement.PrioriteEvenement;
import dev.lions.unionflow.server.api.enums.evenement.StatutEvenement;
import dev.lions.unionflow.server.api.enums.evenement.TypeEvenementMetier;
import dev.lions.unionflow.server.api.enums.finance.StatutCotisation;
import dev.lions.unionflow.server.api.enums.membre.StatutMembre;
import dev.lions.unionflow.server.api.enums.organisation.StatutOrganisation;
import dev.lions.unionflow.server.api.enums.organisation.TypeOrganisation;
import dev.lions.unionflow.server.api.enums.paiement.StatutSession;
import dev.lions.unionflow.server.api.enums.paiement.StatutTraitement;
import dev.lions.unionflow.server.api.enums.paiement.TypeEvenement;
import dev.lions.unionflow.server.api.enums.solidarite.PrioriteAide;
import dev.lions.unionflow.server.api.enums.solidarite.StatutAide;
import dev.lions.unionflow.server.api.enums.solidarite.StatutEvaluation;
import dev.lions.unionflow.server.api.enums.solidarite.StatutProposition;
import dev.lions.unionflow.server.api.enums.solidarite.TypeAide;
import dev.lions.unionflow.server.api.enums.solidarite.TypeEvaluation;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;

/**
 * Tests de validation de la refactorisation des énumérations UnionFlow Vérifie
 * que toutes les enums
 * sont correctement séparées et fonctionnelles
 *
 * @author UnionFlow Team
 * @version 1.0
 * @since 2025-01-10
 */
@DisplayName("Tests de Refactorisation des Énumérations")
class EnumsRefactoringTest {

  @Test
  @DisplayName("Test de base - toutes les enums sont accessibles")
  void testEnumsAccessibles() {
    assertThat(StatutMembre.ACTIF).isNotNull();
    assertThat(TypeOrganisation.LIONS_CLUB).isNotNull();
  }

  @Nested
  @DisplayName("Énumérations Organisation")
  class OrganisationEnumsTest {

    @Test
    @DisplayName("TypeOrganisation - Tous les types disponibles")
    void testTypeOrganisationTousLesTypes() {
      // Given & When & Then
      assertThat(TypeOrganisation.LIONS_CLUB.getLibelle()).isEqualTo("Lions Club");
      assertThat(TypeOrganisation.ASSOCIATION.getLibelle()).isEqualTo("Association");
      assertThat(TypeOrganisation.FEDERATION.getLibelle()).isEqualTo("Fédération / Union d'associations");
      assertThat(TypeOrganisation.ONG.getLibelle()).isEqualTo("ONG / Association humanitaire");
      assertThat(TypeOrganisation.SYNDICAT.getLibelle()).isEqualTo("Syndicat non partisan");
      assertThat(TypeOrganisation.MUTUELLE_SANTE.getLibelle()).isEqualTo("Mutuelle de santé");
      assertThat(TypeOrganisation.MUTUELLE_EPARGNE_CREDIT.getLibelle()).isEqualTo("Mutuelle d'épargne et de crédit");
      assertThat(TypeOrganisation.TONTINE.getLibelle()).isEqualTo("Tontine / épargne rotative");
    }

    @Test
    @DisplayName("StatutOrganisation - Tous les statuts disponibles")
    void testStatutOrganisationTousLesStatuts() {
      // Given & When & Then
      assertThat(StatutOrganisation.ACTIVE.getLibelle()).isEqualTo("Active");
      assertThat(StatutOrganisation.INACTIVE.getLibelle()).isEqualTo("Inactive");
      assertThat(StatutOrganisation.SUSPENDUE.getLibelle()).isEqualTo("Suspendue");
      assertThat(StatutOrganisation.EN_CREATION.getLibelle()).isEqualTo("En Création");
      assertThat(StatutOrganisation.DISSOUTE.getLibelle()).isEqualTo("Dissoute");
    }
  }

  @Nested
  @DisplayName("Énumérations Membre")
  class MembreEnumsTest {

    @Test
    @DisplayName("StatutMembre - Tous les statuts disponibles")
    void testStatutMembreTousLesStatuts() {
      // Given & When & Then
      assertThat(StatutMembre.ACTIF.getLibelle()).isEqualTo("Actif");
      assertThat(StatutMembre.INACTIF.getLibelle()).contains("Inactif");
      assertThat(StatutMembre.SUSPENDU.getLibelle()).contains("Suspendu");
      assertThat(StatutMembre.RADIE.getLibelle()).contains("Radié");
      assertThat(StatutMembre.DEMISSIONNAIRE.getLibelle()).isNotNull();
      assertThat(StatutMembre.HONORAIRE.getLibelle()).isNotNull();
      assertThat(StatutMembre.DECEDE.getLibelle()).isNotNull();
    }
  }

  @Nested
  @DisplayName("Énumérations Paiement")
  class PaiementEnumsTest {

    @Test
    @DisplayName("StatutSession - Tous les statuts disponibles")
    void testStatutSessionTousLesStatuts() {
      // Given & When & Then
      assertThat(StatutSession.PENDING.getLibelle()).isEqualTo("En attente");
      assertThat(StatutSession.COMPLETED.getLibelle()).isEqualTo("Complétée");
      assertThat(StatutSession.CANCELLED.getLibelle()).isEqualTo("Annulée");
      assertThat(StatutSession.EXPIRED.getLibelle()).isEqualTo("Expirée");
      assertThat(StatutSession.FAILED.getLibelle()).isEqualTo("Échouée");
    }

    @Test
    @DisplayName("TypeEvenement - Méthode fromCode")
    void testTypeEvenementFromCode() {
      // Given & When & Then
      assertThat(TypeEvenement.fromCode("checkout.complete"))
          .isEqualTo(TypeEvenement.CHECKOUT_COMPLETE);
      assertThat(TypeEvenement.fromCode("payout.failed")).isEqualTo(TypeEvenement.PAYOUT_FAILED);
      assertThat(TypeEvenement.fromCode("balance.updated"))
          .isEqualTo(TypeEvenement.BALANCE_UPDATED);
      assertThat(TypeEvenement.fromCode("code_inexistant")).isNull();
    }

    @Test
    @DisplayName("StatutTraitement - Tous les statuts disponibles")
    void testStatutTraitementTousLesStatuts() {
      // Given & When & Then
      assertThat(StatutTraitement.RECU.getLibelle()).isEqualTo("Reçu");
      assertThat(StatutTraitement.EN_COURS.getLibelle()).isEqualTo("En cours de traitement");
      assertThat(StatutTraitement.TRAITE.getLibelle()).isEqualTo("Traité avec succès");
      assertThat(StatutTraitement.ECHEC.getLibelle()).isEqualTo("Échec de traitement");
      assertThat(StatutTraitement.IGNORE.getLibelle()).isEqualTo("Ignoré");
    }
  }

  @Nested
  @DisplayName("Énumérations Abonnement")
  class AbonnementEnumsTest {

    @Test
    @DisplayName("TypeFormule - Tous les types disponibles")
    void testTypeFormuleTousLesTypes() {
      // Given & When & Then
      assertThat(TypeFormule.STARTER.getLibelle()).contains("Starter");
      assertThat(TypeFormule.STANDARD.getLibelle()).contains("Standard");
      assertThat(TypeFormule.PREMIUM.getLibelle()).contains("Premium");
      assertThat(TypeFormule.CRYSTAL.getLibelle()).contains("Crystal");
    }

    @Test
    @DisplayName("StatutFormule - Tous les statuts disponibles")
    void testStatutFormuleTousLesStatuts() {
      // Given & When & Then
      assertThat(StatutFormule.ACTIVE.getLibelle()).isEqualTo("Active");
      assertThat(StatutFormule.INACTIVE.getLibelle()).isEqualTo("Inactive");
      assertThat(StatutFormule.ARCHIVEE.getLibelle()).isEqualTo("Archivée");
      assertThat(StatutFormule.BIENTOT_DISPONIBLE.getLibelle()).isEqualTo("Bientôt Disponible");
    }

    @Test
    @DisplayName("StatutAbonnement - Tous les statuts disponibles")
    void testStatutAbonnementTousLesStatuts() {
      // Given & When & Then
      assertThat(StatutAbonnement.ACTIF.getLibelle()).isEqualTo("Actif");
      assertThat(StatutAbonnement.SUSPENDU.getLibelle()).isEqualTo("Suspendu");
      assertThat(StatutAbonnement.EXPIRE.getLibelle()).isEqualTo("Expiré");
      assertThat(StatutAbonnement.ANNULE.getLibelle()).isEqualTo("Annulé");
      assertThat(StatutAbonnement.EN_ATTENTE_PAIEMENT.getLibelle())
          .isEqualTo("En attente de paiement");
    }
  }

  @Nested
  @DisplayName("Énumérations Événement")
  class EvenementEnumsTest {

    @Test
    @DisplayName("TypeEvenementMetier - Tous les types disponibles")
    void testTypeEvenementMetierTousLesTypes() {
      // Given & When & Then
      assertThat(TypeEvenementMetier.ASSEMBLEE_GENERALE.getLibelle())
          .isEqualTo("Assemblée Générale");
      assertThat(TypeEvenementMetier.FORMATION.getLibelle()).isEqualTo("Formation");
      assertThat(TypeEvenementMetier.ACTIVITE_SOCIALE.getLibelle()).isEqualTo("Activité Sociale");
      assertThat(TypeEvenementMetier.ACTION_CARITATIVE.getLibelle()).isEqualTo("Action Caritative");
      assertThat(TypeEvenementMetier.REUNION_BUREAU.getLibelle()).isEqualTo("Réunion de Bureau");
      assertThat(TypeEvenementMetier.CONFERENCE.getLibelle()).isEqualTo("Conférence");
      assertThat(TypeEvenementMetier.ATELIER.getLibelle()).isEqualTo("Atelier");
      assertThat(TypeEvenementMetier.CEREMONIE.getLibelle()).isEqualTo("Cérémonie");
      assertThat(TypeEvenementMetier.AUTRE.getLibelle()).isEqualTo("Autre");
    }

    @Test
    @DisplayName("StatutEvenement - Tous les statuts disponibles")
    void testStatutEvenementTousLesStatuts() {
      // Given & When & Then
      assertThat(StatutEvenement.PLANIFIE.getLibelle()).isEqualTo("Planifié");
      assertThat(StatutEvenement.CONFIRME.getLibelle()).isEqualTo("Confirmé");
      assertThat(StatutEvenement.EN_COURS.getLibelle()).isEqualTo("En cours");
      assertThat(StatutEvenement.TERMINE.getLibelle()).isEqualTo("Terminé");
      assertThat(StatutEvenement.ANNULE.getLibelle()).isEqualTo("Annulé");
      assertThat(StatutEvenement.REPORTE.getLibelle()).isEqualTo("Reporté");
    }

    @Test
    @DisplayName("PrioriteEvenement - Toutes les priorités disponibles")
    void testPrioriteEvenementToutesLesPriorites() {
      // Given & When & Then
      assertThat(PrioriteEvenement.CRITIQUE.getLibelle()).isEqualTo("Critique");
      assertThat(PrioriteEvenement.HAUTE.getLibelle()).isEqualTo("Haute");
      assertThat(PrioriteEvenement.NORMALE.getLibelle()).isEqualTo("Normale");
      assertThat(PrioriteEvenement.BASSE.getLibelle()).isEqualTo("Basse");
    }
  }

  @Nested
  @DisplayName("Énumérations Finance")
  class FinanceEnumsTest {

    @Test
    @DisplayName("StatutCotisation - Tous les statuts disponibles")
    void testStatutCotisationTousLesStatuts() {
      // Given & When & Then
      assertThat(StatutCotisation.EN_ATTENTE.getLibelle()).isEqualTo("En attente");
      assertThat(StatutCotisation.PAYEE.getLibelle()).isEqualTo("Payée");
      assertThat(StatutCotisation.PARTIELLEMENT_PAYEE.getLibelle())
          .isEqualTo("Partiellement payée");
      assertThat(StatutCotisation.EN_RETARD.getLibelle()).isEqualTo("En retard");
      assertThat(StatutCotisation.ANNULEE.getLibelle()).isEqualTo("Annulée");
      assertThat(StatutCotisation.REMBOURSEE.getLibelle()).isEqualTo("Remboursée");
    }
  }

  @Nested
  @DisplayName("Énumérations Solidarité")
  class SolidariteEnumsTest {

    @Test
    @DisplayName("TypeAide - Tous les types disponibles")
    void testTypeAideTousLesTypes() {
      // Given & When & Then
      assertThat(TypeAide.AIDE_FINANCIERE_URGENTE.getLibelle())
          .isEqualTo("Aide financière urgente");
      assertThat(TypeAide.AIDE_FRAIS_MEDICAUX.getLibelle()).isEqualTo("Aide frais médicaux");
      assertThat(TypeAide.AIDE_FRAIS_SCOLARITE.getLibelle()).isEqualTo("Aide frais de scolarité");
      assertThat(TypeAide.HEBERGEMENT_URGENCE.getLibelle()).isEqualTo("Hébergement d'urgence");
      assertThat(TypeAide.AIDE_ALIMENTAIRE.getLibelle()).isEqualTo("Aide alimentaire");
      assertThat(TypeAide.CONSEIL_JURIDIQUE.getLibelle()).isEqualTo("Conseil juridique");
      assertThat(TypeAide.AIDE_RECHERCHE_EMPLOI.getLibelle()).isEqualTo("Aide recherche d'emploi");
      assertThat(TypeAide.SOUTIEN_PSYCHOLOGIQUE.getLibelle()).isEqualTo("Soutien psychologique");
      assertThat(TypeAide.AUTRE.getLibelle()).isEqualTo("Autre");
    }

    @Test
    @DisplayName("StatutAide - Tous les statuts disponibles")
    void testStatutAideTousLesStatuts() {
      // Given & When & Then
      assertThat(StatutAide.EN_ATTENTE.getLibelle()).isEqualTo("En attente");
      assertThat(StatutAide.EN_COURS_EVALUATION.getLibelle()).isEqualTo("En cours d'évaluation");
      assertThat(StatutAide.APPROUVEE.getLibelle()).isEqualTo("Approuvée");
      assertThat(StatutAide.REJETEE.getLibelle()).isEqualTo("Rejetée");
      assertThat(StatutAide.EN_COURS_VERSEMENT.getLibelle()).isEqualTo("En cours de versement");
      assertThat(StatutAide.VERSEE.getLibelle()).isEqualTo("Versée");
      assertThat(StatutAide.ANNULEE.getLibelle()).isEqualTo("Annulée");
      assertThat(StatutAide.SUSPENDUE.getLibelle()).isEqualTo("Suspendue");
    }

    @Test
    @DisplayName("PrioriteAide - Toutes les priorités disponibles")
    void testPrioriteAideToutesLesPriorites() {
      // Given & When & Then
      assertThat(PrioriteAide.CRITIQUE.getLibelle()).isEqualTo("Critique");
      assertThat(PrioriteAide.URGENTE.getLibelle()).isEqualTo("Urgente");
      assertThat(PrioriteAide.ELEVEE.getLibelle()).isEqualTo("Élevée");
      assertThat(PrioriteAide.NORMALE.getLibelle()).isEqualTo("Normale");
      assertThat(PrioriteAide.FAIBLE.getLibelle()).isEqualTo("Faible");
    }

    @Test
    @DisplayName("StatutProposition - Tous les statuts disponibles")
    void testStatutPropositionTousLesStatuts() {
      assertThat(StatutProposition.BROUILLON.getLibelle()).isEqualTo("Brouillon");
      assertThat(StatutProposition.ACTIVE.getLibelle()).isEqualTo("Active");
      assertThat(StatutProposition.SUSPENDUE.getLibelle()).isEqualTo("Suspendue");
      assertThat(StatutProposition.TERMINEE.getLibelle()).isEqualTo("Terminée");
      assertThat(StatutProposition.ANNULEE.getLibelle()).isEqualTo("Annulée");
    }

    @Test
    @DisplayName("StatutEvaluation - Tous les statuts disponibles")
    void testStatutEvaluationTousLesStatuts() {
      assertThat(StatutEvaluation.BROUILLON.getLibelle()).isEqualTo("Brouillon");
      assertThat(StatutEvaluation.ACTIVE.getLibelle()).isEqualTo("Active");
      assertThat(StatutEvaluation.MASQUEE.getLibelle()).isEqualTo("Masquée");
    }

    @Test
    @DisplayName("TypeEvaluation - Tous les types disponibles")
    void testTypeEvaluationTousLesTypes() {
      assertThat(TypeEvaluation.SATISFACTION_BENEFICIAIRE.getLibelle()).isEqualTo("Satisfaction du bénéficiaire");
      assertThat(TypeEvaluation.EVALUATION_IMPACT.getLibelle()).isEqualTo("Évaluation d'impact");
    }
  }

  @Nested
  @DisplayName("Tests de Couverture Complète")
  class CouvertureCompleteTest {

    @Test
    @DisplayName("Vérification que toutes les enums ont des valeurs")
    void testToutesLesEnumsOntDesValeurs() {
      // Given & When & Then - Organisation
      assertThat(TypeOrganisation.values()).isNotEmpty();
      assertThat(StatutOrganisation.values()).isNotEmpty();

      // Given & When & Then - Membre
      assertThat(StatutMembre.values()).isNotEmpty();

      // Given & When & Then - Paiement
      assertThat(StatutSession.values()).isNotEmpty();
      assertThat(TypeEvenement.values()).isNotEmpty();
      assertThat(StatutTraitement.values()).isNotEmpty();

      // Given & When & Then - Abonnement
      assertThat(TypeFormule.values()).isNotEmpty();
      assertThat(StatutFormule.values()).isNotEmpty();
      assertThat(StatutAbonnement.values()).isNotEmpty();

      // Given & When & Then - Événement
      assertThat(TypeEvenementMetier.values()).isNotEmpty();

      // Given & When & Then - Finance
      assertThat(StatutCotisation.values()).isNotEmpty();

      // Given & When & Then - Solidarité
      assertThat(TypeAide.values()).isNotEmpty();
      assertThat(StatutAide.values()).isNotEmpty();
      assertThat(StatutProposition.values()).isNotEmpty();
      assertThat(StatutEvaluation.values()).isNotEmpty();
      assertThat(TypeEvaluation.values()).isNotEmpty();
    }
  }
}
