package com.njcn.rdms.module.project.framework.security.service;

import com.njcn.rdms.framework.security.core.util.SecurityFrameworkUtils;
import com.njcn.rdms.framework.test.core.ut.BaseMockitoUnitTest;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockedStatic;

import java.util.List;

import static org.mockito.Mockito.mockStatic;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;

class ProjectObjectAuthorizationServiceTest extends BaseMockitoUnitTest {

    @InjectMocks
    private ProjectObjectAuthorizationService authorizationService;
    @Mock
    private ProjectObjectPermissionService projectObjectPermissionService;

    @Test
    void checkOwnerOrProjectPermission_whenCurrentUserIsOwner_shouldSkipProjectPermissionCheck() {
        Long projectId = 1001L;
        Long ownerUserId = 2001L;

        try (MockedStatic<SecurityFrameworkUtils> mockedStatic = mockLoginUser(ownerUserId)) {
            authorizationService.checkOwnerOrProjectPermission(projectId, ownerUserId, "project:task:status");
        }

        verify(projectObjectPermissionService, never()).checkPermission(projectId, "project:task:status", false);
    }

    @Test
    void checkOwnerOrProjectPermission_whenCurrentUserIsNotOwner_shouldCheckProjectPermission() {
        Long projectId = 1002L;
        Long ownerUserId = 2002L;

        try (MockedStatic<SecurityFrameworkUtils> mockedStatic = mockLoginUser(2999L)) {
            authorizationService.checkOwnerOrProjectPermission(projectId, ownerUserId, "project:task:status");
        }

        verify(projectObjectPermissionService).checkPermission(projectId, "project:task:status", false);
    }

    @Test
    void checkAnyOwnerOrProjectPermission_whenCurrentUserMatchesAnyOwner_shouldSkipProjectPermissionCheck() {
        Long projectId = 1003L;

        try (MockedStatic<SecurityFrameworkUtils> mockedStatic = mockLoginUser(3002L)) {
            authorizationService.checkAnyOwnerOrProjectPermission(projectId,
                    List.of(3001L, 3002L, 3003L), "project:task:update");
        }

        verify(projectObjectPermissionService, never()).checkPermission(projectId, "project:task:update", false);
    }

    @Test
    void checkAnyOwnerOrProjectPermission_whenCurrentUserMatchesNoOwner_shouldCheckProjectPermission() {
        Long projectId = 1004L;

        try (MockedStatic<SecurityFrameworkUtils> mockedStatic = mockLoginUser(3999L)) {
            authorizationService.checkAnyOwnerOrProjectPermission(projectId,
                    List.of(3001L, 3002L, 3003L), "project:task:delete");
        }

        verify(projectObjectPermissionService).checkPermission(projectId, "project:task:delete", false);
    }

    private MockedStatic<SecurityFrameworkUtils> mockLoginUser(Long loginUserId) {
        MockedStatic<SecurityFrameworkUtils> mockedStatic = mockStatic(SecurityFrameworkUtils.class);
        mockedStatic.when(SecurityFrameworkUtils::getLoginUserId).thenReturn(loginUserId);
        return mockedStatic;
    }

}
