package com.njcn.rdms.module.project.framework.notify;

import com.njcn.rdms.framework.common.pojo.CommonResult;
import com.njcn.rdms.framework.test.core.ut.BaseMockitoUnitTest;
import com.njcn.rdms.module.project.constant.ObjectRoleConstants;
import com.njcn.rdms.module.project.dal.dataobject.member.UserObjectRoleDO;
import com.njcn.rdms.module.project.dal.mysql.member.UserObjectRoleMapper;
import com.njcn.rdms.module.system.api.permission.ObjectPermissionApi;
import com.njcn.rdms.module.system.api.permission.dto.ObjectRoleRespDTO;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;

import java.util.List;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.anySet;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.when;

class TeamNotifyRecipientResolverTest extends BaseMockitoUnitTest {

    @InjectMocks
    private TeamNotifyRecipientResolver resolver;
    @Mock
    private UserObjectRoleMapper userObjectRoleMapper;
    @Mock
    private ObjectPermissionApi objectPermissionApi;

    @Test
    void resolve_filtersInactiveAndCreator_picksManagerAsPrimary() {
        // u1: manager(active) + creator(active) → 保留，代表角色=manager
        // u2: creator only(active) → 排除（纯创建者）
        // u3: watcher(inactive) → 排除（失效）
        UserObjectRoleDO r1 = row(1L, 100L, 0);  // manager role id 100
        UserObjectRoleDO r1c = row(1L, 300L, 0); // creator role id 300
        UserObjectRoleDO r2 = row(2L, 300L, 0);  // creator only
        UserObjectRoleDO r3 = row(3L, 200L, 1);  // watcher inactive
        when(userObjectRoleMapper.selectListByObject("project", 10L))
                .thenReturn(List.of(r1, r1c, r2, r3));
        when(objectPermissionApi.getObjectRoleList(anySet(), eq(ObjectRoleConstants.ROLE_SCOPE_OBJECT), eq("project")))
                .thenReturn(CommonResult.success(List.of(
                        role(100L, "project_manager", "项目经理"),
                        role(200L, "project_watcher", "项目观察者"),
                        role(300L, "project_creator", "项目创建者"))));

        List<TeamRecipient> out = resolver.resolveActiveExcludingCreator(
                "project", 10L, "project_creator", "project_manager");

        assertEquals(1, out.size());
        assertEquals(1L, out.get(0).userId());
        assertEquals("项目经理", out.get(0).roleName());
    }

    @Test
    void resolve_noActiveMembers_returnsEmpty() {
        // 全部失效 → 直接空集，不触达 RPC
        UserObjectRoleDO r1 = row(1L, 100L, 1);
        UserObjectRoleDO r2 = row(2L, 200L, 1);
        when(userObjectRoleMapper.selectListByObject("product", 20L))
                .thenReturn(List.of(r1, r2));

        List<TeamRecipient> out = resolver.resolveActiveExcludingCreator(
                "product", 20L, "product_creator", "product_manager");

        assertTrue(out.isEmpty());
    }

    @Test
    void resolve_mixedActiveInactiveSameUser_inactiveRowIgnored() {
        // u1 同时持有 manager(active) 与 watcher(inactive)：失效行既不应踢掉 u1，也不应成为代表角色
        UserObjectRoleDO r1 = row(1L, 100L, 0);  // manager active
        UserObjectRoleDO r1w = row(1L, 200L, 1); // watcher inactive
        when(userObjectRoleMapper.selectListByObject("project", 10L))
                .thenReturn(List.of(r1, r1w));
        when(objectPermissionApi.getObjectRoleList(anySet(), eq(ObjectRoleConstants.ROLE_SCOPE_OBJECT), eq("project")))
                .thenReturn(CommonResult.success(List.of(
                        role(100L, "project_manager", "项目经理"),
                        role(200L, "project_watcher", "项目观察者"))));

        List<TeamRecipient> out = resolver.resolveActiveExcludingCreator(
                "project", 10L, "project_creator", "project_manager");

        assertEquals(1, out.size());
        assertEquals(1L, out.get(0).userId());
        assertEquals("项目经理", out.get(0).roleName());
    }

    @Test
    void resolve_nonManagerUser_fallsBackToLowestRoleId() {
        // u1 持两个 active 非经理非创建者角色（200 与 400）：代表角色按 roleId 升序取 200
        UserObjectRoleDO r1a = row(1L, 400L, 0);
        UserObjectRoleDO r1b = row(1L, 200L, 0);
        when(userObjectRoleMapper.selectListByObject("project", 10L))
                .thenReturn(List.of(r1a, r1b));
        when(objectPermissionApi.getObjectRoleList(anySet(), eq(ObjectRoleConstants.ROLE_SCOPE_OBJECT), eq("project")))
                .thenReturn(CommonResult.success(List.of(
                        role(200L, "project_watcher", "项目观察者"),
                        role(400L, "project_member", "项目成员"))));

        List<TeamRecipient> out = resolver.resolveActiveExcludingCreator(
                "project", 10L, "project_creator", "project_manager");

        assertEquals(1, out.size());
        assertEquals(1L, out.get(0).userId());
        assertEquals("项目观察者", out.get(0).roleName());
    }

    private UserObjectRoleDO row(Long userId, Long roleId, Integer status) {
        UserObjectRoleDO row = new UserObjectRoleDO();
        row.setUserId(userId);
        row.setRoleId(roleId);
        row.setStatus(status);
        return row;
    }

    private ObjectRoleRespDTO role(Long id, String code, String name) {
        ObjectRoleRespDTO role = new ObjectRoleRespDTO();
        role.setId(id);
        role.setCode(code);
        role.setName(name);
        return role;
    }

}
