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("VersementObjet")
class VersementObjetTest {

    private static Versement newVersement() {
        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());
        Versement v = new Versement();
        v.setId(UUID.randomUUID());
        v.setNumeroReference("VRS-2026-001");
        v.setMontant(BigDecimal.TEN);
        v.setCodeDevise("XOF");
        v.setMethodePaiement("WAVE");
        v.setMembre(m);
        return v;
    }

    @Test
    @DisplayName("getters/setters")
    void gettersSetters() {
        VersementObjet vo = new VersementObjet();
        vo.setVersement(newVersement());
        vo.setTypeObjetCible("COTISATION");
        vo.setObjetCibleId(UUID.randomUUID());
        vo.setMontantApplique(new BigDecimal("5000.00"));
        vo.setDateApplication(LocalDateTime.now());
        vo.setCommentaire("Cotisation janvier");

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

    @Test
    @DisplayName("equals et hashCode")
    void equalsHashCode() {
        UUID id = UUID.randomUUID();
        UUID objId = UUID.randomUUID();
        Versement v = newVersement();
        VersementObjet a = new VersementObjet();
        a.setId(id);
        a.setVersement(v);
        a.setTypeObjetCible("COTISATION");
        a.setObjetCibleId(objId);
        a.setMontantApplique(BigDecimal.ONE);
        VersementObjet b = new VersementObjet();
        b.setId(id);
        b.setVersement(v);
        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() {
        VersementObjet vo = new VersementObjet();
        vo.setVersement(newVersement());
        vo.setTypeObjetCible("COTISATION");
        vo.setObjetCibleId(UUID.randomUUID());
        vo.setMontantApplique(BigDecimal.ONE);
        assertThat(vo.toString()).isNotNull().isNotEmpty();
    }

    @Test
    @DisplayName("onCreate initialise dateApplication si null")
    void onCreate_setsDateApplicationWhenNull() {
        VersementObjet vo = new VersementObjet();
        vo.setVersement(newVersement());
        vo.setTypeObjetCible("COTISATION");
        vo.setObjetCibleId(UUID.randomUUID());
        vo.setMontantApplique(BigDecimal.ONE);

        vo.onCreate();

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

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

        vo.onCreate();

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