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

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.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.util.Map;
import org.junit.jupiter.api.Test;
import com.ruoyi.web.modules.merchant.vo.OpenShopCheckVO;
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.web.modules.merchant.constant.MerchantConstants;
import com.ruoyi.web.modules.merchant.domain.BizMerchant;
import com.ruoyi.web.modules.merchant.dto.MerchantCertStatusDTO;
import com.ruoyi.web.modules.merchant.dto.MerchantCreateDTO;
import com.ruoyi.web.modules.merchant.service.IMerchantAccountBindService;
import com.ruoyi.web.modules.merchant.exception.MerchantBatchDeleteException;
import com.ruoyi.web.modules.merchant.facade.IMerchantOrderFacade;
import com.ruoyi.web.modules.merchant.facade.IMerchantShopFacade;
import com.ruoyi.web.modules.merchant.mapper.BizMerchantMapper;
import com.ruoyi.web.modules.merchant.service.impl.MerchantServiceImpl;

@ExtendWith(MockitoExtension.class)
class MerchantServiceImplTest
{
    @Mock
    private BizMerchantMapper merchantMapper;

    @Mock
    private IMerchantOrderFacade orderFacade;

    @Mock
    private IMerchantShopFacade shopFacade;

    @Mock
    private IMerchantAccountBindService accountBindService;

    @InjectMocks
    private MerchantServiceImpl merchantService;

    @Test
    void insert_setsCertNormalAndBizIncomplete()
    {
        MerchantCreateDTO dto = new MerchantCreateDTO();
        dto.setMerchantType(MerchantConstants.TYPE_PERSON);
        dto.setPersonName("张三");
        dto.setIdCardNo("110101199001011234");
        dto.setBindType("SYS_USER");
        dto.setBindUserId(10L);
        when(merchantMapper.countByIdCardNo(any(), eq(null))).thenReturn(0);
        when(merchantMapper.insert(any())).thenAnswer(inv -> {
            BizMerchant m = inv.getArgument(0);
            m.setMerchantId(1L);
            return 1;
        });

        merchantService.insertMerchant(dto, "admin");

        verify(accountBindService).bindAccountOnMerchantCreate(eq(1L), eq(dto), eq("admin"));

        assertEquals(MerchantConstants.CERT_NORMAL, dto.getCertStatus());
        assertEquals(MerchantConstants.BIZ_INCOMPLETE, dto.getBizComplete());
        assertEquals(0, dto.getShopCount());
    }

    @Test
    void update_cancelledMerchant_rejected()
    {
        BizMerchant existing = new BizMerchant();
        existing.setMerchantId(1L);
        existing.setCertStatus(MerchantConstants.CERT_CANCELLED);
        when(merchantMapper.selectById(1L)).thenReturn(existing);

        BizMerchant update = new BizMerchant();
        update.setMerchantId(1L);
        assertThrows(ServiceException.class, () -> merchantService.updateMerchant(update, "admin"));
    }

    @Test
    void certStatus_needConfirm_whenNotConfirmed()
    {
        BizMerchant existing = new BizMerchant();
        existing.setMerchantId(1L);
        existing.setCertStatus(MerchantConstants.CERT_NORMAL);
        when(merchantMapper.selectById(1L)).thenReturn(existing);

        MerchantCertStatusDTO dto = new MerchantCertStatusDTO();
        dto.setCertStatus(MerchantConstants.CERT_FROZEN);
        dto.setConfirm(false);

        Map<String, Object> data = merchantService.updateCertStatus(1L, dto, "admin");
        assertTrue((Boolean) data.get("needConfirm"));
        verify(merchantMapper, never()).updateCertStatus(any(), any());
    }

    @Test
    void delete_withShops_rejected()
    {
        BizMerchant m = new BizMerchant();
        m.setMerchantId(1L);
        m.setCertStatus(MerchantConstants.CERT_NORMAL);
        m.setShopCount(2);
        when(merchantMapper.selectById(1L)).thenReturn(m);
        when(orderFacade.hasUnfinishedOrdersByMerchant(1L)).thenReturn(false);

        assertThrows(MerchantBatchDeleteException.class,
                () -> merchantService.deleteMerchantByIds(new Long[] { 1L }, "admin"));
    }

    @Test
    void openShopCheck_bizIncomplete()
    {
        BizMerchant m = new BizMerchant();
        m.setMerchantId(1L);
        m.setCertStatus(MerchantConstants.CERT_NORMAL);
        m.setBizComplete(MerchantConstants.BIZ_INCOMPLETE);
        when(merchantMapper.selectById(1L)).thenReturn(m);

        OpenShopCheckVO vo = merchantService.openShopCheck(1L);
        assertEquals(false, vo.isAllowed());
        assertEquals("经营信息未完善", vo.getReason());
    }
}
