package dev.lions.unionflow.server.api.dto.cotisation.response;

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

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.UUID;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;

/**
 * Tests unitaires pour CotisationResponse.
 * Couvre les propriétés d'affichage membre/organisation (nomCompletMembre,
 * initialesMembre, typeMembre, regionOrganisation, iconeOrganisation).
 *
 * @author UnionFlow Team
 * @version 1.0
 * @since 2026-03-04
 */
@DisplayName("Tests CotisationResponse")
class CotisationResponseTest {

    @Nested
    @DisplayName("Builder et getters – propriétés membre/organisation")
    class BuilderEtGetters {

        @Test
        @DisplayName("builder remplit nomCompletMembre, initialesMembre, typeMembre")
        void builder_remplitProprietesMembre() {
            CotisationResponse r = CotisationResponse.builder()
                    .nomCompletMembre("Jean Dupont")
                    .initialesMembre("JD")
                    .typeMembre("Actif")
                    .nomMembre("Jean Dupont")
                    .numeroMembre("M-001")
                    .build();

            assertThat(r.getNomCompletMembre()).isEqualTo("Jean Dupont");
            assertThat(r.getInitialesMembre()).isEqualTo("JD");
            assertThat(r.getTypeMembre()).isEqualTo("Actif");
        }

        @Test
        @DisplayName("builder remplit regionOrganisation et iconeOrganisation")
        void builder_remplitProprietesOrganisation() {
            CotisationResponse r = CotisationResponse.builder()
                    .nomOrganisation("Club Lions Abidjan")
                    .regionOrganisation("Abidjan")
                    .iconeOrganisation("pi-users")
                    .build();

            assertThat(r.getRegionOrganisation()).isEqualTo("Abidjan");
            assertThat(r.getIconeOrganisation()).isEqualTo("pi-users");
        }

        @Test
        @DisplayName("propriétés null acceptées")
        void builder_accepteNull() {
            CotisationResponse r = CotisationResponse.builder()
                    .numeroReference("REF-1")
                    .build();

            assertThat(r.getNomCompletMembre()).isNull();
            assertThat(r.getInitialesMembre()).isNull();
            assertThat(r.getTypeMembre()).isNull();
            assertThat(r.getRegionOrganisation()).isNull();
            assertThat(r.getIconeOrganisation()).isNull();
        }

        @Test
        @DisplayName("setters mettent à jour les propriétés")
        void setters_mettentAJour() {
            CotisationResponse r = new CotisationResponse();
            r.setNomCompletMembre("Marie Martin");
            r.setInitialesMembre("MM");
            r.setTypeMembre("En attente");
            r.setRegionOrganisation("Dakar");
            r.setIconeOrganisation("pi-building");

            assertThat(r.getNomCompletMembre()).isEqualTo("Marie Martin");
            assertThat(r.getInitialesMembre()).isEqualTo("MM");
            assertThat(r.getTypeMembre()).isEqualTo("En attente");
            assertThat(r.getRegionOrganisation()).isEqualTo("Dakar");
            assertThat(r.getIconeOrganisation()).isEqualTo("pi-building");
        }

        @Test
        @DisplayName("builder remplit typeLibelle, typeSeverity, typeIcon, statutSeverity, statutIcon")
        void builder_remplitTypeEtStatutTag() {
            CotisationResponse r = CotisationResponse.builder()
                    .type("ANNUELLE")
                    .typeLibelle("Annuelle")
                    .typeSeverity("success")
                    .typeIcon("pi-star")
                    .statut("PAYEE")
                    .statutSeverity("success")
                    .statutIcon("pi-check")
                    .build();

            assertThat(r.getType()).isEqualTo("ANNUELLE");
            assertThat(r.getTypeLibelle()).isEqualTo("Annuelle");
            assertThat(r.getTypeSeverity()).isEqualTo("success");
            assertThat(r.getTypeIcon()).isEqualTo("pi-star");
            assertThat(r.getStatutSeverity()).isEqualTo("success");
            assertThat(r.getStatutIcon()).isEqualTo("pi-check");
        }

        @Test
        @DisplayName("builder remplit montant, montantFormatte, dates formatées, retard, mode paiement")
        void builder_remplitAffichage() {
            CotisationResponse r = CotisationResponse.builder()
                    .montant(BigDecimal.valueOf(10000))
                    .montantFormatte("10 000")
                    .dateEcheanceFormattee("15/03/2026")
                    .retardCouleur("text-green-600")
                    .retardTexte("À jour")
                    .datePaiementFormattee("01/03/2026 14:30")
                    .modePaiementIcon("pi-wallet")
                    .modePaiementLibelle("Espèces")
                    .build();

            assertThat(r.getMontant()).isEqualByComparingTo(BigDecimal.valueOf(10000));
            assertThat(r.getMontantFormatte()).isEqualTo("10 000");
            assertThat(r.getDateEcheanceFormattee()).isEqualTo("15/03/2026");
            assertThat(r.getRetardCouleur()).isEqualTo("text-green-600");
            assertThat(r.getRetardTexte()).isEqualTo("À jour");
            assertThat(r.getDatePaiementFormattee()).isEqualTo("01/03/2026 14:30");
            assertThat(r.getModePaiementIcon()).isEqualTo("pi-wallet");
            assertThat(r.getModePaiementLibelle()).isEqualTo("Espèces");
        }
    }

    @Nested
    @DisplayName("Builder complet")
    class BuilderComplet {

        @Test
        @DisplayName("builder avec toutes les propriétés principales")
        void builder_complet() {
            UUID id = UUID.randomUUID();
            UUID membreId = UUID.randomUUID();
            UUID orgId = UUID.randomUUID();
            LocalDate dateEcheance = LocalDate.now().plusMonths(1);
            LocalDateTime datePaiement = LocalDateTime.now();

            CotisationResponse r = CotisationResponse.builder()
                    .numeroReference("COT-2026-001")
                    .membreId(membreId)
                    .nomMembre("Jean Dupont")
                    .nomCompletMembre("Jean Dupont")
                    .initialesMembre("JD")
                    .typeMembre("Actif")
                    .numeroMembre("M-001")
                    .organisationId(orgId)
                    .nomOrganisation("Club Test")
                    .regionOrganisation("Abidjan")
                    .iconeOrganisation("pi-star")
                    .typeCotisation("MENSUELLE")
                    .libelle("Cotisation mars")
                    .montantDu(BigDecimal.valueOf(5000))
                    .montantPaye(BigDecimal.ZERO)
                    .montantRestant(BigDecimal.valueOf(5000))
                    .codeDevise("XOF")
                    .statut("EN_ATTENTE")
                    .dateEcheance(dateEcheance)
                    .datePaiement(datePaiement)
                    .annee(2026)
                    .mois(3)
                    .build();
            r.setId(id);

            assertThat(r.getId()).isEqualTo(id);
            assertThat(r.getNumeroReference()).isEqualTo("COT-2026-001");
            assertThat(r.getMembreId()).isEqualTo(membreId);
            assertThat(r.getNomCompletMembre()).isEqualTo("Jean Dupont");
            assertThat(r.getInitialesMembre()).isEqualTo("JD");
            assertThat(r.getTypeMembre()).isEqualTo("Actif");
            assertThat(r.getOrganisationId()).isEqualTo(orgId);
            assertThat(r.getNomOrganisation()).isEqualTo("Club Test");
            assertThat(r.getRegionOrganisation()).isEqualTo("Abidjan");
            assertThat(r.getIconeOrganisation()).isEqualTo("pi-star");
            assertThat(r.getMontantDu()).isEqualByComparingTo(BigDecimal.valueOf(5000));
            assertThat(r.getStatut()).isEqualTo("EN_ATTENTE");
            assertThat(r.getDateEcheance()).isEqualTo(dateEcheance);
        }
    }
}
