package dev.lions.user.manager.resource;

import dev.lions.user.manager.client.KeycloakAdminClient;
import dev.lions.user.manager.dto.common.UserSessionStatsDTO;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.keycloak.admin.client.resource.RealmResource;
import org.keycloak.admin.client.resource.UserResource;
import org.keycloak.admin.client.resource.UsersResource;
import org.keycloak.representations.idm.UserRepresentation;
import org.junit.jupiter.api.Assertions;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

import java.util.List;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.when;

@ExtendWith(MockitoExtension.class)
class UserMetricsResourceTest {

    @Mock
    KeycloakAdminClient keycloakAdminClient;

    @Mock
    RealmResource realmResource;

    @Mock
    UsersResource usersResource;

    @Mock
    UserResource userResource1;

    @Mock
    UserResource userResource2;

    @InjectMocks
    UserMetricsResource userMetricsResource;

    @Test
    void testGetUserSessionStats() {
        // Préparer deux utilisateurs avec des sessions différentes
        UserRepresentation u1 = new UserRepresentation();
        u1.setId("u1");
        UserRepresentation u2 = new UserRepresentation();
        u2.setId("u2");

        when(keycloakAdminClient.getRealm("test-realm")).thenReturn(realmResource);
        when(realmResource.users()).thenReturn(usersResource);
        when(usersResource.list()).thenReturn(List.of(u1, u2));

        // u1 a 2 sessions, u2 en a 0
        when(usersResource.get("u1")).thenReturn(userResource1);
        when(usersResource.get("u2")).thenReturn(userResource2);
        when(userResource1.getUserSessions()).thenReturn(List.of(new org.keycloak.representations.idm.UserSessionRepresentation(),
                new org.keycloak.representations.idm.UserSessionRepresentation()));
        when(userResource2.getUserSessions()).thenReturn(List.of());

        UserSessionStatsDTO stats = userMetricsResource.getUserSessionStats("test-realm");

        assertNotNull(stats);
        assertEquals("test-realm", stats.getRealmName());
        assertEquals(2L, stats.getTotalUsers());
        assertEquals(2L, stats.getActiveSessions()); // 2 sessions au total
        assertEquals(1L, stats.getOnlineUsers()); // 1 utilisateur avec au moins une session
    }

    @Test
    void testGetUserSessionStats_DefaultRealm() {
        when(keycloakAdminClient.getRealm("master")).thenReturn(realmResource);
        when(realmResource.users()).thenReturn(usersResource);
        when(usersResource.list()).thenReturn(List.of());

        UserSessionStatsDTO stats = userMetricsResource.getUserSessionStats(null);

        assertNotNull(stats);
        assertEquals("master", stats.getRealmName());
        assertEquals(0L, stats.getTotalUsers());
    }

    @Test
    void testGetUserSessionStats_OnError() {
        when(keycloakAdminClient.getRealm(anyString()))
                .thenThrow(new RuntimeException("KC error"));

        Assertions.assertThrows(RuntimeException.class,
                () -> userMetricsResource.getUserSessionStats("realm"));
    }
}


