package dev.lions.user.manager.client.view;

import dev.lions.user.manager.client.service.AuditServiceClient;
import dev.lions.user.manager.client.service.RoleServiceClient;
import dev.lions.user.manager.client.service.UserMetricsServiceClient;
import dev.lions.user.manager.client.service.UserServiceClient;
import dev.lions.user.manager.dto.role.RoleDTO;
import dev.lions.user.manager.dto.user.UserSearchCriteriaDTO;
import dev.lions.user.manager.dto.user.UserSearchResultDTO;
import jakarta.faces.application.FacesMessage;
import jakarta.faces.context.FacesContext;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockedStatic;
import org.mockito.junit.jupiter.MockitoExtension;

import java.util.Collections;

import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.*;

@ExtendWith(MockitoExtension.class)
class DashboardBeanTest {

    @Mock
    UserServiceClient userServiceClient;

    @Mock
    RoleServiceClient roleServiceClient;

    @Mock
    AuditServiceClient auditServiceClient;

    @Mock
    UserMetricsServiceClient userMetricsServiceClient;

    @Mock
    FacesContext facesContext;

    @InjectMocks
    DashboardBean dashboardBean;

    MockedStatic<FacesContext> facesContextMock;

    @BeforeEach
    void setUp() throws Exception {
        facesContextMock = mockStatic(FacesContext.class);
        facesContextMock.when(FacesContext::getCurrentInstance).thenReturn(facesContext);
        // Injecter defaultRealm (normalement @ConfigProperty) via réflexion — sans ça,
        // init() propage null vers les mocks et anyString() ne matche pas.
        java.lang.reflect.Field f = DashboardBean.class.getDeclaredField("defaultRealm");
        f.setAccessible(true);
        f.set(dashboardBean, "lions-user-manager");
    }

    @AfterEach
    void tearDown() {
        facesContextMock.close();
    }

    @Test
    void testInit() {
        // Mock User Client
        UserSearchResultDTO userResult = new UserSearchResultDTO();
        userResult.setTotalCount(100L);
        when(userServiceClient.searchUsers(any(UserSearchCriteriaDTO.class))).thenReturn(userResult);

        // Mock Role Client
        RoleDTO role = RoleDTO.builder().name("role").build();
        when(roleServiceClient.getAllRealmRoles(anyString())).thenReturn(Collections.singletonList(role));

        // Mock Audit Client
        dev.lions.user.manager.dto.common.CountDTO successDto = new dev.lions.user.manager.dto.common.CountDTO(50L);
        dev.lions.user.manager.dto.common.CountDTO failureDto = new dev.lions.user.manager.dto.common.CountDTO(5L);
        when(auditServiceClient.getSuccessCount(anyString(), anyString())).thenReturn(successDto);
        when(auditServiceClient.getFailureCount(anyString(), anyString())).thenReturn(failureDto);

        // Mock Metrics Client
        dev.lions.user.manager.dto.common.UserSessionStatsDTO stats = dev.lions.user.manager.dto.common.UserSessionStatsDTO
                .builder()
                .realmName("master")
                .totalUsers(100L)
                .activeSessions(80L)
                .onlineUsers(70L)
                .build();
        when(userMetricsServiceClient.getUserSessionStats(anyString())).thenReturn(stats);

        dashboardBean.init();

        assertEquals(100L, dashboardBean.getTotalUsers());
        assertEquals(1L, dashboardBean.getTotalRoles());
        assertEquals(55L, dashboardBean.getRecentActions());
        assertEquals("100", dashboardBean.getTotalUsersDisplay());
        assertEquals("55", dashboardBean.getRecentActionsDisplay());
    }

    @Test
    void testLoadStatisticsError() {
        when(userServiceClient.searchUsers(any())).thenThrow(new RuntimeException("Error"));

        dashboardBean.loadStatistics();

        assertEquals(0L, dashboardBean.getTotalUsers());
        verify(facesContext).addMessage(any(), any(FacesMessage.class));
    }

    @Test
    void testRefreshStatistics() {
        // Mock User Client
        UserSearchResultDTO userResult = new UserSearchResultDTO();
        userResult.setTotalCount(10L);
        when(userServiceClient.searchUsers(any(UserSearchCriteriaDTO.class))).thenReturn(userResult);

        // Mock Role Client
        when(roleServiceClient.getAllRealmRoles(anyString())).thenReturn(Collections.emptyList());

        // Mock Audit Client
        dev.lions.user.manager.dto.common.CountDTO successDto = new dev.lions.user.manager.dto.common.CountDTO(0L);
        dev.lions.user.manager.dto.common.CountDTO failureDto = new dev.lions.user.manager.dto.common.CountDTO(0L);
        when(auditServiceClient.getSuccessCount(anyString(), anyString())).thenReturn(successDto);
        when(auditServiceClient.getFailureCount(anyString(), anyString())).thenReturn(failureDto);

        dashboardBean.refreshStatistics();

        verify(facesContext, atLeastOnce()).addMessage(any(), any(FacesMessage.class));
    }
}
