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

import com.zt.plat.framework.common.pojo.CommonResult;
import com.zt.plat.framework.common.pojo.PageResult;
import com.zt.plat.module.base.api.materialgradeext.dto.MaterialGradeExtPageReqDTO;
import com.zt.plat.module.base.api.materialgradeext.dto.MaterialGradeExtRespDTO;
import com.zt.plat.module.base.api.materialgradeext.dto.MaterialGradeExtSaveReqDTO;
import com.zt.plat.module.base.controller.admin.materialgradeext.vo.MaterialGradeExtPageReqVO;
import com.zt.plat.module.base.controller.admin.materialgradeext.vo.MaterialGradeExtRespVO;
import com.zt.plat.module.base.controller.admin.materialgradeext.vo.MaterialGradeExtSaveReqVO;
import com.zt.plat.module.base.service.materialgradeext.MaterialGradeExtService;
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 MaterialGradeExtApiImplTest {

    @InjectMocks
    private MaterialGradeExtApiImpl api;

    @Mock
    private MaterialGradeExtService materialGradeExtService;

    private MaterialGradeExtSaveReqDTO buildSaveReqDTO() {
        MaterialGradeExtSaveReqDTO dto = new MaterialGradeExtSaveReqDTO();
        dto.setId(1L);
        dto.setCompanyCode("C001");
        dto.setCompanyName("公司A");
        dto.setMaterialCode("M001");
        dto.setMaterialName("物料A");
        dto.setChineseBrand("ZH");
        dto.setEnglishBrand("EN");
        dto.setSpecificationModel("SPC");
        dto.setLineType("single");
        dto.setPackageDesc("箱装");
        return dto;
    }

    private MaterialGradeExtRespVO buildRespVO() {
        MaterialGradeExtRespVO respVO = new MaterialGradeExtRespVO();
        respVO.setId(11L);
        respVO.setCompanyCode("C001");
        respVO.setMaterialCode("M001");
        respVO.setCreateTime(LocalDateTime.now());
        return respVO;
    }

    @Test
    void create_shouldInvokeServiceAndReturnDto() {
        MaterialGradeExtSaveReqDTO reqDTO = buildSaveReqDTO();
        MaterialGradeExtRespVO serviceResp = buildRespVO();
        when(materialGradeExtService.create(any(MaterialGradeExtSaveReqVO.class))).thenReturn(serviceResp);

        CommonResult<MaterialGradeExtRespDTO> result = api.create(reqDTO);

        assertThat(result.isSuccess()).isTrue();
        assertThat(result.getData().getId()).isEqualTo(serviceResp.getId());
        ArgumentCaptor<MaterialGradeExtSaveReqVO> captor = ArgumentCaptor.forClass(MaterialGradeExtSaveReqVO.class);
        verify(materialGradeExtService).create(captor.capture());
        assertThat(captor.getValue().getCompanyCode()).isEqualTo("C001");
        assertThat(captor.getValue().getMaterialCode()).isEqualTo("M001");
    }

    @Test
    void update_shouldInvokeService() {
        MaterialGradeExtSaveReqDTO reqDTO = buildSaveReqDTO();

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

        assertThat(result.isSuccess()).isTrue();
        assertThat(result.getData()).isTrue();
        ArgumentCaptor<MaterialGradeExtSaveReqVO> captor = ArgumentCaptor.forClass(MaterialGradeExtSaveReqVO.class);
        verify(materialGradeExtService).update(captor.capture());
        assertThat(captor.getValue().getCompanyCode()).isEqualTo("C001");
    }

    @Test
    void delete_shouldInvokeService() {
        CommonResult<Boolean> result = api.delete(9L);

        assertThat(result.isSuccess()).isTrue();
        assertThat(result.getData()).isTrue();
        verify(materialGradeExtService).delete(9L);
    }

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

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

        assertThat(result.isSuccess()).isTrue();
        assertThat(result.getData()).isTrue();
        verify(materialGradeExtService).deleteByIds(ids);
    }

    @Test
    void get_shouldReturnConvertedDto() {
        MaterialGradeExtRespVO respVO = buildRespVO();
        when(materialGradeExtService.get(5L)).thenReturn(respVO);

        CommonResult<MaterialGradeExtRespDTO> result = api.get(5L);

        assertThat(result.isSuccess()).isTrue();
        assertThat(result.getData().getId()).isEqualTo(respVO.getId());
        assertThat(result.getData().getCompanyCode()).isEqualTo("C001");
    }

    @Test
    void getPage_shouldConvertPageResult() {
        MaterialGradeExtRespVO respVO = buildRespVO();
        PageResult<MaterialGradeExtRespVO> page = new PageResult<>(List.of(respVO), 1L);
        when(materialGradeExtService.getPage(any(MaterialGradeExtPageReqVO.class))).thenReturn(page);

        MaterialGradeExtPageReqDTO reqDTO = new MaterialGradeExtPageReqDTO();
        reqDTO.setCompanyCode("C001");

        CommonResult<PageResult<MaterialGradeExtRespDTO>> result = api.getPage(reqDTO);

        assertThat(result.isSuccess()).isTrue();
        assertThat(result.getData().getTotal()).isEqualTo(1L);
        assertThat(result.getData().getList()).hasSize(1);
        assertThat(result.getData().getList().get(0).getCompanyCode()).isEqualTo("C001");
    }
}