package com.sw.mes.fb.turnstore.controller;

import com.sw.mes.core.api.system.YbFeignClients;
import com.sw.mes.core.dto.TurnstoreTrayPostDto;
import com.sw.mes.core.entity.SearchFilter;
import com.sw.mes.core.response.ResponsePage;
import com.sw.mes.core.response.Result;
import com.sw.mes.core.response.ResultGenerator;
import com.sw.mes.core.utils.*;
import com.sw.mes.fb.turnstore.dto.RawMaterialCancelDto;
import com.sw.mes.fb.turnstore.dto.RawMaterialPostDto;
import com.sw.mes.fb.turnstore.dto.RawMaterialReceivingDto;
import com.sw.mes.fb.turnstore.entity.RawMaterialReceiving;
import com.sw.mes.fb.turnstore.service.RawMaterialReceivingService;
import io.swagger.annotations.*;
import lombok.extern.slf4j.Slf4j;
import org.modelmapper.ModelMapper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;

import javax.annotation.Resource;
import javax.servlet.ServletRequest;
import javax.validation.Valid;
import java.util.List;
import java.util.stream.Collectors;


/**
 * @Author
 * @Description：
 * @Date: Create in
 * @Modified By:
 */
@RestController
@RequestMapping("/RawMaterialReceiving")
@Slf4j
@Api(description = "原料接收接口")
public class RawMaterialReceivingController {
    @Autowired
    ModelMapper modelMapper;

    @Resource
    private YbFeignClients feignService;

    @Autowired
    private RawMaterialReceivingService rawMaterialReceivingService;

    @ApiOperation(value = "分页查询原料接收列表")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "rows", value = "行数", dataType = "integer", paramType = "query"),
            @ApiImplicitParam(name = "page", value = "页码", dataType = "integer", paramType = "query"),
            @ApiImplicitParam(name = "search_EQ_trayNo", value = "托号", dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "search_EQ_source", value = "来源", dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "search_EQ_state", value = "状态", dataType = "string", paramType = "query"),
    })
    @GetMapping("/listByPage")
    public Result<ResponsePage<RawMaterialReceivingDto>> listByPage(ServletRequest request, @ApiIgnore RequestPage requestPage) {
        SearchFilter searchFilter = new SearchFilter("user", SearchFilter.Operator.NOT, "自动");
        Specification<RawMaterialReceiving> specification = DynamicSpecifications.bySearchFilter(request, RawMaterialReceiving.class, searchFilter);
        Page<RawMaterialReceiving> page = rawMaterialReceivingService.findByExample(specification, PageUtil.createPageable(requestPage));
        List<RawMaterialReceivingDto> dtos = page.getContent().stream()
                .map(this::toLazyDto)
                .collect(Collectors.toList());
        ResponsePage responsePage = new ResponsePage(dtos, page.getTotalElements());
        return ResultGenerator.success(responsePage);
    }

    @ApiOperation(value = "获取所有原料接收")
    @GetMapping("/listAll")
    public Result<List<RawMaterialReceivingDto>> listAll(ServletRequest request) {
        Specification<RawMaterialReceiving> specification = DynamicSpecifications.bySearchFilter(request, RawMaterialReceiving.class);
        List<RawMaterialReceiving> rawMaterialReceivings = rawMaterialReceivingService.findByExampleSort(specification, null);
        List<RawMaterialReceivingDto> rawMaterialReceivingDtos = rawMaterialReceivings.stream()
                .map(this::toLazyDto)
                .collect(Collectors.toList());
        return ResultGenerator.success(rawMaterialReceivingDtos);
    }

    @ApiOperation(value = "原料接收详细信息")
    @GetMapping("/{id}")
    public Result<RawMaterialReceivingDto> get(@PathVariable @ApiParam(value = "原料接收id") Integer id) {
        RawMaterialReceiving rawMaterialReceiving = rawMaterialReceivingService.get(id);
        if (null == rawMaterialReceiving) {
            return ResultGenerator.fail("该原料接收不存在");
        }
        return ResultGenerator.success(toEagerDto(rawMaterialReceiving));
    }

    @ApiOperation(value = "创建原料接收")
    @PostMapping("/create")
    public Result create(@RequestBody @Valid @ApiParam(value = "原料接收对象") RawMaterialReceivingDto rawMaterialReceivingDto, BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            return ResultGenerator.fail(bindingResult.getFieldError().getDefaultMessage());
        }
        RawMaterialReceiving rawMaterialReceiving = fromDto(rawMaterialReceivingDto);
        rawMaterialReceivingService.saveOrUpdate(rawMaterialReceiving);
        return ResultGenerator.success();
    }

    @ApiOperation(value = "原料接收接口")
    @PostMapping("/receive")
    public Result receive(@RequestBody TurnstoreTrayPostDto trayPostDto) {
        RawMaterialReceiving rawMaterialReceiving = rawMaterialReceivingService.findByTrayNoAndState(trayPostDto.getTrayDto().getTrayNo(), 0);
        if (null != rawMaterialReceiving) {
            return ResultGenerator.fail("已存在未确认状态的托号,不能重复入库");
        }
        ThreadManager.getThreadPollProxy().execute(() -> {
            //异步执行原料接收
            rawMaterialReceivingService.saveRawMaterial(trayPostDto);
        });
        return ResultGenerator.success();
    }

    @ApiOperation(value = "取消")
    @PostMapping("/cancelState")
    public Result<String> cancelState(@RequestBody RawMaterialCancelDto materialCancelDto) {
        //取消原料接收
        String trayNo = materialCancelDto.getTrayNo();
        String user = materialCancelDto.getUser();
        return rawMaterialReceivingService.cancelState(trayNo, user);
    }

    @ApiOperation(value = "更新原料接收")
    @PostMapping("/update")
    public Result update(@RequestBody @Valid @ApiParam(value = "原料接收") RawMaterialPostDto dto, BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            return ResultGenerator.fail(bindingResult.getFieldError().getDefaultMessage());
        }
        if (dto.getReceivingDto().getId() == null) {
            return ResultGenerator.fail("id不能为空");
        }
        RawMaterialReceiving entity = rawMaterialReceivingService.get(dto.getReceivingDto().getId());
        if (entity == null || 0 != entity.getState()) {
            return ResultGenerator.fail("该托数据不存在或者已被处理,请确认后再操作;");
        }
        if (null == dto.getReceivingDetailList() || dto.getReceivingDetailList().size() == 0) {
            return ResultGenerator.fail("接收详情不能为空");
        }
        try {
            //更新原料接收主表
            RawMaterialReceiving entityFromFto = fromDto(dto.getReceivingDto());
            BeanUtils.copyProperties(entityFromFto, entity, BeanUtil.getIgnoreProperties(entityFromFto, null, null));
            //更新明细表
            rawMaterialReceivingService.saveDetailDto(dto.getReceivingDetailList(), entity.getHasGone());
            rawMaterialReceivingService.saveOrUpdate(entity);
            if ("圆棒检验".equals(entity.getSource())) {
                //封装传输DTO
                TurnstoreTrayPostDto trayPostDto = rawMaterialReceivingService.initTurnstoreTrayPostDto(entity, dto.getReceivingDetailList());
                //返回状态
                feignService.updateState(trayPostDto);
            } else {
                //更新方棒组托状态
                rawMaterialReceivingService.updateFbTrayState(entity, dto.getReceivingDetailList());
            }
            return ResultGenerator.success();
        } catch (Exception e) {
            return ResultGenerator.fail(e.getMessage());
        }
    }

    @ApiOperation(value = "删除原料接收")
    @PostMapping("/delete")
    public Result remove(@ApiParam(value = "id集合,逗号分隔,如2,4", type = "query") @RequestParam Integer[] ids) {
        for (Integer id : ids) {
            rawMaterialReceivingService.delete(id);
        }
        return ResultGenerator.success();
    }

    public RawMaterialReceivingDto toLazyDto(RawMaterialReceiving entity) {
        return modelMapper.map(entity, RawMaterialReceivingDto.class);
    }

    public RawMaterialReceivingDto toEagerDto(RawMaterialReceiving entity) {
        return modelMapper.map(entity, RawMaterialReceivingDto.class);
    }

    public RawMaterialReceiving fromDto(RawMaterialReceivingDto dto) {
        return modelMapper.map(dto, RawMaterialReceiving.class);
    }
}
