package com.saas.admin.service;

import com.saas.admin.entity.Permission;
import com.saas.admin.entity.Role;
import com.saas.admin.entity.User;
import com.saas.admin.entity.UserRole;
import com.saas.admin.repository.PermissionRepository;
import com.saas.admin.repository.RolePermissionRepository;
import com.saas.admin.repository.RoleRepository;
import com.saas.admin.repository.UserRoleRepository;
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.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;

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

@ExtendWith(MockitoExtension.class)
class RBACServiceTest {
    
    @Mock
    private RoleRepository roleRepository;
    
    @Mock
    private PermissionRepository permissionRepository;
    
    @Mock
    private RolePermissionRepository rolePermissionRepository;
    
    @Mock
    private UserRoleRepository userRoleRepository;
    
    @InjectMocks
    private RBACService rbacService;
    
    private Role testRole;
    private Permission testPermission;
    private User testUser;
    
    @BeforeEach
    void setUp() {
        testRole = Role.builder()
                .id(1L)
                .name("ADMIN")
                .description("Administrator role")
                .isActive(true)
                .isSystem(false)
                .build();
        
        testPermission = Permission.builder()
                .id(1L)
                .resource("tenant")
                .action("read")
                .description("Read tenant data")
                .isActive(true)
                .isSystem(false)
                .build();
        
        testUser = new User();
        testUser.setId(1L);
        testUser.setEmail("test@example.com");
    }
    
    @Test
    void testCreateRole_Success() {
        when(roleRepository.existsByName("ADMIN")).thenReturn(false);
        when(roleRepository.save(any(Role.class))).thenReturn(testRole);
        
        Role result = rbacService.createRole("admin", "Administrator role", false);
        
        assertNotNull(result);
        assertEquals("ADMIN", result.getName());
        verify(roleRepository).save(any(Role.class));
    }
    
    @Test
    void testCreateRole_AlreadyExists() {
        when(roleRepository.existsByName("ADMIN")).thenReturn(true);
        
        assertThrows(IllegalArgumentException.class, () -> 
            rbacService.createRole("admin", "Administrator role", false)
        );
        
        verify(roleRepository, never()).save(any(Role.class));
    }
    
    @Test
    void testGetRoleById_Found() {
        when(roleRepository.findById(1L)).thenReturn(Optional.of(testRole));
        
        Optional<Role> result = rbacService.getRoleById(1L);
        
        assertTrue(result.isPresent());
        assertEquals("ADMIN", result.get().getName());
    }
    
    @Test
    void testGetRoleById_NotFound() {
        when(roleRepository.findById(99L)).thenReturn(Optional.empty());
        
        Optional<Role> result = rbacService.getRoleById(99L);
        
        assertFalse(result.isPresent());
    }
    
    @Test
    void testGetAllRoles() {
        Role role2 = Role.builder().id(2L).name("USER").build();
        when(roleRepository.findAll()).thenReturn(Arrays.asList(testRole, role2));
        
        List<Role> roles = rbacService.getAllRoles();
        
        assertEquals(2, roles.size());
    }
    
    @Test
    void testDeleteRole_Success() {
        when(roleRepository.findById(1L)).thenReturn(Optional.of(testRole));
        when(userRoleRepository.countByRole(testRole)).thenReturn(0L);
        
        assertDoesNotThrow(() -> rbacService.deleteRole(1L));
        
        verify(roleRepository).delete(testRole);
    }
    
    @Test
    void testDeleteRole_SystemRole() {
        testRole.setIsSystem(true);
        when(roleRepository.findById(1L)).thenReturn(Optional.of(testRole));
        
        assertThrows(IllegalStateException.class, () -> rbacService.deleteRole(1L));
        
        verify(roleRepository, never()).delete(any());
    }
    
    @Test
    void testDeleteRole_AssignedToUsers() {
        when(roleRepository.findById(1L)).thenReturn(Optional.of(testRole));
        when(userRoleRepository.countByRole(testRole)).thenReturn(5L);
        
        assertThrows(IllegalStateException.class, () -> rbacService.deleteRole(1L));
        
        verify(roleRepository, never()).delete(any());
    }
    
    @Test
    void testCreatePermission_Success() {
        when(permissionRepository.existsByResourceAndAction("tenant", "read")).thenReturn(false);
        when(permissionRepository.save(any(Permission.class))).thenReturn(testPermission);
        
        Permission result = rbacService.createPermission("tenant", "read", "Read tenant data", false);
        
        assertNotNull(result);
        assertEquals("tenant", result.getResource());
        assertEquals("read", result.getAction());
        verify(permissionRepository).save(any(Permission.class));
    }
    
    @Test
    void testCreatePermission_AlreadyExists() {
        when(permissionRepository.existsByResourceAndAction("tenant", "read")).thenReturn(true);
        
        assertThrows(IllegalArgumentException.class, () -> 
            rbacService.createPermission("tenant", "read", "Read tenant data", false)
        );
        
        verify(permissionRepository, never()).save(any(Permission.class));
    }
    
    @Test
    void testGetPermissionById_Found() {
        when(permissionRepository.findById(1L)).thenReturn(Optional.of(testPermission));
        
        Optional<Permission> result = rbacService.getPermissionById(1L);
        
        assertTrue(result.isPresent());
        assertEquals("tenant:read", result.get().getPermissionString());
    }
    
    @Test
    void testDeletePermission_Success() {
        when(permissionRepository.findById(1L)).thenReturn(Optional.of(testPermission));
        when(rolePermissionRepository.findByPermission(testPermission)).thenReturn(List.of());
        
        assertDoesNotThrow(() -> rbacService.deletePermission(1L));
        
        verify(permissionRepository).delete(testPermission);
    }
    
    @Test
    void testDeletePermission_SystemPermission() {
        testPermission.setIsSystem(true);
        when(permissionRepository.findById(1L)).thenReturn(Optional.of(testPermission));
        
        assertThrows(IllegalStateException.class, () -> rbacService.deletePermission(1L));
        
        verify(permissionRepository, never()).delete(any());
    }
    
    @Test
    void testCachedPermissionsForUser() {
        List<String> permissions = Arrays.asList("tenant:read", "tenant:write", "user:read");
        when(userRoleRepository.findAllPermissionsByUserId(1L)).thenReturn(permissions);
        
        List<String> result1 = rbacService.getCachedPermissionsForUser(1L);
        List<String> result2 = rbacService.getCachedPermissionsForUser(1L);
        
        assertEquals(3, result1.size());
        assertEquals(result1, result2);
        verify(userRoleRepository, times(1)).findAllPermissionsByUserId(1L);
    }
    
    @Test
    void testInvalidateCacheForUser() {
        List<String> permissions = Arrays.asList("tenant:read");
        when(userRoleRepository.findAllPermissionsByUserId(1L)).thenReturn(permissions);
        
        rbacService.getCachedPermissionsForUser(1L);
        
        rbacService.invalidateCacheForUser(1L);
        
        rbacService.getCachedPermissionsForUser(1L);
        
        verify(userRoleRepository, times(2)).findAllPermissionsByUserId(1L);
    }
    
    @Test
    void testGetCacheSize() {
        when(userRoleRepository.findAllPermissionsByUserId(1L)).thenReturn(List.of("perm1"));
        when(userRoleRepository.findAllPermissionsByUserId(2L)).thenReturn(List.of("perm2"));
        
        rbacService.getCachedPermissionsForUser(1L);
        rbacService.getCachedPermissionsForUser(2L);
        
        assertEquals(2, rbacService.getCacheSize());
    }
    
    @Test
    void testInvalidateCacheAll() {
        when(userRoleRepository.findAllPermissionsByUserId(1L)).thenReturn(List.of("perm1"));
        when(userRoleRepository.findAllPermissionsByUserId(2L)).thenReturn(List.of("perm2"));
        
        rbacService.getCachedPermissionsForUser(1L);
        rbacService.getCachedPermissionsForUser(2L);
        assertEquals(2, rbacService.getCacheSize());
        
        rbacService.invalidateCacheAll();
        
        assertEquals(0, rbacService.getCacheSize());
    }
    
    @Test
    void testAssignPermissionToRole() {
        when(roleRepository.findById(1L)).thenReturn(Optional.of(testRole));
        when(permissionRepository.findById(1L)).thenReturn(Optional.of(testPermission));
        when(rolePermissionRepository.existsByRoleAndPermission(testRole, testPermission)).thenReturn(false);
        when(roleRepository.save(testRole)).thenReturn(testRole);
        
        assertDoesNotThrow(() -> rbacService.assignPermissionToRole(1L, 1L));
        
        verify(roleRepository).save(testRole);
    }
    
    @Test
    void testAssignPermissionToRole_AlreadyAssigned() {
        when(roleRepository.findById(1L)).thenReturn(Optional.of(testRole));
        when(permissionRepository.findById(1L)).thenReturn(Optional.of(testPermission));
        when(rolePermissionRepository.existsByRoleAndPermission(testRole, testPermission)).thenReturn(true);
        
        assertDoesNotThrow(() -> rbacService.assignPermissionToRole(1L, 1L));
        
        verify(roleRepository, never()).save(any());
    }
    
    @Test
    void testAssignRoleToUser() {
        when(userRoleRepository.existsByUserAndRole(testUser, testRole)).thenReturn(false);
        when(userRoleRepository.save(any(UserRole.class))).thenReturn(new UserRole());
        
        assertDoesNotThrow(() -> rbacService.assignRoleToUser(testUser, testRole, "admin"));
        
        verify(userRoleRepository).save(any(UserRole.class));
    }
    
    @Test
    void testAssignRoleToUser_AlreadyAssigned() {
        when(userRoleRepository.existsByUserAndRole(testUser, testRole)).thenReturn(true);
        
        assertDoesNotThrow(() -> rbacService.assignRoleToUser(testUser, testRole, "admin"));
        
        verify(userRoleRepository, never()).save(any(UserRole.class));
    }
    
    @Test
    void testAssignRoleToUser_InvalidatesCache() {
        when(userRoleRepository.existsByUserAndRole(testUser, testRole)).thenReturn(false);
        when(userRoleRepository.save(any(UserRole.class))).thenReturn(new UserRole());
        when(userRoleRepository.findAllPermissionsByUserId(1L)).thenReturn(List.of("perm1"));
        
        rbacService.getCachedPermissionsForUser(1L);
        assertEquals(1, rbacService.getCacheSize());
        
        rbacService.assignRoleToUser(testUser, testRole, "admin");
        
        assertEquals(0, rbacService.getCacheSize());
    }
    
    @Test
    void testRemoveRoleFromUser() {
        UserRole userRole = new UserRole();
        when(userRoleRepository.findByUserAndRole(testUser, testRole)).thenReturn(Optional.of(userRole));
        
        assertDoesNotThrow(() -> rbacService.removeRoleFromUser(testUser, testRole));
        
        verify(userRoleRepository).delete(userRole);
    }
    
    @Test
    void testRemoveRoleFromUser_NotAssigned() {
        when(userRoleRepository.findByUserAndRole(testUser, testRole)).thenReturn(Optional.empty());
        
        assertDoesNotThrow(() -> rbacService.removeRoleFromUser(testUser, testRole));
        
        verify(userRoleRepository, never()).delete(any(UserRole.class));
    }
    
    @Test
    void testRemoveRoleFromUser_InvalidatesCache() {
        when(userRoleRepository.findByUserAndRole(testUser, testRole)).thenReturn(Optional.of(new UserRole()));
        when(userRoleRepository.findAllPermissionsByUserId(1L)).thenReturn(List.of("perm1"));
        
        rbacService.getCachedPermissionsForUser(1L);
        assertEquals(1, rbacService.getCacheSize());
        
        rbacService.removeRoleFromUser(testUser, testRole);
        
        assertEquals(0, rbacService.getCacheSize());
    }
    
    @Test
    void testRemovePermissionFromRole_Success() {
        when(roleRepository.findById(1L)).thenReturn(Optional.of(testRole));
        when(permissionRepository.findById(1L)).thenReturn(Optional.of(testPermission));
        when(roleRepository.save(testRole)).thenReturn(testRole);
        
        assertDoesNotThrow(() -> rbacService.removePermissionFromRole(1L, 1L));
        
        verify(roleRepository).save(testRole);
    }
    
    @Test
    void testRemovePermissionFromRole_RoleNotFound() {
        when(roleRepository.findById(99L)).thenReturn(Optional.empty());
        
        assertThrows(IllegalArgumentException.class, () -> 
            rbacService.removePermissionFromRole(99L, 1L)
        );
    }
    
    @Test
    void testRemovePermissionFromRole_PermissionNotFound() {
        when(roleRepository.findById(1L)).thenReturn(Optional.of(testRole));
        when(permissionRepository.findById(99L)).thenReturn(Optional.empty());
        
        assertThrows(IllegalArgumentException.class, () -> 
            rbacService.removePermissionFromRole(1L, 99L)
        );
    }
    
    @Test
    void testRemovePermissionFromRole_InvalidatesCache() {
        when(roleRepository.findById(1L)).thenReturn(Optional.of(testRole));
        when(permissionRepository.findById(1L)).thenReturn(Optional.of(testPermission));
        when(roleRepository.save(testRole)).thenReturn(testRole);
        when(userRoleRepository.findAllPermissionsByUserId(1L)).thenReturn(List.of("tenant:read"));
        
        rbacService.getCachedPermissionsForUser(1L);
        assertEquals(1, rbacService.getCacheSize());
        
        rbacService.removePermissionFromRole(1L, 1L);
        
        assertEquals(0, rbacService.getCacheSize());
    }
    
    @Test
    void testAssignPermissionToRole_RoleNotFound() {
        when(roleRepository.findById(99L)).thenReturn(Optional.empty());
        
        assertThrows(IllegalArgumentException.class, () -> 
            rbacService.assignPermissionToRole(99L, 1L)
        );
    }
    
    @Test
    void testAssignPermissionToRole_PermissionNotFound() {
        when(roleRepository.findById(1L)).thenReturn(Optional.of(testRole));
        when(permissionRepository.findById(99L)).thenReturn(Optional.empty());
        
        assertThrows(IllegalArgumentException.class, () -> 
            rbacService.assignPermissionToRole(1L, 99L)
        );
    }
    
    @Test
    void testAssignPermissionToRole_InvalidatesCache() {
        when(roleRepository.findById(1L)).thenReturn(Optional.of(testRole));
        when(permissionRepository.findById(1L)).thenReturn(Optional.of(testPermission));
        when(rolePermissionRepository.existsByRoleAndPermission(testRole, testPermission)).thenReturn(false);
        when(roleRepository.save(testRole)).thenReturn(testRole);
        when(userRoleRepository.findAllPermissionsByUserId(1L)).thenReturn(List.of("perm1"));
        
        rbacService.getCachedPermissionsForUser(1L);
        assertEquals(1, rbacService.getCacheSize());
        
        rbacService.assignPermissionToRole(1L, 1L);
        
        assertEquals(0, rbacService.getCacheSize());
    }
    
    @Test
    void testAssignPermissionsToRole_Success() {
        Permission perm2 = Permission.builder().id(2L).resource("user").action("read").build();
        when(roleRepository.findById(1L)).thenReturn(Optional.of(testRole));
        when(permissionRepository.findByIdIn(Arrays.asList(1L, 2L)))
                .thenReturn(Arrays.asList(testPermission, perm2));
        when(rolePermissionRepository.existsByRoleAndPermission(any(), any())).thenReturn(false);
        when(roleRepository.save(testRole)).thenReturn(testRole);
        
        assertDoesNotThrow(() -> rbacService.assignPermissionsToRole(1L, Arrays.asList(1L, 2L)));
        
        verify(roleRepository).save(testRole);
    }
    
    @Test
    void testAssignPermissionsToRole_RoleNotFound() {
        when(roleRepository.findById(99L)).thenReturn(Optional.empty());
        
        assertThrows(IllegalArgumentException.class, () -> 
            rbacService.assignPermissionsToRole(99L, Arrays.asList(1L, 2L))
        );
    }
    
    @Test
    void testAssignPermissionsToRole_SomePermissionsNotFound() {
        when(roleRepository.findById(1L)).thenReturn(Optional.of(testRole));
        when(permissionRepository.findByIdIn(Arrays.asList(1L, 99L)))
                .thenReturn(List.of(testPermission));
        
        assertThrows(IllegalArgumentException.class, () -> 
            rbacService.assignPermissionsToRole(1L, Arrays.asList(1L, 99L))
        );
    }
    
    @Test
    void testAssignPermissionsToRole_InvalidatesCache() {
        when(roleRepository.findById(1L)).thenReturn(Optional.of(testRole));
        when(permissionRepository.findByIdIn(List.of(1L))).thenReturn(List.of(testPermission));
        when(rolePermissionRepository.existsByRoleAndPermission(any(), any())).thenReturn(false);
        when(roleRepository.save(testRole)).thenReturn(testRole);
        when(userRoleRepository.findAllPermissionsByUserId(1L)).thenReturn(List.of("perm1"));
        
        rbacService.getCachedPermissionsForUser(1L);
        assertEquals(1, rbacService.getCacheSize());
        
        rbacService.assignPermissionsToRole(1L, List.of(1L));
        
        assertEquals(0, rbacService.getCacheSize());
    }
    
    @Test
    void testDeletePermission_AssignedToRoles() {
        when(permissionRepository.findById(1L)).thenReturn(Optional.of(testPermission));
        when(rolePermissionRepository.findByPermission(testPermission)).thenReturn(List.of(mock(com.saas.admin.entity.RolePermission.class)));
        
        assertThrows(IllegalStateException.class, () -> rbacService.deletePermission(1L));
        
        verify(permissionRepository, never()).delete(any());
    }
    
    @Test
    void testDeletePermission_NotFound() {
        when(permissionRepository.findById(99L)).thenReturn(Optional.empty());
        
        assertThrows(IllegalArgumentException.class, () -> rbacService.deletePermission(99L));
    }
    
    @Test
    void testDeleteRole_NotFound() {
        when(roleRepository.findById(99L)).thenReturn(Optional.empty());
        
        assertThrows(IllegalArgumentException.class, () -> rbacService.deleteRole(99L));
    }
    
    @Test
    void testInvalidateCacheByRole_ClearsAllCache() {
        when(userRoleRepository.findAllPermissionsByUserId(1L)).thenReturn(List.of("perm1"));
        when(userRoleRepository.findAllPermissionsByUserId(2L)).thenReturn(List.of("perm2"));
        
        rbacService.getCachedPermissionsForUser(1L);
        rbacService.getCachedPermissionsForUser(2L);
        assertEquals(2, rbacService.getCacheSize());
        
        rbacService.invalidateCacheByRole(1L);
        
        assertEquals(0, rbacService.getCacheSize());
    }
    
    @Test
    void testInvalidateCacheByPermission_ClearsAllCache() {
        when(userRoleRepository.findAllPermissionsByUserId(1L)).thenReturn(List.of("perm1"));
        when(userRoleRepository.findAllPermissionsByUserId(2L)).thenReturn(List.of("perm2"));
        
        rbacService.getCachedPermissionsForUser(1L);
        rbacService.getCachedPermissionsForUser(2L);
        assertEquals(2, rbacService.getCacheSize());
        
        rbacService.invalidateCacheByPermission(1L);
        
        assertEquals(0, rbacService.getCacheSize());
    }
    
    @Test
    void testCacheReloadsAfterInvalidation() {
        List<String> initialPerms = List.of("perm1");
        List<String> updatedPerms = Arrays.asList("perm1", "perm2");
        
        when(userRoleRepository.findAllPermissionsByUserId(1L))
                .thenReturn(initialPerms)
                .thenReturn(updatedPerms);
        
        List<String> first = rbacService.getCachedPermissionsForUser(1L);
        assertEquals(1, first.size());
        
        rbacService.invalidateCacheForUser(1L);
        
        List<String> second = rbacService.getCachedPermissionsForUser(1L);
        assertEquals(2, second.size());
        
        verify(userRoleRepository, times(2)).findAllPermissionsByUserId(1L);
    }
    
    @Test
    void testEvictExpiredCache() {
        when(userRoleRepository.findAllPermissionsByUserId(1L)).thenReturn(List.of("perm1"));
        
        rbacService.getCachedPermissionsForUser(1L);
        assertEquals(1, rbacService.getCacheSize());
        
        rbacService.evictExpiredCache();
        
        assertEquals(1, rbacService.getCacheSize());
    }
    
    @Test
    void testUpdatePermission_Success() {
        when(permissionRepository.findById(1L)).thenReturn(Optional.of(testPermission));
        when(permissionRepository.save(testPermission)).thenReturn(testPermission);
        
        Permission result = rbacService.updatePermission(1L, "Updated description", true);
        
        assertNotNull(result);
        verify(permissionRepository).save(testPermission);
    }
    
    @Test
    void testUpdatePermission_NotFound() {
        when(permissionRepository.findById(99L)).thenReturn(Optional.empty());
        
        assertThrows(IllegalArgumentException.class, () -> 
            rbacService.updatePermission(99L, "description", true)
        );
    }
    
    @Test
    void testUpdateRole_Success() {
        when(roleRepository.findById(1L)).thenReturn(Optional.of(testRole));
        when(roleRepository.save(testRole)).thenReturn(testRole);
        
        Role result = rbacService.updateRole(1L, "Updated description", false);
        
        assertNotNull(result);
        verify(roleRepository).save(testRole);
    }
    
    @Test
    void testUpdateRole_NotFound() {
        when(roleRepository.findById(99L)).thenReturn(Optional.empty());
        
        assertThrows(IllegalArgumentException.class, () -> 
            rbacService.updateRole(99L, "description", true)
        );
    }
    
    // =========================================================================
    // ADDITIONAL TESTS FOR CACHE EXPIRY AND BULK ASSIGNMENT FAILURES
    // =========================================================================
    
    @Test
    void testCacheInvalidation_OnRoleUpdate() {
        when(userRoleRepository.findAllPermissionsByUserId(1L)).thenReturn(List.of("perm1", "perm2"));
        when(roleRepository.findById(1L)).thenReturn(Optional.of(testRole));
        when(roleRepository.save(testRole)).thenReturn(testRole);
        
        rbacService.getCachedPermissionsForUser(1L);
        assertEquals(1, rbacService.getCacheSize());
        
        rbacService.updateRole(1L, "Updated", true);
        
        assertEquals(0, rbacService.getCacheSize());
    }
    
    @Test
    void testCacheInvalidation_OnPermissionUpdate() {
        when(userRoleRepository.findAllPermissionsByUserId(1L)).thenReturn(List.of("perm1"));
        when(permissionRepository.findById(1L)).thenReturn(Optional.of(testPermission));
        when(permissionRepository.save(testPermission)).thenReturn(testPermission);
        
        rbacService.getCachedPermissionsForUser(1L);
        assertEquals(1, rbacService.getCacheSize());
        
        rbacService.updatePermission(1L, "Updated", true);
        
        assertEquals(0, rbacService.getCacheSize());
    }
    
    @Test
    void testAssignPermissionToRole_DuplicateReturnsEarly() {
        when(roleRepository.findById(1L)).thenReturn(Optional.of(testRole));
        when(permissionRepository.findById(1L)).thenReturn(Optional.of(testPermission));
        when(rolePermissionRepository.existsByRoleAndPermission(testRole, testPermission)).thenReturn(true);
        
        rbacService.assignPermissionToRole(1L, 1L);
        
        verify(roleRepository, never()).save(any());
    }
    
    @Test
    void testAssignPermissionToRole_NotDuplicate() {
        when(roleRepository.findById(1L)).thenReturn(Optional.of(testRole));
        when(permissionRepository.findById(1L)).thenReturn(Optional.of(testPermission));
        when(rolePermissionRepository.existsByRoleAndPermission(testRole, testPermission)).thenReturn(false);
        when(roleRepository.save(any())).thenReturn(testRole);
        
        rbacService.assignPermissionToRole(1L, 1L);
        
        verify(roleRepository).save(testRole);
    }
    
    @Test
    void testRemovePermissionFromRole_CallsRoleRepository() {
        when(roleRepository.findById(1L)).thenReturn(Optional.of(testRole));
        when(permissionRepository.findById(1L)).thenReturn(Optional.of(testPermission));
        when(roleRepository.save(any())).thenReturn(testRole);
        
        rbacService.removePermissionFromRole(1L, 1L);
        
        verify(roleRepository).save(testRole);
    }
    
    @Test
    void testInvalidateCacheAll_EmptiesEverything() {
        when(userRoleRepository.findAllPermissionsByUserId(1L)).thenReturn(List.of("perm1"));
        when(userRoleRepository.findAllPermissionsByUserId(2L)).thenReturn(List.of("perm2"));
        
        rbacService.getCachedPermissionsForUser(1L);
        rbacService.getCachedPermissionsForUser(2L);
        assertEquals(2, rbacService.getCacheSize());
        
        rbacService.invalidateCacheAll();
        
        assertEquals(0, rbacService.getCacheSize());
    }
    
    @Test
    void testDeleteRole_WithAssignedUsers_ThrowsException() {
        when(roleRepository.findById(1L)).thenReturn(Optional.of(testRole));
        when(userRoleRepository.countByRole(testRole)).thenReturn(5L);
        
        assertThrows(IllegalStateException.class, () -> 
            rbacService.deleteRole(1L)
        );
    }
    
    @Test
    void testDeleteRole_NoAssignedUsers_Success() {
        when(roleRepository.findById(1L)).thenReturn(Optional.of(testRole));
        when(userRoleRepository.countByRole(testRole)).thenReturn(0L);
        
        rbacService.deleteRole(1L);
        
        verify(roleRepository).delete(testRole);
    }
}
