package dev.lions.unionflow.server.repository;

import dev.lions.unionflow.server.entity.Organisation;
import dev.lions.unionflow.server.entity.ParametresLcbFt;
import io.quarkus.test.junit.QuarkusTest;
import io.quarkus.test.TestTransaction;
import jakarta.inject.Inject;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import java.math.BigDecimal;
import java.util.Optional;
import java.util.UUID;

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

@QuarkusTest
class ParametresLcbFtRepositoryTest {

    @Inject
    ParametresLcbFtRepository parametresLcbFtRepository;

    @Inject
    OrganisationRepository organisationRepository;

    @Test
    @TestTransaction
    @DisplayName("findByOrganisationAndDevise retourne empty pour org et devise inexistants")
    void findByOrganisationAndDevise_inexistant_returnsEmpty() {
        Optional<ParametresLcbFt> result = parametresLcbFtRepository
                .findByOrganisationAndDevise(UUID.randomUUID(), "XOF");
        assertThat(result).isEmpty();
    }

    @Test
    @TestTransaction
    @DisplayName("findByOrganisationAndDevise avec codeDevise null utilise XOF par défaut")
    void findByOrganisationAndDevise_nullDevise_utiliseCodDeviseDefaut() {
        Optional<ParametresLcbFt> result = parametresLcbFtRepository
                .findByOrganisationAndDevise(UUID.randomUUID(), null);
        assertThat(result).isEmpty();
    }

    @Test
    @TestTransaction
    @DisplayName("findByOrganisationAndDevise avec codeDevise blank utilise XOF par défaut")
    void findByOrganisationAndDevise_blankDevise_utiliseCodDeviseDefaut() {
        Optional<ParametresLcbFt> result = parametresLcbFtRepository
                .findByOrganisationAndDevise(UUID.randomUUID(), "  ");
        assertThat(result).isEmpty();
    }

    @Test
    @TestTransaction
    @DisplayName("getSeuilJustification retourne empty pour org inexistante")
    void getSeuilJustification_inexistant_returnsEmpty() {
        Optional<BigDecimal> result = parametresLcbFtRepository
                .getSeuilJustification(UUID.randomUUID(), "XOF");
        assertThat(result).isEmpty();
    }

    @Test
    @TestTransaction
    @DisplayName("findByOrganisationAndDevise — fallback global si organisation non trouvée")
    void findByOrganisationAndDevise_orgNotFound_fallsBackToGlobal() {
        // Organisation inconnue → fallback vers paramètre global
        Optional<ParametresLcbFt> result = parametresLcbFtRepository
                .findByOrganisationAndDevise(UUID.randomUUID(), "EUR");
        // Le résultat peut être present (param global) ou empty selon les données de test
        assertThat(result).isNotNull(); // ne lève pas d'exception
    }

    @Test
    @TestTransaction
    @DisplayName("findByOrganisationAndDevise — paramètre organisationnel présent retourne directement (branche isPresent=true)")
    void findByOrganisationAndDevise_orgParamPresent_returnsOrgParam() {
        // Crée une organisation et un paramètre LCB-FT associé
        Organisation org = new Organisation();
        org.setNom("Org LCB-FT " + UUID.randomUUID().toString().substring(0, 8));
        org.setTypeOrganisation("ASSOCIATION");
        org.setStatut("ACTIVE");
        org.setEmail("lcbft-" + UUID.randomUUID() + "@test.com");
        org.setActif(true);
        organisationRepository.persist(org);

        // Crée le paramètre pour cette organisation spécifique
        ParametresLcbFt param = ParametresLcbFt.builder()
                .organisation(org)
                .codeDevise("XOF")
                .montantSeuilJustification(BigDecimal.valueOf(1000000))
                .build();
        parametresLcbFtRepository.persist(param);

        // La 1ère requête : byOrg → isPresent = true → retourne directement
        // Couvre la branche if (byOrg.isPresent()) return byOrg;
        Optional<ParametresLcbFt> result = parametresLcbFtRepository
                .findByOrganisationAndDevise(org.getId(), "XOF");

        assertThat(result).isPresent();
        assertThat(result.get().getOrganisation().getId()).isEqualTo(org.getId());
    }
}
