package com.ruoyi.web.modules.account.support;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.when;
import java.util.Collections;
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 com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.web.modules.account.constant.PlatformAdminConstants;
import com.ruoyi.web.modules.account.dto.PlatformAdminCreateDTO;
import com.ruoyi.web.modules.account.dto.PlatformAdminUpdateDTO;
import com.ruoyi.system.mapper.SysRoleMapper;
import com.ruoyi.web.modules.account.mapper.PlatformAdminMapper;
import com.ruoyi.web.modules.account.vo.PlatformAdminRoleOptionVO;
import com.ruoyi.web.modules.store.mapper.BizMerchantAccountMapper;

@ExtendWith(MockitoExtension.class)
class PlatformAdminSupportTest
{
    @Mock
    private PlatformAdminMapper platformAdminMapper;

    @Mock
    private SysRoleMapper roleMapper;

    @Mock
    private BizMerchantAccountMapper merchantAccountMapper;

    @InjectMocks
    private PlatformAdminSupport support;

    @Test
    void resolveAdminName_prefersNickName()
    {
        assertEquals("张三", support.resolveAdminName("张三", "zhangsan"));
        assertEquals("zhangsan", support.resolveAdminName(null, "zhangsan"));
    }

    @Test
    void validateCreate_rejectsMemberRole()
    {
        PlatformAdminCreateDTO dto = buildCreateDto();
        dto.setRoleIds(new Long[] { 99L });
        SysRole memberRole = new SysRole();
        memberRole.setRoleId(99L);
        memberRole.setRoleKey("member");
        memberRole.setDelFlag("0");
        memberRole.setStatus("0");
        when(roleMapper.selectRoleById(99L)).thenReturn(memberRole);

        ServiceException ex = assertThrows(ServiceException.class, () -> support.validateCreate(dto));
        assertEquals(PlatformAdminConstants.MSG_INVALID_ROLE, ex.getMessage());
    }

    @Test
    void assertDeletable_rejectsSelf()
    {
        ServiceException ex = assertThrows(ServiceException.class,
                () -> support.assertDeletable(new Long[] { 5L }, 5L, Collections.emptyList()));
        assertEquals(PlatformAdminConstants.MSG_CANNOT_DELETE_SELF, ex.getMessage());
    }

    @Test
    void assertDeletable_rejectsBuiltinAdmin()
    {
        ServiceException ex = assertThrows(ServiceException.class,
                () -> support.assertDeletable(new Long[] { 1L }, 2L, Collections.emptyList()));
        assertEquals(PlatformAdminConstants.MSG_CANNOT_DELETE_BUILTIN_ADMIN, ex.getMessage());
    }

    @Test
    void assertDeletable_rejectsLastAdmin()
    {
        when(platformAdminMapper.existsInListScope(eq(10L), any())).thenReturn(1);
        when(platformAdminMapper.countUsersWithRoleKeyAmong(PlatformAdminConstants.ADMIN_ROLE_KEY, new Long[] { 10L }))
                .thenReturn(1);
        when(platformAdminMapper.countUsersWithRoleKey(PlatformAdminConstants.ADMIN_ROLE_KEY)).thenReturn(1);

        ServiceException ex = assertThrows(ServiceException.class,
                () -> support.assertDeletable(new Long[] { 10L }, 2L, Collections.emptyList()));
        assertEquals(PlatformAdminConstants.MSG_KEEP_ONE_ADMIN, ex.getMessage());
    }

    @Test
    void assertDeletable_rejectsMerchantAccountBound()
    {
        when(platformAdminMapper.existsInListScope(eq(10L), any())).thenReturn(1);
        when(platformAdminMapper.countUsersWithRoleKeyAmong(PlatformAdminConstants.ADMIN_ROLE_KEY, new Long[] { 10L }))
                .thenReturn(0);
        when(platformAdminMapper.countUsersWithRoleKey(PlatformAdminConstants.ADMIN_ROLE_KEY)).thenReturn(2);
        SysUser user = new SysUser();
        user.setUserId(10L);
        user.setUserName("bound01");
        when(merchantAccountMapper.countByAccountId(10L)).thenReturn(1);

        ServiceException ex = assertThrows(ServiceException.class,
                () -> support.assertDeletable(new Long[] { 10L }, 2L, Collections.singletonList(user)));
        assertEquals(PlatformAdminConstants.MSG_MERCHANT_ACCOUNT_BOUND, ex.getMessage());
    }

    @Test
    void assertEditableRoles_rejectsRemovingOnlyAdmin()
    {
        SysRole adminRole = new SysRole();
        adminRole.setRoleId(1L);
        adminRole.setRoleKey(PlatformAdminConstants.ADMIN_ROLE_KEY);
        adminRole.setDelFlag("0");
        adminRole.setStatus("0");
        SysRole shopRole = new SysRole();
        shopRole.setRoleId(2L);
        shopRole.setRoleKey(PlatformAdminConstants.MERCHANT_ROLE_KEY);
        shopRole.setDelFlag("0");
        shopRole.setStatus("0");
        when(roleMapper.selectRoleById(2L)).thenReturn(shopRole);
        when(platformAdminMapper.userHasRoleKey(10L, PlatformAdminConstants.ADMIN_ROLE_KEY)).thenReturn(1);
        when(platformAdminMapper.countUsersWithRoleKey(PlatformAdminConstants.ADMIN_ROLE_KEY)).thenReturn(1);
        when(roleMapper.selectRoleList(any())).thenReturn(Collections.singletonList(adminRole));

        ServiceException ex = assertThrows(ServiceException.class,
                () -> support.assertEditableRoles(10L, new Long[] { 2L }, 99L));
        assertEquals(PlatformAdminConstants.MSG_KEEP_ONE_ADMIN, ex.getMessage());
    }

    @Test
    void mergeRoleIdsOnUpdate_preservesNonPlatformRoles()
    {
        PlatformAdminRoleOptionVO member = new PlatformAdminRoleOptionVO();
        member.setRoleId(8L);
        member.setRoleKey("member");
        when(platformAdminMapper.selectAllRolesByUserId(10L)).thenReturn(Collections.singletonList(member));

        Long[] merged = support.mergeRoleIdsOnUpdate(10L, new Long[] { 2L });
        assertEquals(2, merged.length);
        assertTrue(java.util.Arrays.asList(merged).contains(8L));
        assertTrue(java.util.Arrays.asList(merged).contains(2L));
    }

    private PlatformAdminCreateDTO buildCreateDto()
    {
        PlatformAdminCreateDTO dto = new PlatformAdminCreateDTO();
        dto.setAdminName("运营甲");
        dto.setUserName("pad_user01");
        dto.setPhonenumber("17700001111");
        dto.setPassword("Admin@123");
        dto.setRoleIds(new Long[] { 2L });
        return dto;
    }
}
