package dev.lions.unionflow.server.repository;

import dev.lions.unionflow.server.entity.ParametresCotisationOrganisation;
import io.quarkus.hibernate.orm.panache.PanacheQuery;
import org.junit.jupiter.api.BeforeEach;
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;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.*;

@DisplayName("ParametresCotisationOrganisationRepository — tests unitaires")
class ParametresCotisationOrganisationRepositoryTest {

    static class TestableParametresCotisationOrganisationRepository
            extends ParametresCotisationOrganisationRepository {
        // instanciation sans CDI
    }

    private ParametresCotisationOrganisationRepository repo;

    @BeforeEach
    void setUp() {
        repo = spy(new TestableParametresCotisationOrganisationRepository());
    }

    @Test
    @DisplayName("classExists : instanciation possible sans CDI")
    void classExists() {
        assertThat(new TestableParametresCotisationOrganisationRepository()).isNotNull();
    }

    // ─── findByOrganisationId ─────────────────────────────────────────────────

    @Test
    @DisplayName("findByOrganisationId : retourne Optional.empty() si aucun paramètre")
    @SuppressWarnings("unchecked")
    void findByOrganisationId_noResult_returnsEmpty() {
        PanacheQuery<ParametresCotisationOrganisation> query = mock(PanacheQuery.class);
        when(query.firstResultOptional()).thenReturn(Optional.empty());
        doReturn(query).when(repo).find(anyString(), any(UUID.class));

        Optional<ParametresCotisationOrganisation> result =
                repo.findByOrganisationId(UUID.randomUUID());

        assertThat(result).isEmpty();
    }

    @Test
    @DisplayName("findByOrganisationId : retourne les paramètres de l'organisation")
    @SuppressWarnings("unchecked")
    void findByOrganisationId_withResult_returnsParametres() {
        ParametresCotisationOrganisation parametres = new ParametresCotisationOrganisation();
        PanacheQuery<ParametresCotisationOrganisation> query = mock(PanacheQuery.class);
        when(query.firstResultOptional()).thenReturn(Optional.of(parametres));
        doReturn(query).when(repo).find(anyString(), any(UUID.class));

        Optional<ParametresCotisationOrganisation> result =
                repo.findByOrganisationId(UUID.randomUUID());

        assertThat(result).isPresent().contains(parametres);
    }

    // ─── findAvecGenerationAutomatiqueActivee ─────────────────────────────────

    @Test
    @DisplayName("findAvecGenerationAutomatiqueActivee : retourne liste vide si aucune organisation")
    @SuppressWarnings("unchecked")
    void findAvecGenerationAutomatiqueActivee_noResult_returnsEmpty() {
        PanacheQuery<ParametresCotisationOrganisation> query = mock(PanacheQuery.class);
        when(query.list()).thenReturn(List.of());
        doReturn(query).when(repo).find(anyString());

        List<ParametresCotisationOrganisation> result =
                repo.findAvecGenerationAutomatiqueActivee();

        assertThat(result).isEmpty();
    }

    @Test
    @DisplayName("findAvecGenerationAutomatiqueActivee : retourne les organisations avec génération auto activée")
    @SuppressWarnings("unchecked")
    void findAvecGenerationAutomatiqueActivee_withResult_returnsList() {
        ParametresCotisationOrganisation p1 = new ParametresCotisationOrganisation();
        ParametresCotisationOrganisation p2 = new ParametresCotisationOrganisation();
        PanacheQuery<ParametresCotisationOrganisation> query = mock(PanacheQuery.class);
        when(query.list()).thenReturn(List.of(p1, p2));
        doReturn(query).when(repo).find(anyString());

        List<ParametresCotisationOrganisation> result =
                repo.findAvecGenerationAutomatiqueActivee();

        assertThat(result).hasSize(2).containsExactly(p1, p2);
    }
}
