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

import dev.lions.unionflow.server.api.dto.agricole.CampagneAgricoleDTO;
import dev.lions.unionflow.server.api.enums.agricole.StatutCampagneAgricole;
import dev.lions.unionflow.server.entity.Organisation;
import dev.lions.unionflow.server.entity.agricole.CampagneAgricole;
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.util.UUID;

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

@QuarkusTest
class CampagneAgricoleMapperTest {

    @Inject
    CampagneAgricoleMapper 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 orgId = UUID.randomUUID();
        Organisation org = new Organisation();
        org.setId(orgId);
        CampagneAgricole entity = CampagneAgricole.builder()
                .organisation(org)
                .designation("Campagne Arachide 2025")
                .typeCulturePrincipale("Arachide")
                .surfaceTotaleEstimeeHectares(new BigDecimal("100.5"))
                .volumePrevisionnelTonnes(new BigDecimal("50"))
                .volumeReelTonnes(new BigDecimal("48"))
                .statut(StatutCampagneAgricole.RECOLTE)
                .build();
        entity.setId(UUID.randomUUID());

        CampagneAgricoleDTO dto = mapper.toDto(entity);

        assertThat(dto).isNotNull();
        assertThat(dto.getOrganisationCoopId()).isEqualTo(orgId.toString());
        assertThat(dto.getDesignation()).isEqualTo("Campagne Arachide 2025");
        assertThat(dto.getTypeCulturePrincipale()).isEqualTo("Arachide");
        assertThat(dto.getSurfaceTotaleEstimeeHectares()).isEqualByComparingTo("100.5");
        assertThat(dto.getStatut()).isEqualTo(StatutCampagneAgricole.RECOLTE);
    }

    @Test
    @DisplayName("toEntity mappe DTO vers entity")
    void toEntity_mapsDtoToEntity() {
        CampagneAgricoleDTO dto = new CampagneAgricoleDTO();
        dto.setDesignation("Campagne test");
        dto.setTypeCulturePrincipale("Maïs");
        dto.setSurfaceTotaleEstimeeHectares(new BigDecimal("200"));
        dto.setStatut(StatutCampagneAgricole.PREPARATION);

        CampagneAgricole entity = mapper.toEntity(dto);

        assertThat(entity).isNotNull();
        assertThat(entity.getDesignation()).isEqualTo("Campagne test");
        assertThat(entity.getTypeCulturePrincipale()).isEqualTo("Maïs");
        assertThat(entity.getOrganisation()).isNull();
    }

    @Test
    @DisplayName("updateEntityFromDto met à jour l'entité cible")
    void updateEntityFromDto_updatesTarget() {
        CampagneAgricole entity = CampagneAgricole.builder()
                .designation("Ancienne")
                .statut(StatutCampagneAgricole.PREPARATION)
                .build();
        CampagneAgricoleDTO dto = new CampagneAgricoleDTO();
        dto.setDesignation("Nouvelle désignation");
        dto.setStatut(StatutCampagneAgricole.CLOTUREE);

        mapper.updateEntityFromDto(dto, entity);

        assertThat(entity.getDesignation()).isEqualTo("Nouvelle désignation");
        assertThat(entity.getStatut()).isEqualTo(StatutCampagneAgricole.CLOTUREE);
    }

    @Test
    @DisplayName("updateEntityFromDto avec dto null ne modifie pas l'entité")
    void updateEntityFromDto_nullDto_noOp() {
        CampagneAgricole entity = CampagneAgricole.builder()
                .designation("Inchangée")
                .statut(StatutCampagneAgricole.PREPARATION)
                .build();

        mapper.updateEntityFromDto(null, entity);

        assertThat(entity.getDesignation()).isEqualTo("Inchangée");
        assertThat(entity.getStatut()).isEqualTo(StatutCampagneAgricole.PREPARATION);
    }

    @Test
    @DisplayName("toDto avec entity sans organisation met organisationCoopId à null")
    void toDto_entityWithNullOrganisation_nullOrganisationId() {
        CampagneAgricole entity = CampagneAgricole.builder()
                .designation("Sans org")
                .statut(StatutCampagneAgricole.PREPARATION)
                .build();
        entity.setId(UUID.randomUUID());
        // organisation est null → entityOrganisationId retourne null → organisationCoopId non setté

        CampagneAgricoleDTO dto = mapper.toDto(entity);

        assertThat(dto).isNotNull();
        assertThat(dto.getOrganisationCoopId()).isNull();
        assertThat(dto.getDesignation()).isEqualTo("Sans org");
    }
}
