package dev.lions.unionflow.server.repository;

import dev.lions.unionflow.server.entity.DemandeAdhesion;
import dev.lions.unionflow.server.entity.Membre;
import dev.lions.unionflow.server.entity.Organisation;
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.util.List;
import java.util.Optional;
import java.util.UUID;

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

@QuarkusTest
class AdhesionRepositoryTest {

    @Inject
    AdhesionRepository adhesionRepository;
    @Inject
    OrganisationRepository organisationRepository;
    @Inject
    MembreRepository membreRepository;

    private Organisation newOrganisation() {
        Organisation o = new Organisation();
        o.setNom("Org Adhesion");
        o.setTypeOrganisation("ASSOCIATION");
        o.setStatut("ACTIVE");
        o.setEmail("adh-org-" + UUID.randomUUID() + "@test.com");
        o.setActif(true);
        organisationRepository.persist(o);
        return o;
    }

    private Membre newMembre() {
        Membre m = new Membre();
        m.setNumeroMembre("ADH-" + UUID.randomUUID().toString().substring(0, 8));
        m.setPrenom("Test");
        m.setNom("User");
        m.setEmail("adh-membre-" + UUID.randomUUID() + "@test.com");
        m.setDateNaissance(java.time.LocalDate.of(1990, 1, 1));
        m.setActif(true);
        membreRepository.persist(m);
        return m;
    }

    @Test
    @TestTransaction
    @DisplayName("findByNumeroReference retourne empty pour référence inexistante")
    void findByNumeroReference_inexistant_returnsEmpty() {
        Optional<DemandeAdhesion> opt = adhesionRepository.findByNumeroReference("REF-" + UUID.randomUUID());
        assertThat(opt).isEmpty();
    }

    @Test
    @TestTransaction
    @DisplayName("findByMembreId retourne une liste")
    void findByMembreId_returnsList() {
        List<DemandeAdhesion> list = adhesionRepository.findByMembreId(UUID.randomUUID());
        assertThat(list).isNotNull();
    }

    @Test
    @TestTransaction
    @DisplayName("findByOrganisationId retourne une liste")
    void findByOrganisationId_returnsList() {
        List<DemandeAdhesion> list = adhesionRepository.findByOrganisationId(UUID.randomUUID());
        assertThat(list).isNotNull();
    }

    @Test
    @TestTransaction
    @DisplayName("findByStatut retourne une liste")
    void findByStatut_returnsList() {
        List<DemandeAdhesion> list = adhesionRepository.findByStatut("EN_ATTENTE");
        assertThat(list).isNotNull();
    }

    @Test
    @TestTransaction
    @DisplayName("findEnAttente retourne une liste")
    void findEnAttente_returnsList() {
        List<DemandeAdhesion> list = adhesionRepository.findEnAttente();
        assertThat(list).isNotNull();
    }

    @Test
    @TestTransaction
    @DisplayName("findApprouveesEnAttentePaiement retourne une liste")
    void findApprouveesEnAttentePaiement_returnsList() {
        List<DemandeAdhesion> list = adhesionRepository.findApprouveesEnAttentePaiement();
        assertThat(list).isNotNull();
    }

    @Test
    @TestTransaction
    @DisplayName("persist puis findById et findByNumeroReference retrouvent la demande")
    void persist_thenFind_findsDemande() {
        Organisation org = newOrganisation();
        Membre membre = newMembre();
        String ref = "DA-" + UUID.randomUUID().toString().substring(0, 8);
        DemandeAdhesion d = DemandeAdhesion.builder()
                .numeroReference(ref)
                .utilisateur(membre)
                .organisation(org)
                .statut("EN_ATTENTE")
                .build();
        adhesionRepository.persist(d);
        assertThat(d.getId()).isNotNull();
        DemandeAdhesion found = adhesionRepository.findById(d.getId());
        assertThat(found).isNotNull();
        Optional<DemandeAdhesion> byRef = adhesionRepository.findByNumeroReference(ref);
        assertThat(byRef).isPresent();
        assertThat(byRef.get().getNumeroReference()).isEqualTo(ref);
    }
}
