package dev.lions.unionflow.server.mapper.collectefonds;

import dev.lions.unionflow.server.api.dto.collectefonds.CampagneCollecteResponse;
import dev.lions.unionflow.server.api.enums.collectefonds.StatutCampagneCollecte;
import dev.lions.unionflow.server.entity.Organisation;
import dev.lions.unionflow.server.entity.collectefonds.CampagneCollecte;
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.LocalDateTime;
import java.util.UUID;

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

@QuarkusTest
class CampagneCollecteMapperTest {

    @Inject
    CampagneCollecteMapper mapper;

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

    @Test
    @DisplayName("toDto mappe entity vers DTO")
    void toDto_mapsEntityToDto() {
        UUID orgId = UUID.randomUUID();
        Organisation org = new Organisation();
        org.setId(orgId);
        CampagneCollecte entity = CampagneCollecte.builder()
                .organisation(org)
                .titre("Collecte 2025")
                .courteDescription("Courte desc")
                .objectifFinancier(new BigDecimal("1000000"))
                .statut(StatutCampagneCollecte.EN_COURS)
                .dateOuverture(LocalDateTime.now())
                .dateCloturePrevue(LocalDateTime.now().plusMonths(1))
                .estPublique(true)
                .build();
        entity.setId(UUID.randomUUID());

        CampagneCollecteResponse dto = mapper.toDto(entity);

        assertThat(dto).isNotNull();
        assertThat(dto.getOrganisationId()).isEqualTo(orgId.toString());
        assertThat(dto.getTitre()).isEqualTo("Collecte 2025");
        assertThat(dto.getCourteDescription()).isEqualTo("Courte desc");
        assertThat(dto.getObjectifFinancier()).isEqualByComparingTo("1000000");
        assertThat(dto.getStatut()).isEqualTo(StatutCampagneCollecte.EN_COURS);
        assertThat(dto.getEstPublique()).isTrue();
    }

    @Test
    @DisplayName("updateEntityFromDto met à jour l'entité cible")
    void updateEntityFromDto_updatesTarget() {
        CampagneCollecte entity = CampagneCollecte.builder()
                .titre("Ancien titre")
                .objectifFinancier(BigDecimal.ZERO)
                .build();
        CampagneCollecteResponse dto = new CampagneCollecteResponse();
        dto.setTitre("Nouveau titre");
        dto.setObjectifFinancier(new BigDecimal("500000"));

        mapper.updateEntityFromDto(dto, entity);

        assertThat(entity.getTitre()).isEqualTo("Nouveau titre");
        assertThat(entity.getObjectifFinancier()).isEqualByComparingTo("500000");
    }

    @Test
    @DisplayName("updateEntityFromDto avec dto null ne modifie pas l'entité")
    void updateEntityFromDto_nullDto_noOp() {
        CampagneCollecte entity = CampagneCollecte.builder()
                .titre("Inchangé")
                .objectifFinancier(new BigDecimal("200000"))
                .build();

        mapper.updateEntityFromDto(null, entity);

        assertThat(entity.getTitre()).isEqualTo("Inchangé");
        assertThat(entity.getObjectifFinancier()).isEqualByComparingTo("200000");
    }

    @Test
    @DisplayName("toDto avec entity sans organisation met organisationId à null")
    void toDto_entityWithNullOrganisation_nullOrganisationId() {
        CampagneCollecte entity = CampagneCollecte.builder()
                .titre("Sans org")
                .statut(StatutCampagneCollecte.EN_COURS)
                .build();
        entity.setId(UUID.randomUUID());
        // organisation est null → entityOrganisationId retourne null → organisationId non setté

        CampagneCollecteResponse dto = mapper.toDto(entity);

        assertThat(dto).isNotNull();
        assertThat(dto.getOrganisationId()).isNull();
        assertThat(dto.getTitre()).isEqualTo("Sans org");
    }
}
