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

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doNothing;
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.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.system.mapper.SysUserMapper;
import com.ruoyi.web.modules.account.constant.AccountManageConstants;
import com.ruoyi.web.modules.account.domain.AccountManageQuery;
import com.ruoyi.web.modules.account.domain.AccountManageRow;
import com.ruoyi.web.modules.account.mapper.AccountManageMapper;
import com.ruoyi.web.modules.account.service.impl.AccountManageServiceImpl;
import com.ruoyi.web.modules.account.support.AccountManageSupport;
import com.ruoyi.web.modules.account.vo.AccountManageListVO;
import com.ruoyi.web.modules.store.domain.BizMerchantAccount;
import com.ruoyi.web.modules.store.mapper.BizMerchantAccountMapper;

@ExtendWith(MockitoExtension.class)
class AccountManageServiceImplTest
{
    @Mock
    private AccountManageMapper accountManageMapper;

    @Mock
    private AccountManageSupport accountManageSupport;

    @Mock
    private IAccountProfileService accountProfileService;

    @Mock
    private BizMerchantAccountMapper merchantAccountMapper;

    @Mock
    private SysUserMapper sysUserMapper;

    @InjectMocks
    private AccountManageServiceImpl accountManageService;

    @Test
    void selectAccountList_masksMobileAndKeepsShopCount()
    {
        AccountManageRow row = new AccountManageRow();
        row.setUserId(10L);
        row.setMerchantId(1L);
        row.setNickName("张老板");
        row.setUserName("13800138000");
        row.setShopCount(2);
        when(accountManageMapper.selectList(any(AccountManageQuery.class))).thenReturn(Collections.singletonList(row));
        when(accountManageSupport.resolveAccountName("张老板", "13800138000")).thenReturn("张老板");
        when(accountManageSupport.resolveMobile(row)).thenReturn("13800138000");

        AccountManageListVO vo = accountManageService.selectAccountList(new AccountManageQuery()).get(0);

        assertEquals("138****8000", vo.getMobile());
        assertEquals(2, vo.getShopCount());
    }

    @Test
    void selectAccountList_nonMerchantShopCountNull()
    {
        AccountManageRow row = new AccountManageRow();
        row.setUserId(20L);
        row.setNickName("平台运营");
        row.setUserName("pad01");
        row.setPhonenumber("17700001111");
        when(accountManageMapper.selectList(any(AccountManageQuery.class))).thenReturn(Collections.singletonList(row));
        when(accountManageSupport.resolveAccountName("平台运营", "pad01")).thenReturn("平台运营");
        when(accountManageSupport.resolveMobile(row)).thenReturn("17700001111");

        AccountManageListVO vo = accountManageService.selectAccountList(new AccountManageQuery()).get(0);

        assertNull(vo.getShopCount());
    }

    @Test
    void deleteAccounts_merchantAdmin_logicDeleteBinding()
    {
        BizMerchantAccount binding = new BizMerchantAccount();
        binding.setAccountId(10L);
        doNothing().when(accountManageSupport).assertDeletable(10L, 99L);
        when(accountManageSupport.findMerchantAdminBinding(10L)).thenReturn(binding);

        accountManageService.deleteAccounts(new Long[] { 10L }, 99L, "admin");

        verify(merchantAccountMapper).logicDeleteByUserId(10L, "admin");
        verify(sysUserMapper, never()).deleteUserById(any());
    }

    @Test
    void deleteAccounts_nonMerchant_deletesSysUser()
    {
        doNothing().when(accountManageSupport).assertDeletable(20L, 99L);
        when(accountManageSupport.findMerchantAdminBinding(20L)).thenReturn(null);

        accountManageService.deleteAccounts(new Long[] { 20L }, 99L, "admin");

        verify(sysUserMapper).deleteUserById(20L);
    }

    @Test
    void selectAccountDetail_notFound()
    {
        when(accountManageSupport.requireAccountRow(99L))
                .thenThrow(new ServiceException(AccountManageConstants.MSG_NOT_FOUND));

        assertThrows(ServiceException.class, () -> accountManageService.selectAccountDetail(99L));
    }
}
