package com.cf.imes.module.system.controller.admin.dict;

import com.cf.imes.framework.common.enums.CommonStatusEnum;
import com.cf.imes.framework.common.pojo.PageResult;
import com.cf.imes.framework.test.core.ut.BaseWebUnitTest;
import com.cf.imes.module.system.controller.admin.dict.vo.data.DictDataSaveReqVO;
import com.cf.imes.module.system.controller.admin.dict.vo.data.DictDataSimpleRespVO;
import com.cf.imes.module.system.controller.admin.dict.vo.data.DictDataTransReqVO;
import com.cf.imes.module.system.dal.dataobject.dict.DictDataDO;
import com.cf.imes.module.system.service.dict.DictDataService;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.http.MediaType;
import org.springframework.test.context.bean.override.mockito.MockitoBean;
import org.springframework.test.web.servlet.MockMvc;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

/**
 * 字典数据管理单元测试
 *
 * @author Gqr
 * @since 2026/1/14 15:38
 */
@WebMvcTest(controllers = DictDataController.class, excludeAutoConfiguration = SecurityAutoConfiguration.class)
class DictDataControllerTest extends BaseWebUnitTest {
    @Autowired
    private MockMvc mockMvc;

    @MockitoBean
    private DictDataService dictDataService;

    @Autowired
    private ObjectMapper objectMapper;

    @Test
    void createDictData_success() throws Exception {
        DictDataSaveReqVO reqVO = new DictDataSaveReqVO();
        reqVO.setSort(1);
        reqVO.setLabel("启用");
        reqVO.setDictType("status");
        reqVO.setValue("1");
        reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus());

        when(dictDataService.createDictData(any()))
                .thenReturn(100L);

        mockMvc.perform(post("/system/dict-data/create")
                        .contentType(MediaType.APPLICATION_JSON)
                        .content(objectMapper.writeValueAsString(reqVO)))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$.code").value(0))
                .andExpect(jsonPath("$.data").value(100L));
    }

    @Test
    void updateDictData_success() throws Exception {
        DictDataSaveReqVO reqVO = new DictDataSaveReqVO();
        reqVO.setId(1L);
        reqVO.setDictType("status");
        reqVO.setValue("1");
        reqVO.setLabel("启用");
        reqVO.setSort(1);
        reqVO.setStatus(1);

        mockMvc.perform(put("/system/dict-data/update")
                        .contentType(MediaType.APPLICATION_JSON)
                        .content(objectMapper.writeValueAsString(reqVO)))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$.code").value(0))
                .andExpect(jsonPath("$.data").value(true));

        // 核心断言：Service 被调用
        verify(dictDataService).updateDictData(any(DictDataSaveReqVO.class));
    }

    @Test
    void deleteDictData_success() throws Exception {
        mockMvc.perform(delete("/system/dict-data/delete")
                        .param("id", "1"))
                .andExpect(status().isOk());

        verify(dictDataService).deleteDictData(1L);
    }

    @Test
    void getSimpleDictDataList_success() throws Exception {
        Map<String, List<DictDataSimpleRespVO>> mockResult = new HashMap<>();
        mockResult.put("zh", List.of(new DictDataSimpleRespVO().setLabel("启用")));

        when(dictDataService.getAllLanguageDictData()).thenReturn(mockResult);

        mockMvc.perform(get("/system/dict-data/list-all-simple"))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$.code").value(0))
                .andExpect(jsonPath("$.data.zh[0].label").value("启用"));

        verify(dictDataService).getAllLanguageDictData();
    }

    @Test
    void getDictTypePage_success() throws Exception {
        DictDataDO dictData = new DictDataDO();
        dictData.setId(1L);
        dictData.setLabel("启用");

        PageResult<DictDataDO> pageResult = new PageResult<>();
        pageResult.setTotal(1L);
        pageResult.setList(List.of(dictData));

        when(dictDataService.getDictDataPage(any()))
                .thenReturn(pageResult);

        mockMvc.perform(get("/system/dict-data/page")
                        .param("pageNo", "1")
                        .param("pageSize", "10"))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$.code").value(0))
                .andExpect(jsonPath("$.data.total").value(1))
                .andExpect(jsonPath("$.data.list[0].label").value("启用"));

        verify(dictDataService).getDictDataPage(any());
    }

    @Test
    void getDictData_success() throws Exception {
        DictDataDO dictData = new DictDataDO();
        dictData.setId(1L);
        dictData.setLabel("启用");

        when(dictDataService.getDictData(1L)).thenReturn(dictData);

        mockMvc.perform(get("/system/dict-data/get")
                        .param("id", "1"))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$.code").value(0))
                .andExpect(jsonPath("$.data.label").value("启用"));

        verify(dictDataService).getDictData(1L);
    }

    @Test
    void export_success() throws Exception {
        when(dictDataService.getDictDataPage(any()))
                .thenReturn(new PageResult<>(List.of(), 0L));

        mockMvc.perform(get("/system/dict-data/export")
                        .param("pageNo", "1")
                        .param("pageSize", "10"))
                .andExpect(status().isOk());

        verify(dictDataService).getDictDataPage(any());
    }

    @Test
    void trans_success() throws Exception {
        DictDataTransReqVO reqVO = new DictDataTransReqVO();
        reqVO.setTargetLanguage("en");

        mockMvc.perform(post("/system/dict-data/trans")
                        .contentType(MediaType.APPLICATION_JSON)
                        .content(objectMapper.writeValueAsString(reqVO)))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$.code").value(0))
                .andExpect(jsonPath("$.data").value(true));

        verify(dictDataService).trans(any(DictDataTransReqVO.class));
    }

    @Test
    void getVersion_success() throws Exception {
        when(dictDataService.getI18nVersion()).thenReturn(3);

        mockMvc.perform(get("/system/dict-data/i18n/version"))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$.code").value(0))
                .andExpect(jsonPath("$.data").value(3));

        verify(dictDataService).getI18nVersion();
    }

    @Test
    void updateVersion_success() throws Exception {
        mockMvc.perform(post("/system/dict-data/i18n/version"))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$.code").value(0))
                .andExpect(jsonPath("$.data").value(true));

        verify(dictDataService).updateI18nVersion();
    }


}
