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

import dev.lions.unionflow.server.api.dto.registre.AgrementProfessionnelDTO;
import dev.lions.unionflow.server.api.enums.registre.StatutAgrement;
import dev.lions.unionflow.server.entity.Membre;
import dev.lions.unionflow.server.entity.Organisation;
import dev.lions.unionflow.server.entity.registre.AgrementProfessionnel;
import io.quarkus.test.junit.QuarkusTest;
import jakarta.inject.Inject;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import java.util.UUID;

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

@QuarkusTest
class AgrementProfessionnelMapperTest {

    @Inject
    AgrementProfessionnelMapper 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 membreId = UUID.randomUUID();
        UUID orgId = UUID.randomUUID();
        Membre m = new Membre();
        m.setId(membreId);
        Organisation o = new Organisation();
        o.setId(orgId);
        AgrementProfessionnel entity = AgrementProfessionnel.builder()
                .membre(m)
                .organisation(o)
                .statut(StatutAgrement.VALIDE)
                .secteurOuOrdre("Santé")
                .build();
        entity.setId(UUID.randomUUID());

        AgrementProfessionnelDTO dto = mapper.toDto(entity);

        assertThat(dto).isNotNull();
        assertThat(dto.getMembreId()).isEqualTo(membreId.toString());
        assertThat(dto.getOrganisationId()).isEqualTo(orgId.toString());
        assertThat(dto.getStatut()).isEqualTo(StatutAgrement.VALIDE);
        assertThat(dto.getSecteurOuOrdre()).isEqualTo("Santé");
    }

    @Test
    @DisplayName("toEntity mappe DTO vers entity")
    void toEntity_mapsDtoToEntity() {
        AgrementProfessionnelDTO dto = new AgrementProfessionnelDTO();
        dto.setStatut(StatutAgrement.PROVISOIRE);
        dto.setSecteurOuOrdre("Juridique");

        AgrementProfessionnel entity = mapper.toEntity(dto);

        assertThat(entity).isNotNull();
        assertThat(entity.getStatut()).isEqualTo(StatutAgrement.PROVISOIRE);
        assertThat(entity.getSecteurOuOrdre()).isEqualTo("Juridique");
    }

    @Test
    @DisplayName("toDto avec membre null produit membreId null (branche entityMembreId — objet null)")
    void toDto_membreNull_membreIdIsNull() {
        UUID orgId = UUID.randomUUID();
        Organisation o = new Organisation();
        o.setId(orgId);
        AgrementProfessionnel entity = AgrementProfessionnel.builder()
                .membre(null)
                .organisation(o)
                .statut(StatutAgrement.VALIDE)
                .secteurOuOrdre("Droit")
                .build();
        entity.setId(UUID.randomUUID());

        AgrementProfessionnelDTO dto = mapper.toDto(entity);

        assertThat(dto).isNotNull();
        assertThat(dto.getMembreId()).isNull();
        assertThat(dto.getOrganisationId()).isEqualTo(orgId.toString());
    }

    @Test
    @DisplayName("toDto avec organisation null produit organisationId null (branche entityOrganisationId — objet null)")
    void toDto_organisationNull_organisationIdIsNull() {
        UUID membreId = UUID.randomUUID();
        Membre m = new Membre();
        m.setId(membreId);
        AgrementProfessionnel entity = AgrementProfessionnel.builder()
                .membre(m)
                .organisation(null)
                .statut(StatutAgrement.SUSPENDU)
                .secteurOuOrdre("Comptabilité")
                .build();
        entity.setId(UUID.randomUUID());

        AgrementProfessionnelDTO dto = mapper.toDto(entity);

        assertThat(dto).isNotNull();
        assertThat(dto.getMembreId()).isEqualTo(membreId.toString());
        assertThat(dto.getOrganisationId()).isNull();
    }

    @Test
    @DisplayName("updateEntityFromDto met à jour les champs de l'entité")
    void updateEntityFromDto_updatesEntity() {
        AgrementProfessionnel entity = AgrementProfessionnel.builder()
                .statut(StatutAgrement.PROVISOIRE)
                .secteurOuOrdre("Ancien secteur")
                .build();

        AgrementProfessionnelDTO dto = new AgrementProfessionnelDTO();
        dto.setStatut(StatutAgrement.VALIDE);
        dto.setSecteurOuOrdre("Nouveau secteur");

        mapper.updateEntityFromDto(dto, entity);

        assertThat(entity.getStatut()).isEqualTo(StatutAgrement.VALIDE);
        assertThat(entity.getSecteurOuOrdre()).isEqualTo("Nouveau secteur");
    }

    @Test
    @DisplayName("updateEntityFromDto avec dto null ne modifie pas l'entité (branche updateEntityFromDto — dto null)")
    void updateEntityFromDto_dtoNull_entityUnchanged() {
        AgrementProfessionnel entity = AgrementProfessionnel.builder()
                .statut(StatutAgrement.VALIDE)
                .secteurOuOrdre("Secteur initial")
                .build();

        mapper.updateEntityFromDto(null, entity);

        assertThat(entity.getStatut()).isEqualTo(StatutAgrement.VALIDE);
        assertThat(entity.getSecteurOuOrdre()).isEqualTo("Secteur initial");
    }
}
