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

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.util.Collections;
import java.util.Date;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentCaptor;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.system.mapper.SysUserMapper;
import com.ruoyi.system.mapper.SysUserPostMapper;
import com.ruoyi.system.mapper.SysUserRoleMapper;
import com.ruoyi.system.service.ISysUserService;
import com.ruoyi.web.modules.account.constant.PlatformAdminConstants;
import com.ruoyi.web.modules.account.domain.PlatformAdminQuery;
import com.ruoyi.web.modules.account.domain.PlatformAdminRow;
import com.ruoyi.web.modules.account.dto.PlatformAdminCreateDTO;
import com.ruoyi.web.modules.account.dto.PlatformAdminUpdateDTO;
import com.ruoyi.web.modules.account.mapper.PlatformAdminMapper;
import com.ruoyi.web.modules.account.service.impl.PlatformAdminServiceImpl;
import com.ruoyi.web.modules.account.support.PlatformAdminSupport;
import com.ruoyi.web.modules.account.vo.PlatformAdminListVO;

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

    @Mock
    private PlatformAdminSupport platformAdminSupport;

    @Mock
    private ISysUserService sysUserService;

    @Mock
    private SysUserMapper sysUserMapper;

    @Mock
    private SysUserRoleMapper sysUserRoleMapper;

    @Mock
    private SysUserPostMapper sysUserPostMapper;

    @InjectMocks
    private PlatformAdminServiceImpl platformAdminService;

    @Test
    void selectAdminList_mapsAdminName()
    {
        PlatformAdminRow row = new PlatformAdminRow();
        row.setUserId(10L);
        row.setUserName("pad01");
        row.setNickName("运营甲");
        row.setPhonenumber("17700001111");
        row.setCreateTime(new Date());
        row.setRoleNames("商户经营");
        when(platformAdminMapper.selectList(any(PlatformAdminQuery.class))).thenReturn(Collections.singletonList(row));
        when(platformAdminSupport.resolveAdminName("运营甲", "pad01")).thenReturn("运营甲");

        PlatformAdminListVO vo = platformAdminService.selectAdminList(new PlatformAdminQuery()).get(0);
        assertEquals("运营甲", vo.getAdminName());
        assertEquals("商户经营", vo.getRoleNames());
    }

    @Test
    void selectAdminDetail_notFound()
    {
        when(platformAdminMapper.selectByUserId(eq(99L), any())).thenReturn(null);
        assertThrows(ServiceException.class, () -> platformAdminService.selectAdminDetail(99L));
    }

    @Test
    void createAdmin_duplicateUsername()
    {
        PlatformAdminCreateDTO dto = new PlatformAdminCreateDTO();
        dto.setAdminName("甲");
        dto.setUserName("dup");
        dto.setPhonenumber("17700001111");
        dto.setPassword("Admin@123");
        dto.setRoleIds(new Long[] { 2L });
        when(sysUserService.checkUserNameUnique(any(SysUser.class))).thenReturn(false);

        ServiceException ex = assertThrows(ServiceException.class,
                () -> platformAdminService.createAdmin(dto, "admin"));
        assertEquals(PlatformAdminConstants.MSG_USERNAME_EXISTS, ex.getMessage());
        verify(sysUserService, never()).insertUser(any(SysUser.class));
    }

    @Test
    void createAdmin_success()
    {
        PlatformAdminCreateDTO dto = new PlatformAdminCreateDTO();
        dto.setAdminName("甲");
        dto.setUserName("pad_new");
        dto.setPhonenumber("17700002222");
        dto.setPassword("Admin@123");
        dto.setRoleIds(new Long[] { 2L });
        when(sysUserService.checkUserNameUnique(any(SysUser.class))).thenReturn(true);
        when(sysUserService.checkPhoneUnique(any(SysUser.class))).thenReturn(true);
        when(sysUserService.insertUser(any(SysUser.class))).thenAnswer(invocation -> {
            SysUser user = invocation.getArgument(0);
            user.setUserId(100L);
            return 1;
        });

        Long userId = platformAdminService.createAdmin(dto, "admin");
        assertEquals(100L, userId);
        verify(sysUserService).insertUser(any(SysUser.class));
    }

    @Test
    void updateAdmin_keepsUsername()
    {
        PlatformAdminUpdateDTO dto = new PlatformAdminUpdateDTO();
        dto.setUserId(10L);
        dto.setAdminName("新名称");
        dto.setPhonenumber("17700003333");
        dto.setRoleIds(new Long[] { 2L });
        SysUser existing = new SysUser();
        existing.setUserId(10L);
        existing.setUserName("old_login");
        existing.setDelFlag("0");
        when(sysUserService.selectUserById(10L)).thenReturn(existing);
        when(sysUserService.checkPhoneUnique(any(SysUser.class))).thenReturn(true);
        when(platformAdminSupport.mergeRoleIdsOnUpdate(10L, dto.getRoleIds())).thenReturn(new Long[] { 2L });

        platformAdminService.updateAdmin(dto, 1L, "admin");

        ArgumentCaptor<SysUser> captor = ArgumentCaptor.forClass(SysUser.class);
        verify(sysUserService).updateUser(captor.capture());
        assertEquals("old_login", captor.getValue().getUserName());
        assertEquals("新名称", captor.getValue().getNickName());
    }

    @Test
    void deleteAdmin_success()
    {
        Long[] userIds = new Long[] { 10L };
        SysUser user = new SysUser();
        user.setUserId(10L);
        user.setUserName("merchant01");
        when(sysUserService.selectUserById(10L)).thenReturn(user);

        platformAdminService.deleteAdmin(userIds, 2L);

        verify(platformAdminSupport).assertDeletable(userIds, 2L, Collections.singletonList(user));
        verify(sysUserRoleMapper).deleteUserRoleByUserId(10L);
        verify(sysUserPostMapper).deleteUserPostByUserId(10L);
        verify(sysUserMapper).deleteUserById(10L);
    }
}
