package dev.lions.unionflow.server.entity.mutuelle;

import dev.lions.unionflow.server.entity.Organisation;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.UUID;

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

@DisplayName("ParametresFinanciersMutuelle — entité")
class ParametresFinanciersMutuellTest {

    // ─── constructeur no-arg + setters/getters ────────────────────────────────

    @Test
    @DisplayName("constructeur no-arg : tous les champs par défaut présents")
    void noArgConstructor_defaultsPresent() {
        ParametresFinanciersMutuelle p = new ParametresFinanciersMutuelle();

        assertThat(p.getOrganisation()).isNull();
        assertThat(p.getValeurNominaleParDefaut()).isNull(); // Lombok @Builder.Default ne s'active pas avec new
        assertThat(p.getProchaineCalculInterets()).isNull();
        assertThat(p.getDernierCalculInterets()).isNull();
    }

    @Test
    @DisplayName("setters et getters — valeurs explicites")
    void settersGetters() {
        ParametresFinanciersMutuelle p = new ParametresFinanciersMutuelle();

        Organisation org = new Organisation();
        org.setId(UUID.randomUUID());
        p.setOrganisation(org);

        p.setValeurNominaleParDefaut(new BigDecimal("10000"));
        p.setTauxInteretAnnuelEpargne(new BigDecimal("0.05"));
        p.setTauxDividendePartsAnnuel(new BigDecimal("0.07"));
        p.setPeriodiciteCalcul("TRIMESTRIEL");
        p.setSeuilMinEpargneInterets(new BigDecimal("500"));
        LocalDate prochaine = LocalDate.of(2026, 7, 1);
        p.setProchaineCalculInterets(prochaine);
        LocalDate dernier = LocalDate.of(2026, 4, 1);
        p.setDernierCalculInterets(dernier);
        p.setDernierNbComptesTraites(42);

        assertThat(p.getOrganisation()).isSameAs(org);
        assertThat(p.getValeurNominaleParDefaut()).isEqualByComparingTo("10000");
        assertThat(p.getTauxInteretAnnuelEpargne()).isEqualByComparingTo("0.05");
        assertThat(p.getTauxDividendePartsAnnuel()).isEqualByComparingTo("0.07");
        assertThat(p.getPeriodiciteCalcul()).isEqualTo("TRIMESTRIEL");
        assertThat(p.getSeuilMinEpargneInterets()).isEqualByComparingTo("500");
        assertThat(p.getProchaineCalculInterets()).isEqualTo(prochaine);
        assertThat(p.getDernierCalculInterets()).isEqualTo(dernier);
        assertThat(p.getDernierNbComptesTraites()).isEqualTo(42);
    }

    // ─── builder ──────────────────────────────────────────────────────────────

    @Test
    @DisplayName("builder : valeurs par défaut (@Builder.Default)")
    void builder_defaults() {
        ParametresFinanciersMutuelle p = ParametresFinanciersMutuelle.builder().build();

        assertThat(p.getValeurNominaleParDefaut()).isEqualByComparingTo("5000");
        assertThat(p.getTauxInteretAnnuelEpargne()).isEqualByComparingTo("0.03");
        assertThat(p.getTauxDividendePartsAnnuel()).isEqualByComparingTo("0.05");
        assertThat(p.getPeriodiciteCalcul()).isEqualTo("MENSUEL");
        assertThat(p.getSeuilMinEpargneInterets()).isEqualByComparingTo("0");
        assertThat(p.getDernierNbComptesTraites()).isEqualTo(0);
    }

    @Test
    @DisplayName("builder : valeurs personnalisées")
    void builder_customValues() {
        Organisation org = new Organisation();
        org.setId(UUID.randomUUID());

        LocalDate prochaine = LocalDate.of(2026, 10, 1);
        LocalDate dernier = LocalDate.of(2026, 7, 1);

        ParametresFinanciersMutuelle p = ParametresFinanciersMutuelle.builder()
                .organisation(org)
                .valeurNominaleParDefaut(new BigDecimal("2500"))
                .tauxInteretAnnuelEpargne(new BigDecimal("0.04"))
                .tauxDividendePartsAnnuel(new BigDecimal("0.06"))
                .periodiciteCalcul("ANNUEL")
                .seuilMinEpargneInterets(new BigDecimal("1000"))
                .prochaineCalculInterets(prochaine)
                .dernierCalculInterets(dernier)
                .dernierNbComptesTraites(15)
                .build();

        assertThat(p.getOrganisation()).isSameAs(org);
        assertThat(p.getValeurNominaleParDefaut()).isEqualByComparingTo("2500");
        assertThat(p.getTauxInteretAnnuelEpargne()).isEqualByComparingTo("0.04");
        assertThat(p.getTauxDividendePartsAnnuel()).isEqualByComparingTo("0.06");
        assertThat(p.getPeriodiciteCalcul()).isEqualTo("ANNUEL");
        assertThat(p.getSeuilMinEpargneInterets()).isEqualByComparingTo("1000");
        assertThat(p.getProchaineCalculInterets()).isEqualTo(prochaine);
        assertThat(p.getDernierCalculInterets()).isEqualTo(dernier);
        assertThat(p.getDernierNbComptesTraites()).isEqualTo(15);
    }

    // ─── AllArgsConstructor ───────────────────────────────────────────────────

    @Test
    @DisplayName("AllArgsConstructor : instanciation complète")
    void allArgsConstructor() {
        Organisation org = new Organisation();
        BigDecimal valeur = new BigDecimal("5000");
        BigDecimal tauxEpargne = new BigDecimal("0.03");
        BigDecimal tauxDivide = new BigDecimal("0.05");
        String periodicite = "MENSUEL";
        BigDecimal seuil = BigDecimal.ZERO;
        LocalDate prochaine = LocalDate.of(2026, 6, 1);
        LocalDate dernier = LocalDate.of(2026, 3, 1);
        int nbComptes = 10;

        ParametresFinanciersMutuelle p = new ParametresFinanciersMutuelle(
                org, valeur, tauxEpargne, tauxDivide, periodicite, seuil,
                prochaine, dernier, nbComptes);

        assertThat(p.getOrganisation()).isSameAs(org);
        assertThat(p.getValeurNominaleParDefaut()).isEqualByComparingTo("5000");
        assertThat(p.getTauxInteretAnnuelEpargne()).isEqualByComparingTo("0.03");
        assertThat(p.getTauxDividendePartsAnnuel()).isEqualByComparingTo("0.05");
        assertThat(p.getPeriodiciteCalcul()).isEqualTo("MENSUEL");
        assertThat(p.getSeuilMinEpargneInterets()).isEqualByComparingTo("0");
        assertThat(p.getProchaineCalculInterets()).isEqualTo(prochaine);
        assertThat(p.getDernierCalculInterets()).isEqualTo(dernier);
        assertThat(p.getDernierNbComptesTraites()).isEqualTo(10);
    }

    // ─── equals / hashCode / toString ─────────────────────────────────────────

    @Test
    @DisplayName("equals : deux instances avec même id sont égales")
    void equals_sameId() {
        UUID id = UUID.randomUUID();
        ParametresFinanciersMutuelle a = ParametresFinanciersMutuelle.builder()
                .valeurNominaleParDefaut(new BigDecimal("5000"))
                .tauxInteretAnnuelEpargne(new BigDecimal("0.03"))
                .tauxDividendePartsAnnuel(new BigDecimal("0.05"))
                .periodiciteCalcul("MENSUEL")
                .seuilMinEpargneInterets(BigDecimal.ZERO)
                .dernierNbComptesTraites(0)
                .build();
        a.setId(id);

        ParametresFinanciersMutuelle b = ParametresFinanciersMutuelle.builder()
                .valeurNominaleParDefaut(new BigDecimal("5000"))
                .tauxInteretAnnuelEpargne(new BigDecimal("0.03"))
                .tauxDividendePartsAnnuel(new BigDecimal("0.05"))
                .periodiciteCalcul("MENSUEL")
                .seuilMinEpargneInterets(BigDecimal.ZERO)
                .dernierNbComptesTraites(0)
                .build();
        b.setId(id);

        assertThat(a).isEqualTo(b);
        assertThat(a.hashCode()).isEqualTo(b.hashCode());
    }

    @Test
    @DisplayName("equals : deux instances avec id différents ne sont pas égales")
    void equals_differentId() {
        ParametresFinanciersMutuelle a = ParametresFinanciersMutuelle.builder().build();
        a.setId(UUID.randomUUID());
        ParametresFinanciersMutuelle b = ParametresFinanciersMutuelle.builder().build();
        b.setId(UUID.randomUUID());

        assertThat(a).isNotEqualTo(b);
    }

    @Test
    @DisplayName("toString : non null et non vide")
    void toString_notNull() {
        ParametresFinanciersMutuelle p = ParametresFinanciersMutuelle.builder().build();
        assertThat(p.toString()).isNotNull().isNotEmpty();
    }

    // ─── héritage BaseEntity ───────────────────────────────────────────────────

    @Test
    @DisplayName("héritage BaseEntity : setId / getId fonctionnels")
    void baseEntity_idFieldsWork() {
        ParametresFinanciersMutuelle p = new ParametresFinanciersMutuelle();
        UUID id = UUID.randomUUID();
        p.setId(id);
        p.setActif(true);
        p.setCreePar("admin@test.com");
        p.setModifiePar("admin2@test.com");

        assertThat(p.getId()).isEqualTo(id);
        assertThat(p.getActif()).isTrue();
        assertThat(p.getCreePar()).isEqualTo("admin@test.com");
        assertThat(p.getModifiePar()).isEqualTo("admin2@test.com");
    }

    @Test
    @DisplayName("marquerCommeModifie : met à jour modifiePar et dateModification")
    void marquerCommeModifie_updatesFields() {
        ParametresFinanciersMutuelle p = new ParametresFinanciersMutuelle();
        p.marquerCommeModifie("gestionnaire@test.com");

        assertThat(p.getModifiePar()).isEqualTo("gestionnaire@test.com");
        assertThat(p.getDateModification()).isNotNull();
    }
}
