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

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.Mockito.verify;
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.exception.ServiceException;
import com.ruoyi.web.modules.merchant.vo.MerchantShopBriefVO;
import com.ruoyi.web.modules.store.constant.ShopConstants;
import com.ruoyi.web.modules.store.domain.BizMerchantAccount;
import com.ruoyi.web.modules.store.domain.BizShop;
import com.ruoyi.web.modules.store.dto.SellerShopSwitchDTO;
import com.ruoyi.web.modules.store.mapper.BizShopMapper;
import com.ruoyi.web.modules.store.service.impl.SellerShopContextServiceImpl;
import com.ruoyi.web.modules.store.support.SellerShopContextSupport;
import com.ruoyi.web.modules.store.vo.SellerContextVO;

@ExtendWith(MockitoExtension.class)
class SellerShopContextServiceImplTest
{
    private static final String SESSION_TOKEN = "session-token-abc";

    @Mock
    private SellerShopContextSupport sellerShopContextSupport;

    @Mock
    private BizShopMapper shopMapper;

    @InjectMocks
    private SellerShopContextServiceImpl sellerShopContextService;

    @Test
    void selectContext_adminReturnsCurrentShop()
    {
        BizMerchantAccount account = adminAccount();
        when(sellerShopContextSupport.requireSellerAccount(10L)).thenReturn(account);
        when(sellerShopContextSupport.resolveCurrentShopId(SESSION_TOKEN, account)).thenReturn(201L);
        when(sellerShopContextSupport.isMerchantAdmin(account)).thenReturn(true);
        when(shopMapper.selectById(201L)).thenReturn(shop(201L, "一号店"));
        when(shopMapper.selectBriefByMerchantId(1L)).thenReturn(Collections.singletonList(
                new MerchantShopBriefVO(201L, "一号店", "0")));

        SellerContextVO vo = sellerShopContextService.selectContext(10L, SESSION_TOKEN);

        assertEquals(201L, vo.getShopId());
        assertEquals(ShopConstants.ACCOUNT_TYPE_ADMIN, vo.getAccountType());
    }

    @Test
    void switchShop_adminPersistsSelection()
    {
        BizMerchantAccount account = adminAccount();
        SellerShopSwitchDTO dto = new SellerShopSwitchDTO();
        dto.setShopId(202L);
        when(sellerShopContextSupport.requireSellerAccount(10L)).thenReturn(account);
        when(sellerShopContextSupport.isMerchantAdmin(account)).thenReturn(true);
        when(shopMapper.selectById(202L)).thenReturn(shop(202L, "二号店"));
        when(shopMapper.selectBriefByMerchantId(1L)).thenReturn(Collections.singletonList(
                new MerchantShopBriefVO(202L, "二号店", "0")));

        SellerContextVO vo = sellerShopContextService.switchShop(10L, SESSION_TOKEN, dto);

        assertEquals(202L, vo.getShopId());
        verify(sellerShopContextSupport).saveSelectedShopId(SESSION_TOKEN, 202L);
    }

    @Test
    void switchShop_employeeForbidden()
    {
        BizMerchantAccount account = employeeAccount();
        SellerShopSwitchDTO dto = new SellerShopSwitchDTO();
        dto.setShopId(102L);
        when(sellerShopContextSupport.requireSellerAccount(20L)).thenReturn(account);
        when(sellerShopContextSupport.isMerchantAdmin(account)).thenReturn(false);

        ServiceException ex = assertThrows(ServiceException.class,
                () -> sellerShopContextService.switchShop(20L, SESSION_TOKEN, dto));

        assertEquals(ShopConstants.MSG_SHOP_SWITCH_FORBIDDEN, ex.getMessage());
    }

    private BizMerchantAccount adminAccount()
    {
        BizMerchantAccount account = new BizMerchantAccount();
        account.setMerchantId(1L);
        return account;
    }

    private BizMerchantAccount employeeAccount()
    {
        BizMerchantAccount account = new BizMerchantAccount();
        account.setMerchantId(1L);
        account.setShopId(101L);
        return account;
    }

    private BizShop shop(Long shopId, String shopName)
    {
        BizShop shop = new BizShop();
        shop.setShopId(shopId);
        shop.setShopName(shopName);
        return shop;
    }
}
