package dev.lions.unionflow.server.mapper.mutuelle.credit;

import dev.lions.unionflow.server.api.dto.mutuelle.credit.EcheanceCreditDTO;
import dev.lions.unionflow.server.api.enums.mutuelle.credit.StatutEcheanceCredit;
import dev.lions.unionflow.server.entity.mutuelle.credit.DemandeCredit;
import dev.lions.unionflow.server.entity.mutuelle.credit.EcheanceCredit;
import io.quarkus.test.junit.QuarkusTest;
import jakarta.inject.Inject;
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;

@QuarkusTest
class EcheanceCreditMapperTest {

    @Inject
    EcheanceCreditMapper mapper;

    @Test
    @DisplayName("toDto avec null retourne null")
    void toDto_null_returnsNull() {
        assertThat(mapper.toDto(null)).isNull();
    }

    @Test
    @DisplayName("toEntity avec null retourne null")
    void toEntity_null_returnsNull() {
        assertThat(mapper.toEntity(null)).isNull();
    }

    @Test
    @DisplayName("toDto mappe entity vers DTO")
    void toDto_mapsEntityToDto() {
        UUID demandeId = UUID.randomUUID();
        DemandeCredit demande = new DemandeCredit();
        demande.setId(demandeId);
        EcheanceCredit entity = EcheanceCredit.builder()
                .demandeCredit(demande)
                .ordre(1)
                .dateEcheancePrevue(LocalDate.now().plusMonths(1))
                .datePaiementEffectif(null)
                .capitalAmorti(new BigDecimal("10000"))
                .interetsDeLaPeriode(new BigDecimal("500"))
                .montantTotalExigible(new BigDecimal("10500"))
                .capitalRestantDu(new BigDecimal("90000"))
                .statut(StatutEcheanceCredit.IMPAYEE)
                .build();
        entity.setId(UUID.randomUUID());

        EcheanceCreditDTO dto = mapper.toDto(entity);

        assertThat(dto).isNotNull();
        assertThat(dto.getDemandeCreditId()).isEqualTo(demandeId.toString());
        assertThat(dto.getOrdre()).isEqualTo(1);
        assertThat(dto.getCapitalAmorti()).isEqualByComparingTo("10000");
        assertThat(dto.getStatut()).isEqualTo(StatutEcheanceCredit.IMPAYEE);
    }

    @Test
    @DisplayName("toEntity mappe DTO vers entity")
    void toEntity_mapsDtoToEntity() {
        EcheanceCreditDTO dto = new EcheanceCreditDTO();
        dto.setOrdre(2);
        dto.setDateEcheancePrevue(LocalDate.now().plusMonths(2));
        dto.setCapitalAmorti(new BigDecimal("10000"));
        dto.setInteretsDeLaPeriode(new BigDecimal("400"));
        dto.setMontantTotalExigible(new BigDecimal("10400"));

        EcheanceCredit entity = mapper.toEntity(dto);

        assertThat(entity).isNotNull();
        assertThat(entity.getOrdre()).isEqualTo(2);
        assertThat(entity.getCapitalAmorti()).isEqualByComparingTo("10000");
        assertThat(entity.getDemandeCredit()).isNull();
    }

    @Test
    @DisplayName("updateEntityFromDto met à jour l'entité cible")
    void updateEntityFromDto_updatesTarget() {
        EcheanceCredit entity = EcheanceCredit.builder()
                .ordre(1)
                .statut(StatutEcheanceCredit.IMPAYEE)
                .build();
        EcheanceCreditDTO dto = new EcheanceCreditDTO();
        dto.setOrdre(2);
        dto.setStatut(StatutEcheanceCredit.PAYEE);

        mapper.updateEntityFromDto(dto, entity);

        assertThat(entity.getOrdre()).isEqualTo(2);
        assertThat(entity.getStatut()).isEqualTo(StatutEcheanceCredit.PAYEE);
    }

    @Test
    @DisplayName("updateEntityFromDto avec dto null ne modifie pas l'entité")
    void updateEntityFromDto_nullDto_noOp() {
        EcheanceCredit entity = EcheanceCredit.builder()
                .ordre(1)
                .statut(StatutEcheanceCredit.IMPAYEE)
                .build();

        mapper.updateEntityFromDto(null, entity);

        assertThat(entity.getOrdre()).isEqualTo(1);
        assertThat(entity.getStatut()).isEqualTo(StatutEcheanceCredit.IMPAYEE);
    }

    @Test
    @DisplayName("toDto avec entity sans demandeCredit met demandeCreditId à null")
    void toDto_entityWithNullDemandeCredit_nullDemandeCreditId() {
        EcheanceCredit entity = EcheanceCredit.builder()
                .ordre(3)
                .capitalAmorti(new BigDecimal("5000"))
                .statut(StatutEcheanceCredit.PAYEE)
                .build();
        entity.setId(UUID.randomUUID());
        // demandeCredit est null → entityDemandeCreditId retourne null → demandeCreditId non setté

        EcheanceCreditDTO dto = mapper.toDto(entity);

        assertThat(dto).isNotNull();
        assertThat(dto.getDemandeCreditId()).isNull();
        assertThat(dto.getOrdre()).isEqualTo(3);
        assertThat(dto.getCapitalAmorti()).isEqualByComparingTo("5000");
    }
}
