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

import dev.lions.unionflow.server.api.dto.vote.CandidatDTO;
import dev.lions.unionflow.server.entity.vote.CampagneVote;
import dev.lions.unionflow.server.entity.vote.Candidat;
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 CandidatMapperTest {

    @Inject
    CandidatMapper 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 campagneId = UUID.randomUUID();
        CampagneVote campagne = new CampagneVote();
        campagne.setId(campagneId);
        Candidat entity = Candidat.builder()
                .campagneVote(campagne)
                .nomCandidatureOuChoix("Liste A")
                .membreIdAssocie(null)
                .professionDeFoi("Programme")
                .photoUrl("https://photo")
                .nombreDeVoix(10)
                .pourcentageObtenu(new BigDecimal("25.5"))
                .build();
        entity.setId(UUID.randomUUID());

        CandidatDTO dto = mapper.toDto(entity);

        assertThat(dto).isNotNull();
        assertThat(dto.getCampagneVoteId()).isEqualTo(campagneId.toString());
        assertThat(dto.getNomCandidatureOuChoix()).isEqualTo("Liste A");
        assertThat(dto.getProfessionDeFoi()).isEqualTo("Programme");
        assertThat(dto.getPhotoUrl()).isEqualTo("https://photo");
    }

    @Test
    @DisplayName("toEntity mappe DTO vers entity")
    void toEntity_mapsDtoToEntity() {
        CandidatDTO dto = new CandidatDTO();
        dto.setNomCandidatureOuChoix("OUI");
        dto.setMembreIdAssocie("membre-uuid");
        dto.setProfessionDeFoi("Foi");

        Candidat entity = mapper.toEntity(dto);

        assertThat(entity).isNotNull();
        assertThat(entity.getNomCandidatureOuChoix()).isEqualTo("OUI");
        assertThat(entity.getMembreIdAssocie()).isEqualTo("membre-uuid");
        assertThat(entity.getCampagneVote()).isNull();
    }

    @Test
    @DisplayName("updateEntityFromDto met à jour l'entité cible")
    void updateEntityFromDto_updatesTarget() {
        Candidat entity = Candidat.builder()
                .nomCandidatureOuChoix("Ancien")
                .build();
        CandidatDTO dto = new CandidatDTO();
        dto.setNomCandidatureOuChoix("Nouveau choix");

        mapper.updateEntityFromDto(dto, entity);

        assertThat(entity.getNomCandidatureOuChoix()).isEqualTo("Nouveau choix");
    }

    @Test
    @DisplayName("updateEntityFromDto avec dto null ne modifie pas l'entité")
    void updateEntityFromDto_nullDto_noOp() {
        Candidat entity = Candidat.builder()
                .nomCandidatureOuChoix("Inchangé")
                .professionDeFoi("Foi inchangée")
                .build();

        mapper.updateEntityFromDto(null, entity);

        assertThat(entity.getNomCandidatureOuChoix()).isEqualTo("Inchangé");
        assertThat(entity.getProfessionDeFoi()).isEqualTo("Foi inchangée");
    }

    @Test
    @DisplayName("toDto avec entity sans campagneVote met campagneVoteId à null")
    void toDto_entityWithNullCampagneVote_nullCampagneVoteId() {
        Candidat entity = Candidat.builder()
                .nomCandidatureOuChoix("Sans campagne")
                .professionDeFoi("Foi")
                .build();
        entity.setId(UUID.randomUUID());
        // campagneVote est null → entityCampagneVoteId retourne null → campagneVoteId non setté

        CandidatDTO dto = mapper.toDto(entity);

        assertThat(dto).isNotNull();
        assertThat(dto.getCampagneVoteId()).isNull();
        assertThat(dto.getNomCandidatureOuChoix()).isEqualTo("Sans campagne");
    }
}
