package dev.lions.unionflow.server.entity;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

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

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

@DisplayName("PaiementObjet")
class PaiementObjetTest {

    private static Paiement newPaiement() {
        Membre m = new Membre();
        m.setId(UUID.randomUUID());
        m.setNumeroMembre("M1");
        m.setPrenom("A");
        m.setNom("B");
        m.setEmail("a@test.com");
        m.setDateNaissance(java.time.LocalDate.now());
        Paiement p = new Paiement();
        p.setId(UUID.randomUUID());
        p.setNumeroReference("PAY-1");
        p.setMontant(BigDecimal.TEN);
        p.setCodeDevise("XOF");
        p.setMethodePaiement("WAVE");
        p.setMembre(m);
        return p;
    }

    @Test
    @DisplayName("getters/setters")
    void gettersSetters() {
        PaiementObjet po = new PaiementObjet();
        po.setPaiement(newPaiement());
        po.setTypeObjetCible("COTISATION");
        po.setObjetCibleId(UUID.randomUUID());
        po.setMontantApplique(new BigDecimal("5000.00"));
        po.setDateApplication(LocalDateTime.now());
        po.setCommentaire("Cotisation janvier");

        assertThat(po.getTypeObjetCible()).isEqualTo("COTISATION");
        assertThat(po.getMontantApplique()).isEqualByComparingTo("5000.00");
        assertThat(po.getCommentaire()).isEqualTo("Cotisation janvier");
    }

    @Test
    @DisplayName("equals et hashCode")
    void equalsHashCode() {
        UUID id = UUID.randomUUID();
        UUID objId = UUID.randomUUID();
        Paiement p = newPaiement();
        PaiementObjet a = new PaiementObjet();
        a.setId(id);
        a.setPaiement(p);
        a.setTypeObjetCible("COTISATION");
        a.setObjetCibleId(objId);
        a.setMontantApplique(BigDecimal.ONE);
        PaiementObjet b = new PaiementObjet();
        b.setId(id);
        b.setPaiement(p);
        b.setTypeObjetCible("COTISATION");
        b.setObjetCibleId(objId);
        b.setMontantApplique(BigDecimal.ONE);
        assertThat(a).isEqualTo(b);
        assertThat(a.hashCode()).isEqualTo(b.hashCode());
    }

    @Test
    @DisplayName("toString non null")
    void toString_nonNull() {
        PaiementObjet po = new PaiementObjet();
        po.setPaiement(newPaiement());
        po.setTypeObjetCible("COTISATION");
        po.setObjetCibleId(UUID.randomUUID());
        po.setMontantApplique(BigDecimal.ONE);
        assertThat(po.toString()).isNotNull().isNotEmpty();
    }

    @Test
    @DisplayName("onCreate initialise dateApplication si null")
    void onCreate_setsDateApplicationWhenNull() {
        PaiementObjet po = new PaiementObjet();
        po.setPaiement(newPaiement());
        po.setTypeObjetCible("COTISATION");
        po.setObjetCibleId(UUID.randomUUID());
        po.setMontantApplique(BigDecimal.ONE);
        // dateApplication est null

        po.onCreate();

        assertThat(po.getDateApplication()).isNotNull();
        assertThat(po.getActif()).isTrue();
    }

    @Test
    @DisplayName("onCreate ne remplace pas une dateApplication existante")
    void onCreate_doesNotOverrideDateApplication() {
        LocalDateTime fixed = LocalDateTime.of(2026, 1, 1, 0, 0);
        PaiementObjet po = new PaiementObjet();
        po.setDateApplication(fixed);

        po.onCreate();

        assertThat(po.getDateApplication()).isEqualTo(fixed);
    }
}
