package dev.lions.unionflow.server.service;

import dev.lions.unionflow.server.api.dto.dashboard.DashboardDataResponse;
import dev.lions.unionflow.server.api.dto.dashboard.DashboardStatsResponse;
import dev.lions.unionflow.server.api.dto.dashboard.RecentActivityResponse;
import dev.lions.unionflow.server.entity.Membre;
import dev.lions.unionflow.server.entity.Organisation;
import io.quarkus.test.TestTransaction;
import io.quarkus.test.junit.QuarkusTest;
import jakarta.inject.Inject;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import java.time.LocalDate;
import java.util.List;
import java.util.UUID;

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

@QuarkusTest
class DashboardServiceTest {

    @Inject
    DashboardServiceImpl dashboardService;

    @Inject
    OrganisationService organisationService;

    @Inject
    MembreService membreService;

    private Organisation testOrganisation;
    private Membre testMembre;

    @BeforeEach
    @TestTransaction
    void setup() {
        testOrganisation = new Organisation();
        testOrganisation.setNom("Lions Club Dashboard " + UUID.randomUUID());
        testOrganisation.setEmail("dash-" + UUID.randomUUID() + "@test.com");
        testOrganisation.setTypeOrganisation("CLUB");
        testOrganisation.setStatut("ACTIVE");
        testOrganisation.setActif(true);
        organisationService.creerOrganisation(testOrganisation, "admin@test.com");

        testMembre = new Membre();
        testMembre.setPrenom("Dash");
        testMembre.setNom("Board");
        testMembre.setEmail("dash.board-" + UUID.randomUUID() + "@test.com");
        testMembre.setNumeroMembre("M-" + UUID.randomUUID().toString().substring(0, 8));
        testMembre.setDateNaissance(LocalDate.of(1988, 8, 8));
        testMembre.setStatutCompte("ACTIF");
        testMembre.setActif(true);
        membreService.creerMembre(testMembre);
    }

    @Test
    @TestTransaction
    @DisplayName("getDashboardData retourne des données valides")
    void getDashboardData_returnsValidData() {
        DashboardDataResponse data = dashboardService.getDashboardData(
                testOrganisation.getId().toString(),
                testMembre.getId().toString());

        assertThat(data).isNotNull();
        assertThat(data.getStats()).isNotNull();
        assertThat(data.getOrganizationId()).isEqualTo(testOrganisation.getId().toString());
    }

    @Test
    @TestTransaction
    @DisplayName("getDashboardStats retourne des statistiques cohérentes")
    void getDashboardStats_returnsCoherentStats() {
        DashboardStatsResponse stats = dashboardService.getDashboardStats(
                testOrganisation.getId().toString(),
                testMembre.getId().toString());

        assertThat(stats).isNotNull();
        assertThat(stats.getTotalMembers()).isGreaterThanOrEqualTo(0);
        assertThat(stats.getActiveMembers()).isGreaterThanOrEqualTo(0);
    }

    @Test
    @TestTransaction
    @DisplayName("getDashboardStats avec organizationId null couvre la branche orgId == null")
    void getDashboardStats_nullOrganizationId_returnsStats() {
        DashboardStatsResponse stats = dashboardService.getDashboardStats(null, testMembre.getId().toString());
        assertThat(stats).isNotNull();
        assertThat(stats.getTotalMembers()).isGreaterThanOrEqualTo(0);
    }

    @Test
    @TestTransaction
    @DisplayName("getDashboardStats avec organizationId vide couvre la branche orgId == null (empty string)")
    void getDashboardStats_emptyOrganizationId_returnsStats() {
        DashboardStatsResponse stats = dashboardService.getDashboardStats("", testMembre.getId().toString());
        assertThat(stats).isNotNull();
        assertThat(stats.getTotalOrganizations()).isGreaterThanOrEqualTo(0);
    }

    @Test
    @TestTransaction
    @DisplayName("getDashboardStats avec organizationId invalide couvre le catch IllegalArgumentException dans parseOrganizationId")
    void getDashboardStats_invalidOrganizationId_returnsStats() {
        DashboardStatsResponse stats = dashboardService.getDashboardStats("not-a-uuid", testMembre.getId().toString());
        assertThat(stats).isNotNull();
    }

    @Test
    @TestTransaction
    @DisplayName("getRecentActivities avec organizationId null couvre la branche orgId == null")
    void getRecentActivities_nullOrganizationId_returnsList() {
        List<RecentActivityResponse> activities = dashboardService.getRecentActivities(null, testMembre.getId().toString(), 10);
        assertThat(activities).isNotNull();
    }

    @Test
    @TestTransaction
    @DisplayName("getRecentActivities avec organizationId valide retourne une liste")
    void getRecentActivities_validOrganizationId_returnsList() {
        List<RecentActivityResponse> activities = dashboardService.getRecentActivities(
                testOrganisation.getId().toString(),
                testMembre.getId().toString(),
                10);
        assertThat(activities).isNotNull();
    }

    @Test
    @TestTransaction
    @DisplayName("getDashboardData avec organizationId null couvre toutes les branches orgId null en cascade")
    void getDashboardData_nullOrganizationId_returnsValidData() {
        DashboardDataResponse data = dashboardService.getDashboardData(null, testMembre.getId().toString());
        assertThat(data).isNotNull();
        assertThat(data.getStats()).isNotNull();
    }
}
