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

import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.Collections;
import org.junit.jupiter.api.BeforeEach;
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 org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import com.ruoyi.web.modules.home.service.IHomeAppService;
import com.ruoyi.web.modules.home.vo.HomeBannerVO;
import com.ruoyi.web.modules.home.vo.HomeCategoryNavVO;
import com.ruoyi.web.modules.home.vo.HomeHotGoodsVO;

/**
 * C 端商城首页接口测试（MHP-API-001～010）
 */
@ExtendWith(MockitoExtension.class)
class HomeAppControllerTest
{
    @Mock
    private IHomeAppService homeAppService;

    @InjectMocks
    private HomeAppController controller;

    private MockMvc mockMvc;

    @BeforeEach
    void setUp()
    {
        mockMvc = MockMvcBuilders.standaloneSetup(controller).build();
    }

    @Test
    void banners_returns200WithoutToken() throws Exception
    {
        HomeBannerVO vo = new HomeBannerVO();
        vo.setBannerId(1L);
        vo.setBannerImage("/profile/upload/b1.jpg");
        vo.setSortNo(0);
        when(homeAppService.listBanners()).thenReturn(Collections.singletonList(vo));

        mockMvc.perform(get("/api/home/banners"))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$.code").value(200))
                .andExpect(jsonPath("$.data[0].bannerId").value(1))
                .andExpect(jsonPath("$.data[0].bannerImage").value("/profile/upload/b1.jpg"))
                .andExpect(jsonPath("$.data[0].sortNo").value(0));
    }

    @Test
    void banners_emptyList() throws Exception
    {
        when(homeAppService.listBanners()).thenReturn(Collections.emptyList());

        mockMvc.perform(get("/api/home/banners"))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$.code").value(200))
                .andExpect(jsonPath("$.data").isArray())
                .andExpect(jsonPath("$.data").isEmpty());
    }

    @Test
    void categories_returns200WithoutToken() throws Exception
    {
        HomeCategoryNavVO c1 = new HomeCategoryNavVO();
        c1.setCategoryId(1L);
        c1.setCategoryName("兽药");
        c1.setCategoryPic("/pic/vet.jpg");
        c1.setSortNo(0);
        when(homeAppService.listPlatformLevel1Nav()).thenReturn(Collections.singletonList(c1));

        mockMvc.perform(get("/api/home/categories"))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$.code").value(200))
                .andExpect(jsonPath("$.data[0].categoryId").value(1))
                .andExpect(jsonPath("$.data[0].categoryName").value("兽药"))
                .andExpect(jsonPath("$.data[0].categoryPic").value("/pic/vet.jpg"))
                .andExpect(jsonPath("$.data[0].sortNo").value(0));
    }

    @Test
    void categories_emptyList() throws Exception
    {
        when(homeAppService.listPlatformLevel1Nav()).thenReturn(Collections.emptyList());

        mockMvc.perform(get("/api/home/categories"))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$.code").value(200))
                .andExpect(jsonPath("$.data").isArray())
                .andExpect(jsonPath("$.data").isEmpty());
    }

    @Test
    void hotGoods_returns200WithoutToken() throws Exception
    {
        HomeHotGoodsVO g1 = hotGoods(1L, "G001");
        when(homeAppService.listHotGoods()).thenReturn(Collections.singletonList(g1));

        mockMvc.perform(get("/api/home/hot-goods"))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$.code").value(200))
                .andExpect(jsonPath("$.data[0].goodsId").value(1))
                .andExpect(jsonPath("$.data[0].goodsSn").value("G001"))
                .andExpect(jsonPath("$.data[0].goodsName").value("测试商品"))
                .andExpect(jsonPath("$.data[0].mainPic").value("/pic/g1.jpg"))
                .andExpect(jsonPath("$.data[0].salePrice").value(88.50))
                .andExpect(jsonPath("$.data[0].shopId").value(101))
                .andExpect(jsonPath("$.data[0].shopName").value("测试店"));
    }

    @Test
    void hotGoods_emptyList() throws Exception
    {
        when(homeAppService.listHotGoods()).thenReturn(Collections.emptyList());

        mockMvc.perform(get("/api/home/hot-goods"))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$.code").value(200))
                .andExpect(jsonPath("$.data").isArray())
                .andExpect(jsonPath("$.data").isEmpty());
    }

    @Test
    void hotGoods_returnsMultipleItems() throws Exception
    {
        when(homeAppService.listHotGoods()).thenReturn(Arrays.asList(
                hotGoods(1L, "G001"),
                hotGoods(2L, "G002"),
                hotGoods(3L, "G003")));

        mockMvc.perform(get("/api/home/hot-goods"))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$.code").value(200))
                .andExpect(jsonPath("$.data.length()").value(3));
    }

    @Test
    void hotGoods_preservesOrder() throws Exception
    {
        HomeHotGoodsVO g1 = hotGoods(1L, "G001");
        HomeHotGoodsVO g3 = hotGoods(3L, "G003");
        when(homeAppService.listHotGoods()).thenReturn(Arrays.asList(g1, g3));

        mockMvc.perform(get("/api/home/hot-goods"))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$.data[0].goodsId").value(1))
                .andExpect(jsonPath("$.data[1].goodsId").value(3));
    }

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