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

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
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.web.modules.home.constant.HomeConstants;
import com.ruoyi.web.modules.home.mapper.HomeAppMapper;
import com.ruoyi.web.modules.home.service.impl.HomeAppServiceImpl;
import com.ruoyi.web.modules.home.vo.HomeBannerVO;
import com.ruoyi.web.modules.home.vo.HomeCategoryNavVO;
import com.ruoyi.web.modules.home.vo.HomeHotGoodsVO;

/**
 * 商城首页 Service 单元测试（MHP-UT-001～012）
 */
@ExtendWith(MockitoExtension.class)
class HomeAppServiceImplTest
{
    @Mock
    private HomeAppMapper homeAppMapper;

    @InjectMocks
    private HomeAppServiceImpl homeAppService;

    @Test
    void listBanners_delegatesWithLimit()
    {
        HomeBannerVO b1 = banner(1L, "/pic/b1.jpg", 0);
        when(homeAppMapper.selectBannersForHome(HomeConstants.BANNER_LIST_LIMIT))
                .thenReturn(Collections.singletonList(b1));

        List<HomeBannerVO> result = homeAppService.listBanners();

        verify(homeAppMapper).selectBannersForHome(HomeConstants.BANNER_LIST_LIMIT);
        assertEquals(1, result.size());
        assertEquals("/pic/b1.jpg", result.get(0).getBannerImage());
    }

    @Test
    void listBanners_emptyListWhenNoData()
    {
        when(homeAppMapper.selectBannersForHome(HomeConstants.BANNER_LIST_LIMIT))
                .thenReturn(Collections.emptyList());

        List<HomeBannerVO> result = homeAppService.listBanners();

        assertNotNull(result);
        assertTrue(result.isEmpty());
    }

    @Test
    void listBanners_nullMapperResultReturnsEmpty()
    {
        when(homeAppMapper.selectBannersForHome(HomeConstants.BANNER_LIST_LIMIT)).thenReturn(null);

        List<HomeBannerVO> result = homeAppService.listBanners();

        assertNotNull(result);
        assertTrue(result.isEmpty());
    }

    @Test
    void listPlatformLevel1Nav_returnsVisibleCategories()
    {
        HomeCategoryNavVO c1 = category(1L, "兽药", 0);
        HomeCategoryNavVO c2 = category(2L, "饲料", 1);
        when(homeAppMapper.selectPlatformLevel1Nav()).thenReturn(Arrays.asList(c1, c2));

        List<HomeCategoryNavVO> result = homeAppService.listPlatformLevel1Nav();

        assertEquals(2, result.size());
        assertEquals("兽药", result.get(0).getCategoryName());
        assertEquals("饲料", result.get(1).getCategoryName());
    }

    @Test
    void listPlatformLevel1Nav_preservesSortOrder()
    {
        HomeCategoryNavVO c1 = category(1L, "兽药", 0);
        HomeCategoryNavVO c2 = category(2L, "饲料", 1);
        when(homeAppMapper.selectPlatformLevel1Nav()).thenReturn(Arrays.asList(c1, c2));

        List<HomeCategoryNavVO> result = homeAppService.listPlatformLevel1Nav();

        assertEquals(1L, result.get(0).getCategoryId());
        assertEquals(2L, result.get(1).getCategoryId());
    }

    @Test
    void listHotGoods_delegatesWithLimit6()
    {
        when(homeAppMapper.selectHotGoodsForHome(HomeConstants.HOT_GOODS_LIMIT))
                .thenReturn(Collections.singletonList(hotGoods(1L, "G001", 100)));

        homeAppService.listHotGoods();

        verify(homeAppMapper).selectHotGoodsForHome(HomeConstants.HOT_GOODS_LIMIT);
    }

    @Test
    void listHotGoods_returnsAtMostSix()
    {
        HomeHotGoodsVO[] goods = new HomeHotGoodsVO[6];
        for (int i = 0; i < 6; i++)
        {
            goods[i] = hotGoods((long) (i + 1), "G00" + i, 100 - i);
        }
        when(homeAppMapper.selectHotGoodsForHome(HomeConstants.HOT_GOODS_LIMIT))
                .thenReturn(Arrays.asList(goods));

        List<HomeHotGoodsVO> result = homeAppService.listHotGoods();

        assertEquals(6, result.size());
    }

    @Test
    void listHotGoods_preservesSalesOrder()
    {
        HomeHotGoodsVO g1 = hotGoods(1L, "G001", 100);
        HomeHotGoodsVO g3 = hotGoods(3L, "G003", 50);
        when(homeAppMapper.selectHotGoodsForHome(HomeConstants.HOT_GOODS_LIMIT))
                .thenReturn(Arrays.asList(g1, g3));

        List<HomeHotGoodsVO> result = homeAppService.listHotGoods();

        assertEquals(1L, result.get(0).getGoodsId());
        assertEquals(3L, result.get(1).getGoodsId());
    }

    @Test
    void listHotGoods_preservesSameSalesShelfTimeOrder()
    {
        HomeHotGoodsVO g2 = hotGoods(2L, "G002", 100);
        HomeHotGoodsVO g1 = hotGoods(1L, "G001", 100);
        when(homeAppMapper.selectHotGoodsForHome(HomeConstants.HOT_GOODS_LIMIT))
                .thenReturn(Arrays.asList(g2, g1));

        List<HomeHotGoodsVO> result = homeAppService.listHotGoods();

        assertEquals(2L, result.get(0).getGoodsId());
        assertEquals(1L, result.get(1).getGoodsId());
    }

    @Test
    void listHotGoods_preservesGoodsSnTieBreak()
    {
        HomeHotGoodsVO g001 = hotGoods(1L, "G001", 100);
        HomeHotGoodsVO g002 = hotGoods(2L, "G002", 100);
        when(homeAppMapper.selectHotGoodsForHome(HomeConstants.HOT_GOODS_LIMIT))
                .thenReturn(Arrays.asList(g001, g002));

        List<HomeHotGoodsVO> result = homeAppService.listHotGoods();

        assertEquals("G001", result.get(0).getGoodsSn());
        assertEquals("G002", result.get(1).getGoodsSn());
    }

    @Test
    void listHotGoods_includesClosedShopGoods()
    {
        HomeHotGoodsVO g4 = hotGoods(4L, "G004", 80);
        g4.setShopId(102L);
        g4.setShopName("停业店");
        when(homeAppMapper.selectHotGoodsForHome(HomeConstants.HOT_GOODS_LIMIT))
                .thenReturn(Collections.singletonList(g4));

        List<HomeHotGoodsVO> result = homeAppService.listHotGoods();

        assertEquals(1, result.size());
        assertEquals(102L, result.get(0).getShopId());
    }

    @Test
    void listHotGoods_includesZeroStockGoods()
    {
        HomeHotGoodsVO g5 = hotGoods(5L, "G005", 60);
        when(homeAppMapper.selectHotGoodsForHome(HomeConstants.HOT_GOODS_LIMIT))
                .thenReturn(Collections.singletonList(g5));

        List<HomeHotGoodsVO> result = homeAppService.listHotGoods();

        assertEquals(5L, result.get(0).getGoodsId());
    }

    @Test
    void listHotGoods_mapsShopNameFromJoin()
    {
        HomeHotGoodsVO g1 = hotGoods(1L, "G001", 100);
        g1.setShopName("新店名");
        when(homeAppMapper.selectHotGoodsForHome(HomeConstants.HOT_GOODS_LIMIT))
                .thenReturn(Collections.singletonList(g1));

        HomeHotGoodsVO vo = homeAppService.listHotGoods().get(0);

        assertEquals("新店名", vo.getShopName());
    }

    @Test
    void listHotGoods_emptyListWhenNoData()
    {
        when(homeAppMapper.selectHotGoodsForHome(HomeConstants.HOT_GOODS_LIMIT))
                .thenReturn(Collections.emptyList());

        List<HomeHotGoodsVO> result = homeAppService.listHotGoods();

        assertNotNull(result);
        assertTrue(result.isEmpty());
    }

    @Test
    void listHotGoods_nullMapperResultReturnsEmpty()
    {
        when(homeAppMapper.selectHotGoodsForHome(HomeConstants.HOT_GOODS_LIMIT)).thenReturn(null);

        List<HomeHotGoodsVO> result = homeAppService.listHotGoods();

        assertNotNull(result);
        assertTrue(result.isEmpty());
    }

    @Test
    void listPlatformLevel1Nav_emptyListWhenNoData()
    {
        when(homeAppMapper.selectPlatformLevel1Nav()).thenReturn(Collections.emptyList());

        List<HomeCategoryNavVO> result = homeAppService.listPlatformLevel1Nav();

        assertNotNull(result);
        assertTrue(result.isEmpty());
    }

    @Test
    void listPlatformLevel1Nav_nullMapperResultReturnsEmpty()
    {
        when(homeAppMapper.selectPlatformLevel1Nav()).thenReturn(null);

        List<HomeCategoryNavVO> result = homeAppService.listPlatformLevel1Nav();

        assertNotNull(result);
        assertTrue(result.isEmpty());
    }

    private static HomeCategoryNavVO category(Long id, String name, int sortNo)
    {
        HomeCategoryNavVO vo = new HomeCategoryNavVO();
        vo.setCategoryId(id);
        vo.setCategoryName(name);
        vo.setSortNo(sortNo);
        return vo;
    }

    private static HomeBannerVO banner(Long id, String image, int sortNo)
    {
        HomeBannerVO vo = new HomeBannerVO();
        vo.setBannerId(id);
        vo.setBannerImage(image);
        vo.setSortNo(sortNo);
        return vo;
    }

    private static HomeHotGoodsVO hotGoods(Long goodsId, String goodsSn, int salesProxy)
    {
        HomeHotGoodsVO vo = new HomeHotGoodsVO();
        vo.setGoodsId(goodsId);
        vo.setGoodsSn(goodsSn);
        vo.setGoodsName("商品" + goodsSn);
        vo.setMainPic("/pic/" + goodsSn + ".jpg");
        vo.setSalePrice(new BigDecimal("99.00"));
        vo.setShopId(101L);
        vo.setShopName("测试店");
        return vo;
    }
}
