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

import com.zt.plat.framework.common.pojo.CommonResult;
import com.zt.plat.framework.common.pojo.PageResult;
import com.zt.plat.module.base.api.departmentmaterial.dto.DepartmentMaterialPageReqDTO;
import com.zt.plat.module.base.api.departmentmaterial.dto.DepartmentMaterialRespDTO;
import com.zt.plat.module.base.api.departmentmaterial.dto.DepartmentMaterialSaveReqDTO;
import com.zt.plat.module.base.controller.admin.departmentmaterial.vo.DepartmentMaterialPageReqVO;
import com.zt.plat.module.base.controller.admin.departmentmaterial.vo.DepartmentMaterialRespVO;
import com.zt.plat.module.base.controller.admin.departmentmaterial.vo.DepartmentMaterialSaveReqVO;
import com.zt.plat.module.base.service.departmentmaterial.DepartmentMaterialService;
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 DepartmentMaterialApiImplTest {

    @InjectMocks
    private DepartmentMaterialApiImpl api;

    @Mock
    private DepartmentMaterialService departmentMaterialService;

    private DepartmentMaterialSaveReqDTO buildSaveReq() {
        DepartmentMaterialSaveReqDTO dto = new DepartmentMaterialSaveReqDTO();
        dto.setId(100L);
        dto.setDeptId(200L);
        dto.setInfomationId(300L);
        dto.setClassesId(400L);
        dto.setDictionaryDataValue("TYPE");
        dto.setStatus("ENABLE");
        dto.setRemark("备注");
        return dto;
    }

    private DepartmentMaterialRespVO buildRespVO() {
        DepartmentMaterialRespVO respVO = new DepartmentMaterialRespVO();
        respVO.setId(100L);
        respVO.setDeptId(200L);
        respVO.setInfomationId(300L);
        respVO.setClassesId(400L);
        respVO.setDictionaryDataValue("TYPE");
        respVO.setRemark("备注");
        respVO.setStatus("ENABLE");
        respVO.setMaterialName("原材料");
        respVO.setCreateTime(LocalDateTime.now());
        return respVO;
    }

    @Test
    void createDepartmentMaterial_shouldForwardToServiceAndReturnConvertedDto() {
        DepartmentMaterialSaveReqDTO reqDTO = buildSaveReq();
        DepartmentMaterialRespVO serviceResp = buildRespVO();
        when(departmentMaterialService.createDepartmentMaterial(any(DepartmentMaterialSaveReqVO.class)))
                .thenReturn(serviceResp);

        CommonResult<DepartmentMaterialRespDTO> result = api.createDepartmentMaterial(reqDTO);

        assertThat(result.isSuccess()).isTrue();
        DepartmentMaterialRespDTO data = result.getData();
        assertThat(data.getId()).isEqualTo(serviceResp.getId());
        assertThat(data.getMaterialName()).isEqualTo("原材料");

        ArgumentCaptor<DepartmentMaterialSaveReqVO> captor = ArgumentCaptor.forClass(DepartmentMaterialSaveReqVO.class);
        verify(departmentMaterialService).createDepartmentMaterial(captor.capture());
        DepartmentMaterialSaveReqVO passed = captor.getValue();
        assertThat(passed.getDeptId()).isEqualTo(reqDTO.getDeptId());
        assertThat(passed.getInfomationId()).isEqualTo(reqDTO.getInfomationId());
        assertThat(passed.getDictionaryDataValue()).isEqualTo(reqDTO.getDictionaryDataValue());
    }

    @Test
    void updateDepartmentMaterial_shouldInvokeService() {
        DepartmentMaterialSaveReqDTO reqDTO = buildSaveReq();

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

        assertThat(result.isSuccess()).isTrue();
        assertThat(result.getData()).isTrue();
        ArgumentCaptor<DepartmentMaterialSaveReqVO> captor = ArgumentCaptor.forClass(DepartmentMaterialSaveReqVO.class);
        verify(departmentMaterialService).updateDepartmentMaterial(captor.capture());
        assertThat(captor.getValue().getDeptId()).isEqualTo(reqDTO.getDeptId());
    }

    @Test
    void deleteDepartmentMaterial_shouldInvokeService() {
        CommonResult<Boolean> result = api.deleteDepartmentMaterial(99L);

        assertThat(result.isSuccess()).isTrue();
        assertThat(result.getData()).isTrue();
        verify(departmentMaterialService).deleteDepartmentMaterial(99L);
    }

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

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

        assertThat(result.isSuccess()).isTrue();
        assertThat(result.getData()).isTrue();
        verify(departmentMaterialService).deleteDepartmentMaterialListByIds(ids);
    }

    @Test
    void getDepartmentMaterial_shouldConvertVoToDto() {
        DepartmentMaterialRespVO respVO = buildRespVO();
        when(departmentMaterialService.getDepartmentMaterial(11L)).thenReturn(respVO);

        CommonResult<DepartmentMaterialRespDTO> result = api.getDepartmentMaterial(11L);

        assertThat(result.isSuccess()).isTrue();
        assertThat(result.getData().getId()).isEqualTo(respVO.getId());
        assertThat(result.getData().getMaterialName()).isEqualTo(respVO.getMaterialName());
    }

    @Test
    void getDepartmentMaterialPage_shouldConvertPageResult() {
        DepartmentMaterialRespVO respVO = buildRespVO();
        PageResult<DepartmentMaterialRespVO> page = new PageResult<>(List.of(respVO), 1L);
    when(departmentMaterialService.getDepartmentMaterialPage(any(DepartmentMaterialPageReqVO.class)))
                .thenReturn(page);

        DepartmentMaterialPageReqDTO reqDTO = new DepartmentMaterialPageReqDTO();
        reqDTO.setDeptId(200L);

        CommonResult<PageResult<DepartmentMaterialRespDTO>> result = api.getDepartmentMaterialPage(reqDTO);

        assertThat(result.isSuccess()).isTrue();
        assertThat(result.getData().getList()).hasSize(1);
        assertThat(result.getData().getList().get(0).getMaterialName()).isEqualTo("原材料");
        assertThat(result.getData().getTotal()).isEqualTo(1L);
    }
}
