package com.zt.plat.module.base.api.businessdictionarytype;

import com.zt.plat.framework.common.pojo.CommonResult;
import com.zt.plat.framework.common.pojo.PageResult;
import com.zt.plat.module.base.api.businessdictionarytype.dto.BusinessDictionaryDataDTO;
import com.zt.plat.module.base.api.businessdictionarytype.dto.BusinessDictionaryTypePageReqDTO;
import com.zt.plat.module.base.api.businessdictionarytype.dto.BusinessDictionaryTypeRespDTO;
import com.zt.plat.module.base.api.businessdictionarytype.dto.BusinessDictionaryTypeSaveReqDTO;
import com.zt.plat.module.base.controller.admin.businessdictionarytype.vo.BusinessDictionaryTypePageReqVO;
import com.zt.plat.module.base.controller.admin.businessdictionarytype.vo.BusinessDictionaryTypeRespVO;
import com.zt.plat.module.base.controller.admin.businessdictionarytype.vo.BusinessDictionaryTypeSaveReqVO;
import com.zt.plat.module.base.dal.dataobject.businessdictionarytype.BusinessDictionaryDataDO;
import com.zt.plat.module.base.dal.dataobject.businessdictionarytype.BusinessDictionaryTypeDO;
import com.zt.plat.module.base.service.businessdictionarytype.BusinessDictionaryTypeService;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentCaptor;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

import java.time.LocalDateTime;
import java.util.List;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

@ExtendWith(MockitoExtension.class)
class BusinessDictionaryTypeApiImplTest {

    @InjectMocks
    private BusinessDictionaryTypeApiImpl api;

    @Mock
    private BusinessDictionaryTypeService businessDictionaryTypeService;

    private BusinessDictionaryTypeSaveReqDTO buildSaveReqDTO() {
        BusinessDictionaryDataDTO dataDTO = new BusinessDictionaryDataDTO();
        dataDTO.setId(10L);
        dataDTO.setLabel("启用");
        dataDTO.setValue("ENABLE");
        dataDTO.setRemark("默认状态");
        BusinessDictionaryTypeSaveReqDTO dto = new BusinessDictionaryTypeSaveReqDTO();
        dto.setId(1L);
        dto.setName("状态字典");
        dto.setType("base_material_status");
        dto.setStatus(0L);
        dto.setRemark("备注");
        dto.setBusinessDictionaryDatas(List.of(dataDTO));
        return dto;
    }

    private BusinessDictionaryTypeRespVO buildRespVO() {
        BusinessDictionaryTypeRespVO respVO = new BusinessDictionaryTypeRespVO();
        respVO.setId(1L);
        respVO.setName("状态字典");
        respVO.setType("base_material_status");
        respVO.setStatus(0L);
        respVO.setRemark("备注");
        respVO.setCreateTime(LocalDateTime.now());
        return respVO;
    }

    @Test
    void createBusinessDictionaryType_shouldForwardToServiceAndReturnConvertedDto() {
        BusinessDictionaryTypeSaveReqDTO reqDTO = buildSaveReqDTO();
        BusinessDictionaryTypeRespVO serviceResp = buildRespVO();
        when(businessDictionaryTypeService.createBusinessDictionaryType(any(BusinessDictionaryTypeSaveReqVO.class)))
                .thenReturn(serviceResp);

        CommonResult<BusinessDictionaryTypeRespDTO> result = api.createBusinessDictionaryType(reqDTO);

        assertThat(result.isSuccess()).isTrue();
        assertThat(result.getData()).usingRecursiveComparison()
                .ignoringFields("createTime")
                .isEqualTo(BeanAssertHelper.toRespDTO(serviceResp));

        ArgumentCaptor<BusinessDictionaryTypeSaveReqVO> captor = ArgumentCaptor.forClass(BusinessDictionaryTypeSaveReqVO.class);
        verify(businessDictionaryTypeService).createBusinessDictionaryType(captor.capture());
        BusinessDictionaryTypeSaveReqVO passed = captor.getValue();
        assertThat(passed.getName()).isEqualTo(reqDTO.getName());
        assertThat(passed.getBusinessDictionaryDatas()).hasSize(1);
    BusinessDictionaryDataDO dataDO = passed.getBusinessDictionaryDatas().get(0);
        assertThat(dataDO.getLabel()).isEqualTo("启用");
        assertThat(dataDO.getValue()).isEqualTo("ENABLE");
    }

    @Test
    void updateBusinessDictionaryType_shouldInvokeServiceWithConvertedPayload() {
        BusinessDictionaryTypeSaveReqDTO reqDTO = buildSaveReqDTO();

        CommonResult<Boolean> result = api.updateBusinessDictionaryType(reqDTO);

        assertThat(result.isSuccess()).isTrue();
        assertThat(result.getData()).isTrue();
        ArgumentCaptor<BusinessDictionaryTypeSaveReqVO> captor = ArgumentCaptor.forClass(BusinessDictionaryTypeSaveReqVO.class);
        verify(businessDictionaryTypeService).updateBusinessDictionaryType(captor.capture());
        assertThat(captor.getValue().getName()).isEqualTo(reqDTO.getName());
    }

    @Test
    void deleteBusinessDictionaryType_shouldInvokeService() {
        CommonResult<Boolean> result = api.deleteBusinessDictionaryType(123L);

        assertThat(result.isSuccess()).isTrue();
        assertThat(result.getData()).isTrue();
        verify(businessDictionaryTypeService).deleteBusinessDictionaryType(123L);
    }

    @Test
    void deleteBusinessDictionaryTypeList_shouldInvokeService() {
        List<Long> ids = List.of(1L, 2L);

        CommonResult<Boolean> result = api.deleteBusinessDictionaryTypeList(ids);

        assertThat(result.isSuccess()).isTrue();
        assertThat(result.getData()).isTrue();
        verify(businessDictionaryTypeService).deleteBusinessDictionaryTypeListByIds(ids);
    }

    @Test
    void getBusinessDictionaryType_shouldConvertDoToDto() {
        BusinessDictionaryTypeDO typeDO = new BusinessDictionaryTypeDO();
        typeDO.setId(55L);
        typeDO.setName("状态字典");
        when(businessDictionaryTypeService.getBusinessDictionaryType(55L)).thenReturn(typeDO);

        CommonResult<BusinessDictionaryTypeRespDTO> result = api.getBusinessDictionaryType(55L);

        assertThat(result.isSuccess()).isTrue();
        assertThat(result.getData().getId()).isEqualTo(55L);
        assertThat(result.getData().getName()).isEqualTo("状态字典");
    }

    @Test
    void getBusinessDictionaryTypePage_shouldConvertPageResult() {
        BusinessDictionaryTypeDO typeDO = new BusinessDictionaryTypeDO();
        typeDO.setId(11L);
        typeDO.setName("状态");
        PageResult<BusinessDictionaryTypeDO> page = new PageResult<>(List.of(typeDO), 1L);
    when(businessDictionaryTypeService.getBusinessDictionaryTypePage(any(BusinessDictionaryTypePageReqVO.class)))
                .thenReturn(page);

        BusinessDictionaryTypePageReqDTO reqDTO = new BusinessDictionaryTypePageReqDTO();
        reqDTO.setName("状态");
        CommonResult<PageResult<BusinessDictionaryTypeRespDTO>> result = api.getBusinessDictionaryTypePage(reqDTO);

        assertThat(result.isSuccess()).isTrue();
    assertThat(result.getData().getList()).hasSize(1);
    assertThat(result.getData().getList().get(0).getName()).isEqualTo("状态");
        assertThat(result.getData().getTotal()).isEqualTo(1L);
    }

    @Test
    void getBusinessDictionaryDataListByDictionaryTypeId_shouldConvertList() {
        BusinessDictionaryDataDO dataDO = new BusinessDictionaryDataDO();
        dataDO.setId(9L);
        dataDO.setLabel("启用");
        when(businessDictionaryTypeService.getBusinessDictionaryDataListByDictionaryTypeId(8L))
                .thenReturn(List.of(dataDO));

        CommonResult<List<BusinessDictionaryDataDTO>> result = api.getBusinessDictionaryDataListByDictionaryTypeId(8L);

        assertThat(result.isSuccess()).isTrue();
    assertThat(result.getData()).hasSize(1);
    assertThat(result.getData().get(0).getLabel()).isEqualTo("启用");
    }

    @Test
    void getBusinessDictionaryDataListByType_shouldConvertList() {
        BusinessDictionaryDataDO dataDO = new BusinessDictionaryDataDO();
        dataDO.setId(9L);
        dataDO.setValue("ENABLE");
        when(businessDictionaryTypeService.getBusinessDictionaryDataListByType("base_material_status"))
                .thenReturn(List.of(dataDO));

        CommonResult<List<BusinessDictionaryDataDTO>> result = api.getBusinessDictionaryDataListByType("base_material_status");

        assertThat(result.isSuccess()).isTrue();
    assertThat(result.getData()).hasSize(1);
    assertThat(result.getData().get(0).getValue()).isEqualTo("ENABLE");
    }

    private static final class BeanAssertHelper {
        private BeanAssertHelper() {
        }

        static BusinessDictionaryTypeRespDTO toRespDTO(BusinessDictionaryTypeRespVO respVO) {
            BusinessDictionaryTypeRespDTO dto = new BusinessDictionaryTypeRespDTO();
            dto.setId(respVO.getId());
            dto.setName(respVO.getName());
            dto.setType(respVO.getType());
            dto.setStatus(respVO.getStatus());
            dto.setRemark(respVO.getRemark());
            dto.setCreateTime(respVO.getCreateTime());
            return dto;
        }
    }
}
