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

import com.sw.mes.base.factory.inspect.dto.BarSupportRuleDto;
import com.sw.mes.base.factory.inspect.dto.SupportRuleDto;
import com.sw.mes.base.factory.inspect.entity.BarSupportRule;
import com.sw.mes.base.factory.inspect.service.BarSupportRuleService;
import com.sw.mes.base.workinprocess.entity.PlanProcessingOrder;
import com.sw.mes.base.workinprocess.service.PlanProcessingOrderService;
import com.sw.mes.base.workinprocess.service.WipStorageService;
import com.sw.mes.core.api.system.FbFeignClients;
import com.sw.mes.core.dto.RawMaterialCancelDto;
import com.sw.mes.core.dto.TrayPostDto;
import com.sw.mes.core.dto.TurnstoreTrayDto;
import com.sw.mes.core.entity.SearchFilter;
import com.sw.mes.core.entity.TurnstoreTrayItem;
import com.sw.mes.core.enums.EnumValuesFactory;
import com.sw.mes.core.exception.BusinessException;
import com.sw.mes.core.response.ResponsePage;
import com.sw.mes.core.response.Result;
import com.sw.mes.core.response.ResultCode;
import com.sw.mes.core.response.ResultGenerator;
import com.sw.mes.core.utils.DynamicSpecifications;
import com.sw.mes.core.utils.PageUtil;
import com.sw.mes.core.utils.RequestPage;
import com.sw.mes.inspect.entity.YbInspectData;
import com.sw.mes.inspect.service.YbInspectDataService;
import com.sw.mes.yb.turnstore.dto.TurnstoreTrayItemDto;
import com.sw.mes.yb.turnstore.dto.TurnstoreTrayPostDto;
import com.sw.mes.yb.turnstore.dto.TurnstoreTrayRuleDto;
import com.sw.mes.yb.turnstore.dto.WmsToYbReceiveDto;
import com.sw.mes.yb.turnstore.entity.ProductionBindingTray;
import com.sw.mes.yb.turnstore.entity.TurnstoreTray;
import com.sw.mes.yb.turnstore.service.ProductionBindingTrayService;
import com.sw.mes.yb.turnstore.service.TurnstoreTrayItemService;
import com.sw.mes.yb.turnstore.service.TurnstoreTrayService;
import io.swagger.annotations.*;
import lombok.extern.slf4j.Slf4j;
import org.modelmapper.ModelMapper;
import org.modelmapper.convention.MatchingStrategies;
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.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;


/**
 * @Author
 * @Description：
 * @Date: Create in
 * @Modified By:
 */
@RestController
@RequestMapping("/turnstoreTray")
@Slf4j
@Api(description = "组拖主表接口")
public class TurnstoreTrayController {
    @Autowired
    ModelMapper modelMapper;

    @Autowired
    private TurnstoreTrayService turnstoreTrayService;

    @Autowired
    private TurnstoreTrayItemService turnstoreTrayItemService;

    @Resource
    private FbFeignClients fbFeignClients;

    @Autowired
    private YbInspectDataService inspectService;

    @Autowired
    private BarSupportRuleService barSupportRuleService;

    @Autowired
    private WipStorageService wipStorageService;

    @Autowired
    private PlanProcessingOrderService planProcessingOrderService;

    @Autowired
    private ProductionBindingTrayService productionBindingTrayService;

    @ApiOperation(value = "分页查询组拖主表列表")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "rows", value = "行数", dataType = "integer", paramType = "query"),
            @ApiImplicitParam(name = "page", value = "页码", dataType = "integer", paramType = "query"),
    })
    @GetMapping("/listByPage")
    public Result<ResponsePage<TurnstoreTrayDto>> listByPage(ServletRequest request, @ApiIgnore RequestPage requestPage) {
        SearchFilter searchFilter = new SearchFilter("user", SearchFilter.Operator.NOT, "自动");

        Specification<TurnstoreTray> specification = DynamicSpecifications.bySearchFilter(request, TurnstoreTray.class, searchFilter);
        Page<TurnstoreTray> page = turnstoreTrayService.findByExample(specification, PageUtil.createPageable(requestPage));
        List<TurnstoreTrayDto> dtos = page.getContent().stream()
                .map(this::toLazyDto)
                .collect(Collectors.toList());
        ResponsePage responsePage = new ResponsePage(dtos, page.getTotalElements());
        return ResultGenerator.success(responsePage);
    }

    @ApiOperation(value = "根据托号获取所有组拖主表")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "search_EQ_trayNo", value = "托号", dataType = "string", paramType = "query"),
    })
    @GetMapping("/findByTrayNo")
    public Result<TurnstoreTrayRuleDto> findByTrayNo(ServletRequest request) {
        Specification<TurnstoreTray> specification = DynamicSpecifications.bySearchFilter(request, TurnstoreTray.class);
        List<TurnstoreTray> turnstoreTrays = turnstoreTrayService.findByExampleSort(specification, null);
        TurnstoreTrayRuleDto trayRuleDto = new TurnstoreTrayRuleDto();
        if (turnstoreTrays.size() > 0) {
            trayRuleDto.setTurnstoreTray(turnstoreTrays.get(0));
        }
        return ResultGenerator.success(trayRuleDto);
    }

    @ApiOperation(value = "组拖主表详细信息")
    @GetMapping("/{id}")
    public Result<TurnstoreTrayPostDto> get(@PathVariable @ApiParam(value = "组拖主表id") Integer id) {
        TurnstoreTray turnstoreTray = turnstoreTrayService.get(id);
        if (null == turnstoreTray) {
            return ResultGenerator.fail("该组拖主表不存在");
        }
        TurnstoreTrayPostDto entity = fromDto(turnstoreTray);
        List<TurnstoreTrayItem> turnstoreTrayItemList = turnstoreTrayItemService.findItemsByTrayId(id);
        entity.setItems(toDto(turnstoreTrayItemList));
        // 设置导电型号 判断组托集合中第一个就好
        entity.setConductionType(turnstoreTrayItemList.get(0).getConductiveType());
        // 设置单晶类型
        entity.setType(turnstoreTrayItemList.get(0).getSectionType());
        //查询组托规则
        if (null != turnstoreTray.getRuleName()) {
            BarSupportRule ruleByGroupName = barSupportRuleService.findRuleByGroupName(turnstoreTray.getRuleName());
            entity.setRuleDto(ruleByGroupName);
        }
        //更新打印时间
        turnstoreTray.setPrintTime(new Date());
        turnstoreTrayService.saveOrUpdate(turnstoreTray);
        return ResultGenerator.success(entity);
    }

    @ApiOperation(value = "导出到WMS")
    @GetMapping("/toWms/{id}")
    public Result toWms(@PathVariable @ApiParam(value = "组拖主表id") Integer id) {
        List<TurnstoreTrayItem> turnstoreTrayItemList = turnstoreTrayItemService.getItemsByTrayId(id);
        List<String> sectionItems = turnstoreTrayItemList.stream().map(TurnstoreTrayItem::getSectionNo).collect(Collectors.toList());
        if (sectionItems != null && sectionItems.size() > 0) {
            turnstoreTrayService.reGetSapOrderNo(sectionItems);
        }
        return ResultGenerator.success();
    }

    @ApiOperation(value = "导出Excel")
    @GetMapping("/exportExcel")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "search_EQ_trayNo", value = "托号", dataType = "String", paramType = "query"),
    })
    public void exportExcel(HttpServletRequest request, HttpServletResponse resp) {
        turnstoreTrayItemService.exportExcel(request, resp);
    }

    @ApiOperation(value = "创建组拖主表")
    @PostMapping("/create")
    public Result create(@RequestBody @Valid @ApiParam(value = "组拖主表对象") TurnstoreTrayPostDto turnstoreTrayPostDto, BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            return ResultGenerator.fail(bindingResult.getFieldError().getDefaultMessage());
        }
        if (null == turnstoreTrayPostDto) {
            return ResultGenerator.fail("组拖申请错误");
        }
        if (null == turnstoreTrayPostDto.getItems() || turnstoreTrayPostDto.getItems().size() == 0) {
            return ResultGenerator.fail("组拖明细错误");
        }
        TurnstoreTray turnstoreTray = fromDto(turnstoreTrayPostDto);
        List<TurnstoreTrayItem> items = fromDto(turnstoreTrayPostDto.getItems());
        BarSupportRule ruleDto = turnstoreTrayPostDto.getRuleDto();
        String trayNo1 = turnstoreTrayPostDto.getTrayNo1();
        String trayNo2 = turnstoreTrayPostDto.getTrayNo2();
        turnstoreTrayService.createTray(ruleDto, turnstoreTray, items, trayNo1, trayNo2);
        return ResultGenerator.success();
    }

    @ApiOperation(value = "圆棒WMS接收接口")
    @PostMapping("/ybWmsReceive")
    public Result ybWmsReceive(@RequestBody List<WmsToYbReceiveDto> receiveDto) {
        //查询组托信息
        for (WmsToYbReceiveDto wmsToYbReceiveDto : receiveDto) {
            TurnstoreTray turnstoreTray = turnstoreTrayService.findByTrayNo(wmsToYbReceiveDto.getBoxCode());
            if (null == turnstoreTray) {
                return ResultGenerator.fail("该:" + wmsToYbReceiveDto.getBoxCode() + " 托号信息不存在");
            }
            //拒收时增加组托状态判断---只有待确认的可以拒收
            if ((1 == wmsToYbReceiveDto.getType() || 2 == wmsToYbReceiveDto.getType()) && turnstoreTray.getState() != 0) {
                return ResultGenerator.fail("该:" + wmsToYbReceiveDto.getBoxCode() + " 托号不是待确认状态,不能进行接收拒收操作");
            }
            //冲销时增加组托状态判断---只有已确认的可以冲销
            if (3 == wmsToYbReceiveDto.getType() && turnstoreTray.getState() != 1) {
                return ResultGenerator.fail("该:" + wmsToYbReceiveDto.getBoxCode() + " 托号不是已确认状态,不能冲销");
            }
            //查询组托明细
            List<TurnstoreTrayItem> trayItemList = turnstoreTrayItemService.getItemsByTrayNo(wmsToYbReceiveDto.getBoxCode());
            if (null == trayItemList || trayItemList.isEmpty()) {
                return ResultGenerator.fail("该:" + wmsToYbReceiveDto.getBoxCode() + " 组拖明细错误");
            }

            //构建FbTurnstoreTray更新信息
            buildEntityProp(wmsToYbReceiveDto, turnstoreTray);
            //更新组托表头信息
            turnstoreTrayService.updateTurnstoreTrayStateById(wmsToYbReceiveDto, turnstoreTray);
            //更新组托明细信息
            turnstoreTrayService.updateTrayItemState(wmsToYbReceiveDto, turnstoreTray, trayItemList);
        }
        return ResultGenerator.success();
    }

    private void buildEntityProp(WmsToYbReceiveDto wmsToYbReceiveDto, TurnstoreTray turnstoreTray) {
        //更新信息
        turnstoreTray.setConfirmUser(wmsToYbReceiveDto.getRejectionUser());
        turnstoreTray.setConfirmTime(wmsToYbReceiveDto.getRejectionDate());
        //根据状态进行操作
        if (1 == wmsToYbReceiveDto.getType()) {
            //确认接收
            turnstoreTray.setState(1);
        } else if (2 == wmsToYbReceiveDto.getType()) {
            //拒收
            turnstoreTray.setState(3);
            turnstoreTray.setRemark(wmsToYbReceiveDto.getRejectionReason());
        } else {
            //冲销==取消
            turnstoreTray.setState(4);
            if (null != wmsToYbReceiveDto.getRejectionReason()) {
                turnstoreTray.setRemark(wmsToYbReceiveDto.getRejectionReason());
            } else {
                turnstoreTray.setRemark("冲销");
            }

    }
    }

    @ApiOperation(value = "更新组拖主表")
    @PostMapping("/update")
    public Result update(@RequestBody @Valid @ApiParam(value = "组拖主表") TurnstoreTrayPostDto turnstoreTrayPostDto, BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            return ResultGenerator.fail(bindingResult.getFieldError().getDefaultMessage());
        }
        if (turnstoreTrayPostDto.getId() == null) {
            return ResultGenerator.fail("id不能为空");
        }
        TurnstoreTray entity = turnstoreTrayService.get(turnstoreTrayPostDto.getId());
        if (entity == null) {
            return ResultGenerator.fail("原信息不存在");
        }
        //取消
        if (null != turnstoreTrayPostDto.getState() && 4 == turnstoreTrayPostDto.getState()) {
            if (turnstoreTrayPostDto.getHasGone().contains("WMS")) {
                return ResultGenerator.fail("去向为WMS的,暂不能进行取消操作,请联系管理员处理");
            }
            if (0 != entity.getState()) {
                return ResultGenerator.fail("当前不处于待确认状态,不能进行取消操作,请刷新后再试");
            }
            //更新主表
            TurnstoreTray turnstoreTray = fromDto(turnstoreTrayPostDto);
            //通知下游取消
            RawMaterialCancelDto materialCancelDto = new RawMaterialCancelDto();
            materialCancelDto.setTrayNo(turnstoreTray.getTrayNo());
            materialCancelDto.setUser(turnstoreTray.getUpdateUser());
            //发送取消请求
            Result<String> receive = fbFeignClients.cancelState(materialCancelDto);
            if (receive.getCode() != ResultCode.SUCCESS.getCode()) {
                return ResultGenerator.fail(receive.getMessage());
            }
            turnstoreTray.setId(entity.getId());
            turnstoreTray.setOperationTime(new Date());
            //更新详情
            List<TurnstoreTrayItem> trayItemList = turnstoreTrayItemService.getItemsByTrayId(turnstoreTray.getId());
            for (TurnstoreTrayItem trayItem : trayItemList) {
                //解锁组托状态
                PlanProcessingOrder planProcessingOrder = planProcessingOrderService.findByCode(trayItem.getSectionNo());
                if (null == planProcessingOrder) {
                    throw new BusinessException(trayItem.getSectionNo() + "工单号不存在");
                }
                planProcessingOrder.setStatus(EnumValuesFactory.PlanProcessingOrderStatus.加工中.getKey());
                planProcessingOrderService.saveOrUpdate(planProcessingOrder);

                trayItem.setState(turnstoreTray.getState());
                trayItem.setOperationTime(new Date());
                //退站操作
                wipStorageService.exitStation(trayItem.getSectionNo());
                turnstoreTrayItemService.saveOrUpdate(trayItem);
            }
            //更新主表
            turnstoreTrayService.saveOrUpdate(turnstoreTray);
        } else {
            if (9 != entity.getState()) {
                return ResultGenerator.fail("当前不处于待出库状态,不能进行编辑操作,请刷新后再试");
            }
            if (turnstoreTrayPostDto.getItems() == null || turnstoreTrayPostDto.getItems().isEmpty()) {
                return ResultGenerator.fail("组拖明细错误");
            }
            try {
                TurnstoreTray turnstoreTray = fromDto(turnstoreTrayPostDto);
                turnstoreTray.setId(entity.getId());
                List<TurnstoreTrayItem> items = fromDto(turnstoreTrayPostDto.getItems());
                turnstoreTrayService.updateTray(turnstoreTray, items);
            } catch (Exception e) {
                return ResultGenerator.fail(e.getMessage());
            }
        }
        return ResultGenerator.success();
    }

    @ApiOperation(value = "更新组拖状态")
    @PostMapping("/updateState")
    public Result updateState(@RequestBody TrayPostDto trayPostDto) {
        TurnstoreTrayDto trayDto = trayPostDto.getTrayDto();
        TurnstoreTray entity = turnstoreTrayService.findByTrayNo(trayDto.getTrayNo());
        if (entity == null) {
            return ResultGenerator.fail("原信息不存在");
        }
       return turnstoreTrayService.updateState(entity,trayPostDto);
    }

    @ApiOperation(value = "发起入库")
    @PostMapping("/initiateReceipt")
    public Result initiateReceipt(@RequestBody @Valid @ApiParam(value = "组拖主表对象") TurnstoreTrayDto turnstoreTrayDto) {
        //校验状态
        TurnstoreTray entity = turnstoreTrayService.get(turnstoreTrayDto.getId());
        if (null == entity) {
            return ResultGenerator.fail("原信息不存在");
        }
        if (9 != entity.getState()) {
            return ResultGenerator.fail("当前不处于待出库状态,不能进行发起入库,请刷新后再试");
        }
        List<TurnstoreTrayItem> turnstoreTrayItemList = turnstoreTrayItemService.getItemsByTrayId(turnstoreTrayDto.getId());
        //获取详情列表
        if (null == turnstoreTrayItemList || turnstoreTrayItemList.isEmpty()) {
            return ResultGenerator.fail("组托详情不能为空");
        }
        //发起入库
        return turnstoreTrayService.initiateReceipt(turnstoreTrayDto, turnstoreTrayItemList, false);
    }

    @ApiOperation(value = "删除组拖主表")
    @PostMapping("/delete")
    public Result remove(@ApiParam(value = "id集合,逗号分隔,如2,4", type = "query") @RequestParam Integer[] ids) {
        for (Integer id : ids) {
            //校验状态
            TurnstoreTray turnstoreTray = turnstoreTrayService.get(id);
            if (null == turnstoreTray) {
                return ResultGenerator.fail("原信息不存在");
            }
            if (9 != turnstoreTray.getState()) {
                return ResultGenerator.fail("当前不处于待出库状态,不能进行删除,请刷新后再试");
            }
            turnstoreTrayItemService.deleteByTrayId(id);
            turnstoreTrayService.delete(id);
        }
        return ResultGenerator.success();
    }

    @ApiOperation(value = "校验晶段信息是否符合规则")
    @PostMapping("/validateRule")
    public Result validateRule(@RequestBody @Valid @ApiParam(value = "圆棒组拖规则") SupportRuleDto ruleDto) {
        //查询晶段信息
        YbInspectData inspectData = inspectService.findBySectionNo(ruleDto.getSectionNo());
        if (null == inspectData || null == inspectData.getProductLevel()) {
            return ResultGenerator.fail("当前晶段信息不存在或晶段暂未评级");
        }
        //反切单晶卡控
        if (null != inspectData.getIsCutBack() && 1 == inspectData.getIsCutBack()) {
            return ResultGenerator.fail("该单晶为反切单晶，不允许组托");
        }
        //校验检验数据是否完整
        //Result result = turnstoreTrayService.valudate(inspectData);
        //if (result.getCode() != ResultCode.SUCCESS.getCode()) {
        //    return ResultGenerator.fail(result.getMessage());
        //}
        //校验是否符合组托规则
        if ("综计WMS".equals(ruleDto.getHasGone())) {
            String message = turnstoreTrayService.validateRules(ruleDto, inspectData);
            if (!"符合".equals(message)) {
                return ResultGenerator.fail(message);
            }
        }
        //判断单晶是否在托盘上
        ProductionBindingTray byCrystalNo = productionBindingTrayService.getByCrystalNo(ruleDto.getSectionNo());
        if (null != byCrystalNo) {
            return ResultGenerator.fail("该晶棒还处于托盘绑定状态,请先解绑");
        }
        //查询是否处于当前站点
        wipStorageService.selectWipStorage(ruleDto.getSectionNo(), EnumValuesFactory.WipStorageCode.圆棒检验.getKey(), true);
        //查询是否存在
        List<TurnstoreTrayItem> trayItemList = turnstoreTrayItemService.findBySectionNoValidate(inspectData.getSectionNo());
        if (null != trayItemList && !trayItemList.isEmpty()) {
            for (TurnstoreTrayItem turnstoreTrayItem : trayItemList) {
                if (9 == turnstoreTrayItem.getState()) {
                    return ResultGenerator.fail("该晶段已进行组托，不能重复组托,所在托号为: " + turnstoreTrayItem.getTrayNo());
                } else if ("退料".equals(turnstoreTrayItem.getHasGone()) && 1 == turnstoreTrayItem.getState()) {
                    return ResultGenerator.fail("该晶段已发起退料且接收，不能重复组托,所在托号为: " + turnstoreTrayItem.getTrayNo());
                }
            }
        }
        //组装组托详情
        List<TurnstoreTrayItem> turnstoreTrayItemList = turnstoreTrayService.groupItemList(inspectData);

        return ResultGenerator.success(turnstoreTrayItemList);
    }

    public TurnstoreTrayDto toLazyDto(TurnstoreTray entity) {
        return modelMapper.map(entity, TurnstoreTrayDto.class);
    }

    public TurnstoreTrayDto toEagerDto(TurnstoreTray entity) {
        return modelMapper.map(entity, TurnstoreTrayDto.class);
    }

    public TurnstoreTray fromDto(TurnstoreTrayDto dto) {
        modelMapper.getConfiguration().setFullTypeMatchingRequired(true);
        modelMapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT);
        return modelMapper.map(dto, TurnstoreTray.class);
    }

    public TurnstoreTray fromDto(TurnstoreTrayPostDto dto) {
        modelMapper.getConfiguration().setFullTypeMatchingRequired(true);
        modelMapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT);
        return modelMapper.map(dto, TurnstoreTray.class);
    }

    public TurnstoreTrayPostDto fromDto(TurnstoreTray dto) {
        modelMapper.getConfiguration().setFullTypeMatchingRequired(true);
        modelMapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT);
        return modelMapper.map(dto, TurnstoreTrayPostDto.class);
    }

    public List<TurnstoreTrayItem> fromDto(List<TurnstoreTrayItemDto> dto) {
        modelMapper.getConfiguration().setFullTypeMatchingRequired(true);
        modelMapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT);
        return dto.stream().map(turnstoreTrayItem -> modelMapper.map(turnstoreTrayItem, TurnstoreTrayItem.class)).collect(Collectors.toList());
    }

    public List<TurnstoreTrayItemDto> toDto(List<TurnstoreTrayItem> dto) {
        modelMapper.getConfiguration().setFullTypeMatchingRequired(true);
        modelMapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT);
        return dto.stream().map(turnstoreTrayItemDto -> modelMapper.map(turnstoreTrayItemDto, TurnstoreTrayItemDto.class)).collect(Collectors.toList());
    }

    public BarSupportRuleDto toLazyDto(BarSupportRule entity) {
        return modelMapper.map(entity, BarSupportRuleDto.class);
    }
}
