package dev.lions.user.manager.resource;

import dev.lions.user.manager.dto.realm.AuthorizedRealmsDTO;
import dev.lions.user.manager.dto.realm.RealmAccessCheckDTO;
import dev.lions.user.manager.dto.realm.RealmAssignmentDTO;
import dev.lions.user.manager.service.RealmAuthorizationService;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.core.SecurityContext;
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.junit.jupiter.MockitoExtension;

import java.security.Principal;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;

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

/**
 * Tests unitaires pour RealmAssignmentResource
 */
@ExtendWith(MockitoExtension.class)
class RealmAssignmentResourceTest {

    @Mock
    private RealmAuthorizationService realmAuthorizationService;

    @Mock
    private SecurityContext securityContext;

    @Mock
    private Principal principal;

    @InjectMocks
    private RealmAssignmentResource realmAssignmentResource;

    private RealmAssignmentDTO assignment;

    @BeforeEach
    void setUp() {
        assignment = RealmAssignmentDTO.builder()
                .id("assignment-1")
                .userId("user-1")
                .username("testuser")
                .email("test@example.com")
                .realmName("realm1")
                .isSuperAdmin(false)
                .active(true)
                .assignedAt(LocalDateTime.now())
                .assignedBy("admin")
                .build();
    }

    @Test
    void testGetAllAssignments_Success() {
        List<RealmAssignmentDTO> assignments = Arrays.asList(assignment);
        when(realmAuthorizationService.getAllAssignments()).thenReturn(assignments);

        List<RealmAssignmentDTO> result = realmAssignmentResource.getAllAssignments();

        assertEquals(1, result.size());
    }

    @Test
    void testGetAssignmentsByUser_Success() {
        List<RealmAssignmentDTO> assignments = Arrays.asList(assignment);
        when(realmAuthorizationService.getAssignmentsByUser("user-1")).thenReturn(assignments);

        List<RealmAssignmentDTO> result = realmAssignmentResource.getAssignmentsByUser("user-1");

        assertEquals(1, result.size());
    }

    @Test
    void testGetAssignmentsByRealm_Success() {
        List<RealmAssignmentDTO> assignments = Arrays.asList(assignment);
        when(realmAuthorizationService.getAssignmentsByRealm("realm1")).thenReturn(assignments);

        List<RealmAssignmentDTO> result = realmAssignmentResource.getAssignmentsByRealm("realm1");

        assertEquals(1, result.size());
    }

    @Test
    void testGetAssignmentById_Success() {
        when(realmAuthorizationService.getAssignmentById("assignment-1")).thenReturn(Optional.of(assignment));

        RealmAssignmentDTO result = realmAssignmentResource.getAssignmentById("assignment-1");

        assertNotNull(result);
        assertEquals("assignment-1", result.getId());
    }

    @Test
    void testGetAssignmentById_NotFound() {
        when(realmAuthorizationService.getAssignmentById("non-existent")).thenReturn(Optional.empty());

        assertThrows(RuntimeException.class, () -> realmAssignmentResource.getAssignmentById("non-existent"));
    }

    @Test
    void testCanManageRealm_Success() {
        when(realmAuthorizationService.canManageRealm("user-1", "realm1")).thenReturn(true);

        RealmAccessCheckDTO result = realmAssignmentResource.canManageRealm("user-1", "realm1");

        assertTrue(result.isCanManage());
    }

    @Test
    void testGetAuthorizedRealms_Success() {
        List<String> realms = Arrays.asList("realm1", "realm2");
        when(realmAuthorizationService.getAuthorizedRealms("user-1")).thenReturn(realms);
        when(realmAuthorizationService.isSuperAdmin("user-1")).thenReturn(false);

        AuthorizedRealmsDTO result = realmAssignmentResource.getAuthorizedRealms("user-1");

        assertEquals(2, result.getRealms().size());
        assertFalse(result.isSuperAdmin());
    }

    @Test
    void testAssignRealmToUser_Success() {
        // En Quarkus, @Context SecurityContext injecté peut être simulé via Mockito
        // Mais dans RealmAssignmentResource, l'admin est récupéré du SecurityContext.
        // Puisque c'est un test unitaire @ExtendWith(MockitoExtension.class),
        // @Inject SecurityContext securityContext est mocké.

        when(securityContext.getUserPrincipal()).thenReturn(principal);
        when(principal.getName()).thenReturn("admin");
        when(realmAuthorizationService.assignRealmToUser(any(RealmAssignmentDTO.class))).thenReturn(assignment);

        Response response = realmAssignmentResource.assignRealmToUser(assignment);

        assertEquals(201, response.getStatus());
    }

    @Test
    void testRevokeRealmFromUser_Success() {
        doNothing().when(realmAuthorizationService).revokeRealmFromUser("user-1", "realm1");

        realmAssignmentResource.revokeRealmFromUser("user-1", "realm1");

        verify(realmAuthorizationService).revokeRealmFromUser("user-1", "realm1");
    }

    @Test
    void testRevokeAllRealmsFromUser_Success() {
        doNothing().when(realmAuthorizationService).revokeAllRealmsFromUser("user-1");

        realmAssignmentResource.revokeAllRealmsFromUser("user-1");

        verify(realmAuthorizationService).revokeAllRealmsFromUser("user-1");
    }

    @Test
    void testDeactivateAssignment_Success() {
        doNothing().when(realmAuthorizationService).deactivateAssignment("assignment-1");

        realmAssignmentResource.deactivateAssignment("assignment-1");

        verify(realmAuthorizationService).deactivateAssignment("assignment-1");
    }

    @Test
    void testActivateAssignment_Success() {
        doNothing().when(realmAuthorizationService).activateAssignment("assignment-1");

        realmAssignmentResource.activateAssignment("assignment-1");

        verify(realmAuthorizationService).activateAssignment("assignment-1");
    }

    @Test
    void testSetSuperAdmin_Success() {
        doNothing().when(realmAuthorizationService).setSuperAdmin("user-1", true);

        realmAssignmentResource.setSuperAdmin("user-1", true);

        verify(realmAuthorizationService).setSuperAdmin("user-1", true);
    }
}
