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

import dev.lions.unionflow.server.api.dto.gouvernance.EchelonOrganigrammeDTO;
import dev.lions.unionflow.server.api.enums.gouvernance.NiveauEchelon;
import dev.lions.unionflow.server.entity.Organisation;
import dev.lions.unionflow.server.entity.gouvernance.EchelonOrganigramme;
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 EchelonOrganigrammeMapperTest {

    @Inject
    EchelonOrganigrammeMapper 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);
        EchelonOrganigramme entity = EchelonOrganigramme.builder()
                .organisation(org)
                .echelonParent(null)
                .niveau(NiveauEchelon.NATIONAL)
                .designation("Bureau national")
                .zoneGeographiqueOuDelegation("Zone A")
                .build();
        entity.setId(UUID.randomUUID());

        EchelonOrganigrammeDTO dto = mapper.toDto(entity);

        assertThat(dto).isNotNull();
        assertThat(dto.getDesignation()).isEqualTo("Bureau national");
        assertThat(dto.getNiveau()).isEqualTo(NiveauEchelon.NATIONAL);
        assertThat(dto.getZoneGeographiqueOuDelegation()).isEqualTo("Zone A");
        assertThat(dto.getOrganisationId()).isEqualTo(orgId.toString());
        assertThat(dto.getEchelonParentId()).isNull();
    }

    @Test
    @DisplayName("toEntity mappe DTO vers entity (champs principaux)")
    void toEntity_mapsDtoToEntity() {
        EchelonOrganigrammeDTO dto = new EchelonOrganigrammeDTO();
        dto.setDesignation("Échelon test");
        dto.setNiveau(NiveauEchelon.SIEGE_MONDIAL);
        dto.setZoneGeographiqueOuDelegation("Monde");

        EchelonOrganigramme entity = mapper.toEntity(dto);

        assertThat(entity).isNotNull();
        assertThat(entity.getDesignation()).isEqualTo("Échelon test");
        assertThat(entity.getNiveau()).isEqualTo(NiveauEchelon.SIEGE_MONDIAL);
        assertThat(entity.getZoneGeographiqueOuDelegation()).isEqualTo("Monde");
        assertThat(entity.getOrganisation()).isNull();
        assertThat(entity.getEchelonParent()).isNull();
    }

    @Test
    @DisplayName("updateEntityFromDto met à jour l'entité cible")
    void updateEntityFromDto_updatesTarget() {
        EchelonOrganigramme entity = EchelonOrganigramme.builder()
                .designation("Ancienne")
                .niveau(NiveauEchelon.NATIONAL)
                .build();
        EchelonOrganigrammeDTO dto = new EchelonOrganigrammeDTO();
        dto.setDesignation("Nouvelle désignation");
        dto.setNiveau(NiveauEchelon.SIEGE_MONDIAL);

        mapper.updateEntityFromDto(dto, entity);

        assertThat(entity.getDesignation()).isEqualTo("Nouvelle désignation");
        assertThat(entity.getNiveau()).isEqualTo(NiveauEchelon.SIEGE_MONDIAL);
    }

    // =========================================================================
    // Branche manquante : updateEntityFromDto — dto null → early return (ligne 65)
    // =========================================================================

    @Test
    @DisplayName("updateEntityFromDto avec dto null ne modifie pas l'entité (branche null-guard)")
    void updateEntityFromDto_dtoNull_entityInchangee() {
        EchelonOrganigramme entity = EchelonOrganigramme.builder()
                .designation("Invariante")
                .niveau(NiveauEchelon.NATIONAL)
                .build();

        mapper.updateEntityFromDto(null, entity);

        assertThat(entity.getDesignation()).isEqualTo("Invariante");
        assertThat(entity.getNiveau()).isEqualTo(NiveauEchelon.NATIONAL);
    }

    // ==================== Tests: toDto — branches manquantes (organisation null, echelonParent non-null) ====================

    @Test
    @DisplayName("toDto avec organisation null ne renseigne pas organisationId dans le DTO")
    void toDto_organisationNull_organisationIdAbsentDuDto() {
        EchelonOrganigramme entity = EchelonOrganigramme.builder()
                .organisation(null)
                .echelonParent(null)
                .niveau(NiveauEchelon.NATIONAL)
                .designation("Échelon sans organisation")
                .zoneGeographiqueOuDelegation("Zone B")
                .build();
        entity.setId(UUID.randomUUID());

        EchelonOrganigrammeDTO dto = mapper.toDto(entity);

        assertThat(dto).isNotNull();
        assertThat(dto.getOrganisationId()).isNull();
        assertThat(dto.getEchelonParentId()).isNull();
        assertThat(dto.getDesignation()).isEqualTo("Échelon sans organisation");
        assertThat(dto.getNiveau()).isEqualTo(NiveauEchelon.NATIONAL);
    }

    @Test
    @DisplayName("toDto avec echelonParent non-null renseigne echelonParentId dans le DTO")
    void toDto_echelonParentNonNull_echelonParentIdRenseigneDansDto() {
        UUID parentId = UUID.randomUUID();
        Organisation parent = new Organisation();
        parent.setId(parentId);

        UUID orgId = UUID.randomUUID();
        Organisation org = new Organisation();
        org.setId(orgId);

        EchelonOrganigramme entity = EchelonOrganigramme.builder()
                .organisation(org)
                .echelonParent(parent)
                .niveau(NiveauEchelon.REGIONAL)
                .designation("Échelon régional")
                .zoneGeographiqueOuDelegation("Région Nord")
                .build();
        entity.setId(UUID.randomUUID());

        EchelonOrganigrammeDTO dto = mapper.toDto(entity);

        assertThat(dto).isNotNull();
        assertThat(dto.getOrganisationId()).isEqualTo(orgId.toString());
        assertThat(dto.getEchelonParentId()).isEqualTo(parentId.toString());
        assertThat(dto.getDesignation()).isEqualTo("Échelon régional");
        assertThat(dto.getNiveau()).isEqualTo(NiveauEchelon.REGIONAL);
    }
}
