package com.sw.mes.yb.mcs.service.impl;

import java.math.BigDecimal;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.sw.mes.base.global.GlobalSwitch;
import com.sw.mes.base.global.GlobalSwitchNamespace;
import com.sw.mes.base.system.entity.SysLog;
import com.sw.mes.core.api.system.StoreFeignClients;
import com.sw.mes.core.dto.YbInspectDataToMcsDto;
import com.sw.mes.core.utils.BeanUtil;
import com.sw.mes.core.utils.IpUtils;
import com.sw.mes.core.utils.NumberUtil;
import com.sw.mes.crucible.entity.CrucibleFixedCasting;
import com.sw.mes.crucible.service.CrucibleFixedCastingService;
import com.sw.mes.enumvalue.EnumValuesAgv;
import com.sw.mes.inspect.dao.YbInspectDataDao;
import com.sw.mes.inspect.entity.YbInspectData;
import com.sw.mes.mmcs.dto.CancelMoDistributionDto;
import com.sw.mes.mmcs.dto.IssueMoDto;
import com.sw.mes.mmcs.dto.McsReturnResult;
import com.sw.mes.production.dto.FormulaMaterialClassDetailDto;
import com.sw.mes.production.dto.FormulaSchemeDto;
import com.sw.mes.production.entity.FormulaMaterialClassDetail;
import com.sw.mes.production.entity.FormulaScheme;
import com.sw.mes.production.entity.FormulaWeightScheme;
import com.sw.mes.production.service.FormulaSchemeDetailService;
import com.sw.mes.production.service.FormulaSchemeService;
import com.sw.mes.production.service.FormulaWeightSchemeService;
import com.sw.mes.utils.MMCSHttpUtil;
import com.sw.mes.yb.agv.dto.AgvCallDto;
import com.sw.mes.yb.agv.service.AgvDispatchService;
import com.sw.mes.yb.fls.dto.RecycledMaterialToAGVDto;
import com.sw.mes.yb.fls.dto.RecycledMaterialToAGVDtos;
import com.sw.mes.yb.fls.entity.RecycledWaitRecord;
import com.sw.mes.yb.mcs.dto.AgvTaskDto;
import com.sw.mes.yb.mcs.dto.SybdCallDto;
import com.sw.mes.yb.mcs.dto.fillingMaterial.*;
import com.sw.mes.yb.mcs.dto.fillingMaterial.MoTrayBindingToMcs.BindingCassetteToMcsDto;
import com.sw.mes.yb.mcs.dto.fillingMaterial.MoTrayBindingToMcs.MaterialPropertyDto;
import com.sw.mes.yb.mcs.dto.fillingMaterial.MoTrayBindingToMcs.MoTrayBindingToMcsDto;
import com.sw.mes.yb.mcs.dto.fillingMaterial.MoWarehousingToMcs.MaterialDetailDto;
import com.sw.mes.yb.mcs.dto.fillingMaterial.MoWarehousingToMcs.MoWarehousingBindingToMcsDto;
import com.sw.mes.yb.mcs.entity.SegmentBindInfo;
import com.sw.mes.yb.mcs.service.SegmentBindInfoFbService;
import com.sw.mes.yb.mcs.service.SegmentBindInfoService;
import com.sw.mes.yb.pad.service.ProductionPaintingLineDetailService;
import com.sw.mes.yb.pad.service.RecycledWaitRecordService;
import com.sw.mes.yb.plan.entity.PlanWaterLineManageRecord;
import com.sw.mes.yb.plan.service.PlanWaterLineManageService;
import com.sw.mes.yb.production.dao.LongCrystalDao;
import com.sw.mes.yb.production.dto.ProductionCircleWeightDtoVo;
import com.sw.mes.yb.production.entity.*;
import com.sw.mes.yb.production.entity.AgainTaskPrepare.AgainTaskPrepare;
import com.sw.mes.yb.production.service.AgainTaskDetailService;
import com.sw.mes.yb.production.service.ProductionFurnaceMaterialSplitService;
import com.sw.mes.yb.turnstore.dao.ProductionBindingTrayDao;
import com.sw.mes.yb.turnstore.dao.ProductionBindingTrayLogDao;
import com.sw.mes.yb.turnstore.dto.MaterialTrayBindingDto;
import com.sw.mes.yb.turnstore.entity.MaterialTrayBinding;
import com.sw.mes.yb.turnstore.entity.MaterialWarehousingBinding;
import com.sw.mes.yb.turnstore.entity.ProductionBindingTray;
import com.sw.mes.yb.turnstore.entity.ProductionBindingTrayLog;
import com.sw.mes.yb.turnstore.service.MaterialTrayBindingService;
import com.sw.mes.yb.turnstore.service.MaterialWarehousingBindingService;
import com.sw.mes.yb.turnstore.service.ProductionBindingTrayService;
import org.apache.commons.lang3.StringUtils;
import org.modelmapper.ModelMapper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSONObject;
import com.sw.mes.base.factory.init.dto.SortingConfigDto;
import com.sw.mes.base.factory.init.dto.WarehouseDto;
import com.sw.mes.base.system.entity.DictionaryItem;
import com.sw.mes.base.system.service.DictionaryItemService;
import com.sw.mes.base.workinprocess.dto.CurrentWipStorageStatusDto;
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.annotation.ServiceLogs;
import com.sw.mes.core.context.BaseContextHandler;
import com.sw.mes.core.dto.RankResultDto;
import com.sw.mes.core.enums.EnumValuesFactory;
import com.sw.mes.core.exception.BusinessException;
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.utils.RestUtils;
import com.sw.mes.yb.mcs.dto.BlankConfigDto;
import com.sw.mes.yb.mcs.dto.CrystalTrayBindInfoDto;
import com.sw.mes.yb.mcs.dto.CrystalTrayUnBindInfoDto;
import com.sw.mes.yb.mcs.dto.OrderConfigDto;
import com.sw.mes.yb.mcs.dto.PdaBingDto;
import com.sw.mes.yb.mcs.dto.SpellBindingDto;
import com.sw.mes.yb.mcs.service.YbMesToMcsService;
import com.sw.mes.yb.mcs.utils.RequestDto;
import com.sw.mes.yb.mcs.utils.RequestUtils;
import com.sw.mes.yb.mcs.utils.ResultDto;
import com.sw.mes.yb.pad.entity.SectionNoDetail;
import com.sw.mes.yb.pad.service.SectionNoDetailService;
import com.sw.mes.yb.plan.dto.PlanWaterLineManageToWmsDto;
import com.sw.mes.yb.turnstore.dto.ManualCallDto;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.util.Assert;

import static org.reflections.Reflections.log;

/**
 * @Author: GaoXinJian
 * @Date: 2022-01-12 13:55
 */
@Service
@Transactional
public class YbMesToMcsServiceImpl implements YbMesToMcsService {
    @Autowired
    ModelMapper modelMapper;

    @Autowired
    private RequestUtils requestUtilsMcs;

    @Autowired
    private DictionaryItemService dictionaryItemService;

    @Autowired
    private ProductionBindingTrayLogDao productionBindingTrayLogDao;

    @Autowired
    @Lazy
    private RecycledWaitRecordService recycledWaitRecordService;

    @Autowired
    private PlanProcessingOrderService planProcessingOrderService;

    @Autowired
    private SectionNoDetailService sectionNoDetailService;

    @Autowired
    private WipStorageService wipStorageService;

    @Autowired
    private SegmentBindInfoService segmentBindInfoService;

    @Autowired
    private SegmentBindInfoFbService segmentBindInfoFbService;

    @Autowired
    @Qualifier(value = "yBMesThreadPoolTaskExecutor")
    private ThreadPoolTaskExecutor ybMesThreadPoolExecutor;

    @Autowired
    private ProductionBindingTrayDao productionBindingTrayDao;

    @Autowired
    @Lazy
    private ProductionBindingTrayService productionBindingTrayService;

    @Autowired
    private LongCrystalDao longCrystalDao;

    @Autowired
    private YbInspectDataDao ybInspectDataDao;

//    @Autowired
//    private YbFeignClients ybFeignClients;

    @Autowired
    private PlanWaterLineManageService planWaterLineManageService;

    @Autowired
    private RestUtils restUtils;

    @Value("${spring.mcsServiceUrl}")
    private String mcsServiceUrl;

    @Autowired
    private ProductionPaintingLineDetailService productionPaintingLineDetailService;

    @Autowired
    private FormulaSchemeService formulaSchemeService;

    @Autowired
    private FormulaSchemeDetailService formulaSchemeDetailService;

    @Autowired
    private FormulaWeightSchemeService formulaWeightSchemeService;

    @Autowired
    private ProductionFurnaceMaterialSplitService productionFurnaceMaterialSplitService;

    @Autowired
    private AgainTaskDetailService againTaskDetailService;

    @Autowired
    private StoreFeignClients storeFeignClients;

    @Autowired
    private CrucibleFixedCastingService crucibleFixedCastingService;

    @Autowired
    private MaterialTrayBindingService materialTrayBindingService;
    @Autowired
    private MaterialWarehousingBindingService materialWarehousingBindingService;

    @Autowired
    AgvDispatchService agvDispatchService;
    /**
     * 人工单晶上线体
     */
    private final String pdaBing = "/auto/mesToMcsController/binding";
    /**
     * 晶裂免检
     */
    private final String exemption = "/auto/mesToMcsController/crackAvoidCheck";

    /**
     * 人工单晶解绑（用于人工绑定出错后解绑）
     */
    private final String unPdaBing = "/auto/mesToMcsController/unBinding";


    //http://10.141.0.130:8806/agv/mesToMcsController/recyclingInformationDispatch
    private final String recyclingInformationDispatchUrl = "agv/mesToMcsController/recyclingInformationDispatch";

    //http://10.141.0.130:8806/agv/taskAction/pullAgvTask
    private final String pullAgvTaskUrl = "agv/taskAction/pullAgvTask";



    private final String crystalTrayBindInfoUrl = "/MCS_SERVER_MES/mcs/mes/state/binding";
    private final String crystalTrayUnBindInfoUrl = "/MCS_SERVER_MES/mcs/mes/state/unBinding";
    private final String rankResultUrl = "/auto/mesToMcsController/rankResult";
    private final String orderConfigUrl = "/auto/mesToMcsController/rule/orderConfig";
    private final String planWaterLineUrl = "/MCS_SERVER_DATA/MK/WMS/MES/storageConfigure";
    private final String spellBindingUrl = "/MCS_SERVER_MES/mcs/mes/state/spellBinding";
    private final String blankConfigUrl = "/mcs/mes/rule/blankConfig";
    private final String addManualCall = "/MCS_SERVER_DATA/MK/WMS/MES/addManualCall";
    private final String updateWarehouse = "agv/mesToMcsController/updateWarehouse";
    private final String SYCBD_URL = "agv/mesToMcsController/updateVehicle";

    private final String formulaSchemeToMcsUrl = "/material/mesToMcsController/distribute/materialFormula";

    private final String issueMoToMcsUrl = "/material/mesToMcsController/produceTask\n";

    private final String cancelMoDistributionToMcsUrl = "/material/mesToMcsController/cancelProduceTask";

    private final String moTrayBindingGGToMcsUrl = "/material/mesToMcsController/trayBindingGG";

    private final String moTrayBindingToMcsUrl = "/material/mesToMcsController/trayBinding";

    private final String moWarehousingBindingToMcsUrl = "/forklift/warehouseController/updateWarehouse";


    @Override
    public ResultDto crystalTrayBindInfo(CrystalTrayBindInfoDto crystalTrayBindInfoDto) {
        //todo 规格转换
        List<DictionaryItem> toMCSProductSpec = dictionaryItemService.findByThemeValueAndEnable("ToMCSProductSpec", true);
        Map<String, DictionaryItem> specMap = toMCSProductSpec.stream().collect(Collectors.toMap(DictionaryItem::getName, Function.identity(), (t1, t2) -> t1));
        String productType = crystalTrayBindInfoDto.getProductType();
        if (specMap.containsKey(productType)){
            crystalTrayBindInfoDto.setProductType(specMap.get(productType).getValue());
        }else{
            crystalTrayBindInfoDto.setProductType("0");
        }
        System.out.println("调用接口："+crystalTrayBindInfoUrl +"入参="+JSONObject.toJSON(crystalTrayBindInfoDto));
        return requestUtilsMcs.postForMcs(new RequestDto(crystalTrayBindInfoUrl, crystalTrayBindInfoDto));
    }

    @Override
    public ResultDto recycledMaterialToMcs(RecycledMaterialToAGVDtos recycledMaterialToAGVDto) {
        return requestUtilsMcs.postForMcsNew(new RequestDto(recyclingInformationDispatchUrl, recycledMaterialToAGVDto));
    }

    @Override
    public ResultDto pullAgvTaskToMcs(AgvTaskDto agvTaskDto) {
        return requestUtilsMcs.postForMcsNew(new RequestDto(pullAgvTaskUrl, agvTaskDto));
    }

    @Override
    public Result recycledMaterialToMcsAndAGV(List<RecycledMaterialToAGVDto> recycledMaterialToAGVDto) {

        String pailNum = recycledMaterialToAGVDto.get(0).getPailNum();
        //1 查询最新数据,校验载具车是否是未解绑
        ProductionBindingTrayLog firstData = productionBindingTrayLogDao.getFirstData(pailNum);
        if (null != firstData && null != firstData.getIsBinding() && 2 != firstData.getIsBinding()) {
            return ResultGenerator.fail("载具车未解绑,请先解绑:" + firstData.getTrayNo() + "与:[" + firstData.getCrystalNo() + "]的关系");
        }
        // 2 校验产品类型是否相同
        List<String> collect = recycledMaterialToAGVDto.stream().map(RecycledMaterialToAGVDto::getMaterialType).distinct().collect(Collectors.toList());
        if (collect.size() != 1) {
            return ResultGenerator.fail("物料的产品类别不同,请校验数据");
        }
        RecycledMaterialToAGVDtos recycledMaterialToAGVDtos = new RecycledMaterialToAGVDtos();
        recycledMaterialToAGVDtos.setRecycledMaterialToAGVDtoList(recycledMaterialToAGVDto);
        recycledMaterialToAGVDtos.setMode("getRecycledInfo");

        //todo 1，先下发头尾料信息给mcs ：将车上的头尾料信息，发送给MCS
//        FlsResultDto resultDto = mesToFlsService.recycledMaterialToAGV(recycledMaterialToAGVDtos);
        ResultDto resultDto = this.recycledMaterialToMcs(recycledMaterialToAGVDtos);
        if (resultDto == null || resultDto.getStatus() == null || resultDto.getStatus() != 200) {
            throw new RuntimeException("下发头尾料信息给mcs失败！" + resultDto.getMessage());
        } else {
            //todo 2，然后通知MCS创建拉动任务
            AgvTaskDto agvTaskDto = initAgvTaskDto();
            ResultDto resultDtoForAgv = this.pullAgvTaskToMcs(agvTaskDto);

            if (resultDtoForAgv == null || resultDtoForAgv.getStatus() == null || resultDtoForAgv.getStatus() != 200) {
                throw new RuntimeException("通知MCS创建agv拉动任务失败！" + resultDto.getMessage());
            }else {
                //3 fls接收数据成功后, 与产品讨论使用车号作为托盘号,车号也替代单晶号做为伪单晶 ,进行绑定,做日志记录
                productionBindingTrayService.bindingRecycledPailNum(pailNum);
                //4 记录已发送的数据
                List<RecycledWaitRecord> recycledWaitRecords = new ArrayList<>();
                for (RecycledMaterialToAGVDto materialToAGVDto : recycledMaterialToAGVDto) {
                    RecycledWaitRecord recycledWaitRecord = new RecycledWaitRecord();
                    recycledWaitRecord.setCreateUser("PDA")
                            .setCreateTime(new Date())
                            .setMaterialType(materialToAGVDto.getMaterialType())
                            .setSectionNo(materialToAGVDto.getSectionNo())
                            .setPailNum(materialToAGVDto.getPailNum())
                            .setLocationNo(materialToAGVDto.getLocationNo())
                            .setLandmarkCode(materialToAGVDto.getLandmarkCode())
                            .setStatus(1);
                    recycledWaitRecords.add(recycledWaitRecord);
                }
                recycledWaitRecordService.saveAll(recycledWaitRecords);
            }
        }
        return ResultGenerator.success();
    }

    private AgvTaskDto initAgvTaskDto(){
        AgvTaskDto agvTaskDto = new AgvTaskDto();
        DictionaryItem agvTaskType = dictionaryItemService.findByThemeValueAndNameAndEnable("pullRecycledMaterialAgvTaskToMcs", "任务类型", true);
        Assert.notNull(agvTaskType, "数据字典中任务类型 配置为空");
        Assert.notNull(agvTaskType.getValue(), "数据字典中任务类型 配置为空");
        DictionaryItem startPoint = dictionaryItemService.findByThemeValueAndNameAndEnable("pullRecycledMaterialAgvTaskToMcs", "起始工作位", true);
        Assert.notNull(startPoint, "数据字典中起始工作位 配置为空");
        Assert.notNull(startPoint.getValue(), "数据字典中起始工作位 配置为空");
        DictionaryItem targetPoint = dictionaryItemService.findByThemeValueAndNameAndEnable("pullRecycledMaterialAgvTaskToMcs", "目标库位", true);
        Assert.notNull(targetPoint, "数据字典中目标库位 配置为空");
        Assert.notNull(targetPoint.getValue(), "数据字典中目标库位 配置为空");
        //任务类型 : 固定值，字典配置 38
        agvTaskDto.setAgvTaskType(Integer.parseInt(agvTaskType.getValue().trim()));
        //随机值
        agvTaskDto.setReqCode(DatePattern.PURE_DATETIME_MS_FORMAT.format(new Date()) + new Random().nextInt(98) + 1);
        //起始库位 ：字典配置 字典配置 M01JDTW01
        agvTaskDto.setStartPoint(startPoint.getValue());
        //目标库位 : 固定值，字典配置 M01DM
        agvTaskDto.setTargetPoint(targetPoint.getValue());
        //随机值
        agvTaskDto.setTaskCode(DatePattern.PURE_DATETIME_MS_FORMAT.format(new Date()) + new Random().nextInt(98) + 1);
        return agvTaskDto;
    }


    @Override
    @ServiceLogs(description = "圆棒评级结果下发mcs")
    public ResultDto rankResult(RankResultDto rankResultDto) {
        rankResultDto.setSpecs(getProductType(rankResultDto.getSpecs()));
        return requestUtilsMcs.postForMcs(new RequestDto(rankResultUrl, rankResultDto)); }
    /**
     *
     */
    private String getProductType(String productType) {
        List<DictionaryItem> toMCSProductSpec = dictionaryItemService.findByThemeValueAndEnable("ToMCSProductSpec", true);
        Map<String, DictionaryItem> specMap = toMCSProductSpec.stream().collect(Collectors.toMap(DictionaryItem::getName, Function.identity(), (t1, t2) -> t1));
        if (specMap.containsKey(productType)) {
            return specMap.get(productType).getValue();
        } else {
            return "0";
        }
    }
    @Override
    public ResultDto orderConfig(List<OrderConfigDto> orderConfigDtoList) {
        return requestUtilsMcs.postForMcs(new RequestDto(orderConfigUrl, orderConfigDtoList));
    }

    @Override
    public ResultDto planWaterLineManageToWmsDto(PlanWaterLineManageToWmsDto planWaterLineManageToWmsDto) {
        return requestUtilsMcs.postForMcsByWaterLineManage(new RequestDto(planWaterLineUrl, planWaterLineManageToWmsDto));
    }

    @Override
    public ResultDto spellBinding(SpellBindingDto spellBindingDto) {

        return requestUtilsMcs.postForMcs(new RequestDto(spellBindingUrl, spellBindingDto));
    }

    @Override
    public ResultDto blankConfig(List<BlankConfigDto> blankConfigDtoList) {

        return requestUtilsMcs.postForMcs(new RequestDto(blankConfigUrl, blankConfigDtoList));
    }

    @Override
    public ResultDto blankConfigForUpdateCheck(SortingConfigDto sortingConfigDto) {

        return requestUtilsMcs.postForMcs(new RequestDto(blankConfigUrl, sortingConfigDto));
    }

    @Override
    public ResultDto crystalTrayUnBindInfo(CrystalTrayUnBindInfoDto crystalTrayUnBindInfoDto) {
        return requestUtilsMcs.postForMcs(new RequestDto(crystalTrayUnBindInfoUrl, crystalTrayUnBindInfoDto));
    }

    @Override
    public ResultDto addManualCall(ManualCallDto manualCallDto) {
        return requestUtilsMcs.postForMcsByWaterLineManage(new RequestDto(addManualCall, manualCallDto));
    }

    @Override
    @Transactional
    public Result pdaBing(PdaBingDto pdaBingDto) {
        //校验卡控：不是检验待进站状态不允许当前操作
        Result<CurrentWipStorageStatusDto> currentWipStorageStatusDtoResult = wipStorageService.selectWipStorageResult(pdaBingDto.getSectionNo());
        if (currentWipStorageStatusDtoResult.getCode() != ResultCode.SUCCESS.getCode()) {
            throw new BusinessException(currentWipStorageStatusDtoResult.getMessage());
        }
        CurrentWipStorageStatusDto currentWipStorageStatusDto = currentWipStorageStatusDtoResult.getData();
        if (currentWipStorageStatusDto == null || currentWipStorageStatusDto.getWipStorageCode() == null || currentWipStorageStatusDto.getWipStorageStatus() == null) {
            throw new BusinessException("站点信息查询失败，请检查在制品信息");
        }
        //如果不是检验待进站状态，报错
        boolean isStatus = currentWipStorageStatusDto.getWipStorageCode().equals(EnumValuesFactory.WipStorageCode.圆棒检验.getKey())
                && currentWipStorageStatusDto.getWipStorageStatus() == EnumValuesFactory.WipStorageStatus.待进站.getKey();
        //(现场有需求：不是圆棒检验待进站的棒子也能绑定，因此暂时取消此站点卡控,后期要加回去), 1025,此卡控按照现场需求重新生效
//        if (!isStatus){
//            return ResultGenerator.fail("晶棒:"+pdaBingDto.getSectionNo()+"不是检验待进站状态不允许当前操作！");
//        }

        //校验是否存在绑定记录，存在则告警
        List<SegmentBindInfo> bindInfos = segmentBindInfoService.findBysegmentNo(pdaBingDto.getSectionNo());
        if (null!= bindInfos && !bindInfos.isEmpty()){
            return ResultGenerator.fail("晶棒:"+pdaBingDto.getSectionNo()+"已经执行过绑定操作不允许重复绑定！");
        }


        pdaBingDto.setType("TYPE_S");
        pdaBingDto.setTail("0");
        pdaBingDto.setHasGone("3");

        String sectionNo = pdaBingDto.getSectionNo();
        PlanProcessingOrder byCode = planProcessingOrderService.findByCode(sectionNo);
        if (null == byCode) {
            return ResultGenerator.fail("加工工单表中无此编号： " + sectionNo);
        }
        if (null == byCode.getStatus() || byCode.getStatus() != 1) {
            return ResultGenerator.fail("此编号： " + sectionNo + " 不在加工中状态，当前状态为：" + EnumValuesFactory.PlanProcessingOrderStatus.getText(byCode.getStatus()));
        }

        if (!EnumValuesFactory.WipStorageCode.圆棒检验.getValue().equals(byCode.getWipStorage().getProcessName())
                && !EnumValuesFactory.WipStorageCode.圆棒反切.getValue().equals(byCode.getWipStorage().getProcessName())) {
            return ResultGenerator.fail("此编号： " + sectionNo + " 站点不在圆棒检验或者圆棒反切");
        }
        // 待进站和已进站通过
        if (byCode.getWipStorage().getStatus() == EnumValuesFactory.WipStorageStatus.已出站.getKey()
        ) {
            return ResultGenerator.fail("此编号： " + sectionNo + " 已出站");
        }

//        // 从划线记录、划线明细、长晶棒表中获取规格、导电型号
//        Map<Object, Object> detailByNo = productionPaintingLineDetailService.findDetailByNo(sectionNo);
//        if (null != detailByNo && detailByNo.size() > 0 && null != detailByNo.get("specs") && null != detailByNo.get("conductive_type")) {
//            pdaBingDto.setProductType((String) detailByNo.get("specs"));
//            pdaBingDto.setPn((String) detailByNo.get("conductive_type"));
//        }
//        if (null == pdaBingDto.getProductType() || null == pdaBingDto.getPn()) {
//            // 从圆棒返切记录表中获取规格、导电型号
//            List<ProductionBackCuttingRecord> allBySegmentNo = productionRecutService.findAllBySegmentNo(sectionNo);
//            if(null != allBySegmentNo && allBySegmentNo.size() > 0 && !StringUtils.isEmpty(allBySegmentNo.get(0).getSectionNoDetailJson())){
//                String sectionNoDetailJson = allBySegmentNo.get(0).getSectionNoDetailJson();
//                JSONObject jsonObject = JSONObject.parseObject(sectionNoDetailJson);
//                // 导电型号（PN型）
//                String conductiveType = jsonObject.getString("conductiveType");
//                // 规格
//                String specs = jsonObject.getString("specs");
//                pdaBingDto.setProductType(specs);
//                pdaBingDto.setPn(conductiveType);
//            }
//
//        }
        // 从晶段详情信息追溯表获取规格和导电型号
        SectionNoDetail bySectionNo = sectionNoDetailService.findBySectionNo(sectionNo);
        if (null != bySectionNo && !StringUtils.isEmpty(bySectionNo.getConductiveType()) && !StringUtils.isEmpty(bySectionNo.getSpecs())) {
            String productType = this.productTypeConversion(bySectionNo.getSpecs());
            pdaBingDto.setProductType(productType);
            pdaBingDto.setPn(bySectionNo.getConductiveType());
            pdaBingDto.setTheoryLength(bySectionNo.getLength());
        }

        if (null == bySectionNo || null == pdaBingDto.getProductType() || null == pdaBingDto.getPn()) {
            return ResultGenerator.fail("此编号： " + sectionNo + " 晶段详情信息追溯表或无规格或PN型数据，无法人工绑定");
        }
        pdaBingDto.setBingUser(BaseContextHandler.getUsername());
        // 中间段免检
        Map<String, String> map = productionPaintingLineDetailService.flowDirection(pdaBingDto.getSectionNo(), "人工单晶上线体");
        if(!map.isEmpty()){
            pdaBingDto.setIsAvoidCheck(map.get("isAvoidCheck"));
        }
        String data = JSONObject.toJSONString(pdaBingDto);
        String url = mcsServiceUrl + pdaBing;
        ResponseEntity<String> responseEntity = restUtils.send(data, url, "");
        String send = responseEntity.getBody();
        JSONObject jsonObject = JSONObject.parseObject(send);
        String code = jsonObject.getString("status");
        if (!"Success".equals(code)) {
            throw new BusinessException("人工单晶上线体失败：" + send + " - " + data);
        }

        ybMesThreadPoolExecutor.execute(new Runnable() {
            @Override
            public void run() {
                //判断是否有评级，有，下发评级给mcs
                try {
                    List<YbInspectData> ybInspectDataList = ybInspectDataDao.findBySectionNo(pdaBingDto.getSectionNo());
                    if (null != ybInspectDataList && ybInspectDataList.size()>0){
                        YbInspectData inspectDataBase = ybInspectDataList.get(0);
                        if(null != inspectDataBase.getProductLevel() && !StringUtils.isEmpty(inspectDataBase.getProductLevel())) {
                            RankResultDto resultDto = getRankResultDtoBySectionNo(inspectDataBase);
                            String rankData = JSONObject.toJSONString(resultDto);
                            String rankUrl = mcsServiceUrl + rankResultUrl;
                            ResponseEntity<String> responseEntityForRank = restUtils.send(rankData, rankUrl, "");
                            String message = responseEntityForRank.getBody();
                            JSONObject jsonObjectFromMcs = JSONObject.parseObject(message);
                            String codeFromMcs = jsonObjectFromMcs.getString("status");
                            if (!"100".equals(codeFromMcs)) {
                                throw new BusinessException("评级下发MCS失败：" + message + " - " + rankData);
                            }
                        }
                    }
                } catch (Exception e) { // 圆棒评级下发mcs不影响主业务
                    e.printStackTrace();
                    log.error("圆棒评级下发mcs", e);
                }
            }
        });

        //绑定信息表中新增一条记录，用以预防重复绑定
        SegmentBindInfo segmentBindInfo = new SegmentBindInfo();
        segmentBindInfo.setSegmentNo(pdaBingDto.getSectionNo());
        segmentBindInfo.setDeviceNo(pdaBingDto.getCutNo());
        segmentBindInfo.setCreateTime(new Date());
        segmentBindInfo.setCreateUserName(BaseContextHandler.getUsername());
        segmentBindInfoService.saveOrUpdate(segmentBindInfo);

        //操作过站
//        Result result = wipStorageService.inStation(pdaBingDto.getSectionNo(), null, false);
//        if (result.getCode() != ResultCode.SUCCESS.getCode()) {
//            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
//            return result;
//        }

        //记录日志
//        SysLogDto sysLogDto = new SysLogDto();
//        sysLogDto.setContent(JSON.toJSONString(pdaBingDto));
//        sysLogDto.setCreateTime(new Date());
//        sysLogDto.setCreateUserName(BaseContextHandler.getUsername());
//        sysLogDto.setCreateUserId(BaseContextHandler.getUserID());
//        sysLogDto.setName("人工单晶上线体");
//        sysLogDto.setResult(JSON.toJSONString(responseEntity));
//        sysLogDto.setType("info");
//        sysLogDto.setMethodName("人工单晶上线体");
//        sysLogDto.setServerAddr("/auto/mesToMcsController/binding");
//        sysLogDto.setReqType("post");
//        sysLogDto.setStatus("Success".equals(code)?200:400);
//        ybFeignClients.save(sysLogDto);
        return ResultGenerator.success();
    }

    @Override
    @Transactional
    public Result pdaBingFb(PdaBingDto pdaBingDto) {

        String sectionNo = pdaBingDto.getSectionNo();

        // todo 校验卡控：不是检验待进站状态不允许当前操作
        Result<CurrentWipStorageStatusDto> currentWipStorageStatusDtoResult = wipStorageService.selectWipStorageResult(pdaBingDto.getSectionNo());
        if (currentWipStorageStatusDtoResult.getCode() != ResultCode.SUCCESS.getCode()) {
            throw new BusinessException(currentWipStorageStatusDtoResult.getMessage());
        }
        CurrentWipStorageStatusDto currentWipStorageStatusDto = currentWipStorageStatusDtoResult.getData();
        if (currentWipStorageStatusDto == null || currentWipStorageStatusDto.getWipStorageCode() == null || currentWipStorageStatusDto.getWipStorageStatus() == null) {
            throw new BusinessException("站点信息查询失败，请检查在制品信息");
        }
        //如果不是检验待进站状态，报错
        boolean isStatus = currentWipStorageStatusDto.getWipStorageCode().equals(EnumValuesFactory.WipStorageCode.方棒检验.getKey())
                && currentWipStorageStatusDto.getWipStorageStatus() == EnumValuesFactory.WipStorageStatus.待进站.getKey();
        //(现场有需求：不是圆棒检验待进站的棒子也能绑定，因此暂时取消此站点卡控,后期要加回去), 1025,此卡控按照现场需求重新生效
        if (!isStatus){
            return ResultGenerator.fail("晶棒:"+pdaBingDto.getSectionNo()+"不是方棒检验待进站状态不允许当前操作！");
        }

//        //校验是否存在绑定记录，存在则告警  todo 方棒绑定，不需要卡重复（现场要求）
//        List<SegmentBindInfoFb> bySegmentNo = segmentBindInfoFbService.findBySegmentNo(pdaBingDto.getSectionNo());
//        if (!bySegmentNo.isEmpty()){
//            return ResultGenerator.fail("晶棒:"+pdaBingDto.getSectionNo()+"已经执行过绑定操作不允许重复绑定！");
//        }


        pdaBingDto.setType("TYPE_S");
        pdaBingDto.setTail("0");
        pdaBingDto.setHasGone("3");
        String crystalNo = sectionNo.substring(0, 12);
        LongCrystal byCrystalNo = longCrystalDao.findByCrystalNo(crystalNo);
        if (null == byCrystalNo || null == byCrystalNo.getProductType() || null == byCrystalNo.getConductiveType()) {
            return ResultGenerator.fail("此编号原： " + sectionNo + " 长晶棒编号:" + crystalNo + " 长晶棒中或无规格或PN型数据，无法人工绑定");
        }
        pdaBingDto.setPn(byCrystalNo.getConductiveType());
        String productType = this.productTypeConversion(byCrystalNo.getSpecs());
        pdaBingDto.setProductType(productType);
        pdaBingDto.setBingUser(BaseContextHandler.getUsername());
        String data = JSONObject.toJSONString(pdaBingDto);
        String url = mcsServiceUrl + pdaBing;
        ResponseEntity<String> responseEntity = restUtils.send(data, url, "");
        String send = responseEntity.getBody();
        JSONObject jsonObject = JSONObject.parseObject(send);
        String code = jsonObject.getString("status");
        if (!"Success".equals(code)) {
            throw new BusinessException("人工单晶上线体失败：" + send + " - " + data);
        }

//        //绑定信息表中新增一条记录，用以预防重复绑定 todo 方棒绑定，不需要卡重复（现场要求）
//        SegmentBindInfoFb segmentBindInfo = new SegmentBindInfoFb();
//        segmentBindInfo.setSegmentNo(pdaBingDto.getSectionNo());
//        segmentBindInfo.setDeviceNo(pdaBingDto.getCutNo());
//        segmentBindInfo.setCreateTime(new Date());
//        segmentBindInfo.setCreateUserName(BaseContextHandler.getUsername());
//        segmentBindInfoFbService.saveOrUpdate(segmentBindInfo);

        return ResultGenerator.success();
    }

    RankResultDto getRankResultDtoBySectionNo(YbInspectData inspectDataBase){
        RankResultDto rankResultDto = new RankResultDto();
        YbInspectDataToMcsDto pinKuData = getPinKuData(inspectDataBase, null);
        PlanWaterLineManageRecord planWaterLineManageRecord = null;
//        PlanWaterLineManageRecord planWaterLineManageRecord = planWaterLineManageService.selectOneOrder(inspectDataBase.getDopant(), inspectDataBase.getConductiveType(), inspectDataBase.getProductTypeSecond(), inspectDataBase.getProductType());
        BigDecimal tRadialCentre = inspectDataBase.getWRadialCentre();
        List<DictionaryItem> resistanceLevel = dictionaryItemService.findByThemeValueAndEnableOrderByPriority("resistanceLevel", true);
        String resLevel = null;
        for (DictionaryItem dictionaryItem : resistanceLevel) {
            String value = dictionaryItem.getValue();
            String[] split = value.split("-");
            if(split.length > 1){
                if(tRadialCentre.compareTo(new BigDecimal(split[0])) > 0 && tRadialCentre.compareTo(new BigDecimal(split[1])) <= 0){
                    resLevel = dictionaryItem.getName();
                    break;
                }
            } else {
                if(tRadialCentre.compareTo(new BigDecimal(dictionaryItem.getValue())) <= 0){
                    resLevel = dictionaryItem.getName();
                    break;
                }
            }
        }
        List<PlanWaterLineManageRecord> planWaterLineManageRecords = planWaterLineManageService.selectAllOrder(inspectDataBase.getDopant(), inspectDataBase.getConductiveType(), inspectDataBase.getProductTypeSecond(), "%" + inspectDataBase.getProductLevel() + "%", "%" + resLevel + "%", inspectDataBase.getSideLengthRange());
        if(null != planWaterLineManageRecords && planWaterLineManageRecords.size() > 0){
            for (PlanWaterLineManageRecord waterLineManageRecord : planWaterLineManageRecords) {
                String productType = inspectDataBase.getProductType();
                String[] split = waterLineManageRecord.getProductType().split(",");
                for (String s : split) {
                    if(s.equals(productType)){
                        planWaterLineManageRecord = waterLineManageRecord;
                        break;
                    }
                }
            }
        }
        if(null != planWaterLineManageRecord){
//            pinKuData.setOrderNo(planWaterLineManageRecord.getAufnr());
            pinKuData.setWaterLineManageOrderNo(planWaterLineManageRecord.getAufnr());
        } else {
            pinKuData.setOrderNo(null);
        }
        //rankResultDto赋值
        rankResultDto.setSectionNo(inspectDataBase.getSectionNo());
        rankResultDto.setSticksCount(inspectDataBase.getSticksCount());
        rankResultDto.setActualLength(inspectDataBase.getActualLength());
        rankResultDto.setCrystalNo(inspectDataBase.getCrystalNo());
        rankResultDto.setActualWeight(inspectDataBase.getActualWeight());
        rankResultDto.setDiameterMin(inspectDataBase.getDiameterMin());
        rankResultDto.setDiameterMax(inspectDataBase.getDiameterMax());
        rankResultDto.setSpecs(inspectDataBase.getProductTypeSecond());
        rankResultDto.setData(inspectDataBase.getSectionType());
//        rankResultDto.setDiameterJudge();
        rankResultDto.setDistortion(inspectDataBase.getDistortion());
        rankResultDto.setIsBevel(inspectDataBase.getIsBevel().toString());
//        rankResultDto.setFineDiameter();
//        rankResultDto.setFineCutLength();
        rankResultDto.setPiecewiseNum(inspectDataBase.getPiecewiseNum());
        rankResultDto.setAgainNum(inspectDataBase.getAgainNum());
        rankResultDto.setHeadTailRecognition(inspectDataBase.getHeadTailRecognition());
//        rankResultDto.setIsSeeBottom();
//        rankResultDto.setLineMarking();
        rankResultDto.setIsCutBack(inspectDataBase.getIsCutBack());
        if (null != planWaterLineManageRecord && !com.sw.mes.core.utils.StringUtils.isEmpty(planWaterLineManageRecord.getAufnr())){
            rankResultDto.setWaterLineManageOrderNo(planWaterLineManageRecord.getAufnr());
        }

        rankResultDto.setProductRank(inspectDataBase.getProductLevel());
        rankResultDto.setTestRank(inspectDataBase.getProductLevelExperiment());
        rankResultDto.setType(inspectDataBase.getSectionType());
        rankResultDto.setConductiveType(inspectDataBase.getConductiveType());

        Integer sticksCount = inspectDataBase.getSticksCount();
        BigDecimal actualLength = (sticksCount != null && sticksCount.compareTo(1) > 0) ? inspectDataBase.getSpellBarLength() : inspectDataBase.getActualLength();
        rankResultDto.setGradeType(inspectDataBase.getGradeType());
        rankResultDto.setLength(actualLength);
        rankResultDto.setCrystalLength(actualLength);
        rankResultDto.setYbInspectDataToMcsDto(pinKuData);

        ////圆棒评级下发MCS信息中字段gradeType和type根据数据字典映射转换
//        changeTypeForMcs(rankResultDto);


        return rankResultDto;
    }



    /**
     * 圆棒评级下发MCS信息中字段gradeType和type根据数据字典映射转换
     * @param rankResultDto
     */
    void changeTypeForMcs(RankResultDto rankResultDto){
        List<DictionaryItem> itemList = dictionaryItemService.findItemByThemeValue("gradeTypeToType", true);
        Map<String, String> weightCoefficient = itemList.stream().collect(Collectors.toMap(DictionaryItem::getName, DictionaryItem::getValue));
        String type = weightCoefficient.get(rankResultDto.getGradeType());
        DictionaryItem item = dictionaryItemService.findByThemeValueAndNameAndEnable("standedLength", "标棒最小长度", true);
        BigDecimal standedLength = new BigDecimal(item.getValue());
        if (null != rankResultDto.getGradeType() && rankResultDto.getGradeType().equals("正常") && null != rankResultDto.getActualLength()){
            if (rankResultDto.getActualLength().compareTo(standedLength)>=0){
                rankResultDto.setType("标棒");
            }else {
                rankResultDto.setType("非标棒");
            }
        }else if (!rankResultDto.getGradeType().equals("正常")){
            rankResultDto.setType(type);
        }
    }





    public YbInspectDataToMcsDto getPinKuData(YbInspectData inspectDataBase, RankResultDto rankResultDto) {
        YbInspectDataToMcsDto ybInspectDataToMcsDto = new YbInspectDataToMcsDto();
        if(null != inspectDataBase){
            ybInspectDataToMcsDto.setSectionNo(inspectDataBase.getSectionNo());
            ybInspectDataToMcsDto.setProductTypeSecond(inspectDataBase.getProductTypeSecond());
            ybInspectDataToMcsDto.setActualLength(inspectDataBase.getActualLength());
            ybInspectDataToMcsDto.setProductType(inspectDataBase.getProductType());
            ybInspectDataToMcsDto.setConductiveType(inspectDataBase.getConductiveType());
            ybInspectDataToMcsDto.setOrderNo(inspectDataBase.getOrderNo());
            ybInspectDataToMcsDto.setProductLevel(inspectDataBase.getProductLevel());
            ybInspectDataToMcsDto.setGradeType(inspectDataBase.getGradeType());
            ybInspectDataToMcsDto.setPullType(inspectDataBase.getPullType());

            ybInspectDataToMcsDto.setTradialCentre(NumberUtil.object2String(inspectDataBase.getTRadialCentre(), null));
            ybInspectDataToMcsDto.setWradialCentre(NumberUtil.object2String(inspectDataBase.getWRadialCentre(), null));
            ybInspectDataToMcsDto.setTcentreLife(NumberUtil.object2String(inspectDataBase.getTCentreLife(), null));
            ybInspectDataToMcsDto.setWcentreLife(NumberUtil.object2String(inspectDataBase.getWCentreLife(), null));
            ybInspectDataToMcsDto.setOxygenContentHead(NumberUtil.object2String(inspectDataBase.getOxygenContentHead(), null));
            ybInspectDataToMcsDto.setOxygenContentTail(NumberUtil.object2String(inspectDataBase.getOxygenContentTail(), null));
            ybInspectDataToMcsDto.setCarbonContentHead(NumberUtil.object2String(inspectDataBase.getCarbonContentHead(), null));
            ybInspectDataToMcsDto.setCarbonContentTail(NumberUtil.object2String(inspectDataBase.getCarbonContentTail(), null));

            if(null != rankResultDto){
                ybInspectDataToMcsDto.setProductLevel(rankResultDto.getProductRank());
                ybInspectDataToMcsDto.setProductTypeSecond(rankResultDto.getSpecs());
                ybInspectDataToMcsDto.setSectionNo(rankResultDto.getSectionNo());
                if(null != rankResultDto.getLength()){
                    ybInspectDataToMcsDto.setActualLength(rankResultDto.getLength());
                }
                ybInspectDataToMcsDto.setGradeType(rankResultDto.getGradeType());
            }
            if(!com.sw.mes.utils.StringUtils.isBlank(ybInspectDataToMcsDto.getProductLevel()) && ybInspectDataToMcsDto.getProductLevel().equals("N1")){
                ybInspectDataToMcsDto.setCarbonContentHead("合格");
                ybInspectDataToMcsDto.setCarbonContentTail("合格");
                ybInspectDataToMcsDto.setOxygenContentHead("合格");
                ybInspectDataToMcsDto.setOxygenContentTail("合格");
                ybInspectDataToMcsDto.setTradialCentre("合格");
                ybInspectDataToMcsDto.setWradialCentre("合格");
                ybInspectDataToMcsDto.setTcentreLife("合格");
                ybInspectDataToMcsDto.setWcentreLife("合格");
            } else if(!com.sw.mes.utils.StringUtils.isBlank(ybInspectDataToMcsDto.getProductLevel())){
                ybInspectDataToMcsDto.setCarbonContentHead("不合格");
                ybInspectDataToMcsDto.setCarbonContentTail("不合格");
                ybInspectDataToMcsDto.setOxygenContentHead("不合格");
                ybInspectDataToMcsDto.setOxygenContentTail("不合格");
                ybInspectDataToMcsDto.setTradialCentre("不合格");
                ybInspectDataToMcsDto.setWradialCentre("不合格");
                ybInspectDataToMcsDto.setTcentreLife("不合格");
                ybInspectDataToMcsDto.setWcentreLife("不合格");
            } else {
                ybInspectDataToMcsDto.setCarbonContentHead("");
                ybInspectDataToMcsDto.setCarbonContentTail("");
                ybInspectDataToMcsDto.setOxygenContentHead("");
                ybInspectDataToMcsDto.setOxygenContentTail("");
                ybInspectDataToMcsDto.setTradialCentre("");
                ybInspectDataToMcsDto.setWradialCentre("");
                ybInspectDataToMcsDto.setTcentreLife("");
                ybInspectDataToMcsDto.setWcentreLife("");
            }

            if (com.sw.mes.utils.StringUtils.isBlank(ybInspectDataToMcsDto.getGradeType())) {
                ybInspectDataToMcsDto.setGradeType(null);
            }
        }
        return ybInspectDataToMcsDto;
    }




    @Override
    @Transactional
    public Result unPdaBing(PdaBingDto pdaBingDto) {

        //校验卡控：不是检验待进站状态不允许当前操作
        Result<CurrentWipStorageStatusDto> currentWipStorageStatusDtoResult = wipStorageService.selectWipStorageResult(pdaBingDto.getSectionNo());
        if (currentWipStorageStatusDtoResult.getCode() != ResultCode.SUCCESS.getCode()) {
            throw new BusinessException(currentWipStorageStatusDtoResult.getMessage());
        }
        CurrentWipStorageStatusDto currentWipStorageStatusDto = currentWipStorageStatusDtoResult.getData();
        if (currentWipStorageStatusDto == null || currentWipStorageStatusDto.getWipStorageCode() == null || currentWipStorageStatusDto.getWipStorageStatus() == null) {
            throw new BusinessException("站点信息查询失败，请检查在制品信息");
        }
        //如果不是检验待进站状态，报错
        boolean isStatus = currentWipStorageStatusDto.getWipStorageCode().equals(EnumValuesFactory.WipStorageCode.圆棒检验.getKey())
                && currentWipStorageStatusDto.getWipStorageStatus() == EnumValuesFactory.WipStorageStatus.待进站.getKey();
        //todo 此站点卡控后期会重新加上
        //现场有需求：不是圆棒检验待进站的棒子也能绑定，因此暂时取消此站点卡控
//        if (!isStatus){
//            return ResultGenerator.fail("晶棒:"+pdaBingDto.getSectionNo()+"不是检验待进站状态不允许当前操作！");
//        }

        //校验是否存在绑定记录，如果不存在则告警
        List<SegmentBindInfo> bindInfos = segmentBindInfoService.findBysegmentNo(pdaBingDto.getSectionNo());
        if (null == bindInfos || bindInfos.isEmpty()){
            return ResultGenerator.fail("晶棒:"+pdaBingDto.getSectionNo()+"未执行过绑定操作不允许解绑！");
        }

        String sectionNo = pdaBingDto.getSectionNo();
        PlanProcessingOrder byCode = planProcessingOrderService.findByCode(sectionNo);
        if (null == byCode) {
            return ResultGenerator.fail("加工工单表中无此编号： " + sectionNo);
        }
        if (null == byCode.getStatus() || byCode.getStatus() != 1) {
            return ResultGenerator.fail("此编号： " + sectionNo + " 不在加工中状态，当前状态为：" + EnumValuesFactory.PlanProcessingOrderStatus.getText(byCode.getStatus()));
        }
        if (!EnumValuesFactory.WipStorageCode.圆棒检验.getValue().equals(byCode.getWipStorage().getProcessName())
                &&!EnumValuesFactory.WipStorageCode.圆棒反切.getValue().equals(byCode.getWipStorage().getProcessName())) {
            return ResultGenerator.fail("此编号： " + sectionNo + " 站点不在圆棒检验或者圆棒反切");
        }
        // 待进站和已进站通过
        if (byCode.getWipStorage().getStatus() == EnumValuesFactory.WipStorageStatus.已出站.getKey()
        ) {
            return ResultGenerator.fail("此编号： " + sectionNo + " 已出站");
        }

        //解绑先下发给mcs
        pdaBingDto.setBingUser(BaseContextHandler.getUsername());
        String data = JSONObject.toJSONString(pdaBingDto);
        String url = mcsServiceUrl + unPdaBing;
        ResponseEntity<String> responseEntity = restUtils.send(data, url, "");
        String send = responseEntity.getBody();
        JSONObject jsonObject = JSONObject.parseObject(send);
        String code = jsonObject.getString("status");
        if (!"Success".equals(code)) {
            throw new BusinessException("人工单晶上线体解绑失败：" + send + " - " + data);
        }


        // 此处是删除之前的绑定记录，而不是新增
        SegmentBindInfo bindInfo = bindInfos.get(0);
        segmentBindInfoService.delete(bindInfo.getId());
        return ResultGenerator.success();
    }


    @Override
    @Transactional
    public Result unPdaBingFb(PdaBingDto pdaBingDto) {

        //校验卡控：不是检验待进站状态不允许当前操作
//        Result<CurrentWipStorageStatusDto> currentWipStorageStatusDtoResult = wipStorageService.selectWipStorageResult(pdaBingDto.getSectionNo());
//        if (currentWipStorageStatusDtoResult.getCode() != ResultCode.SUCCESS.getCode()) {
//            throw new BusinessException(currentWipStorageStatusDtoResult.getMessage());
//        }
//        CurrentWipStorageStatusDto currentWipStorageStatusDto = currentWipStorageStatusDtoResult.getData();
//        if (currentWipStorageStatusDto == null || currentWipStorageStatusDto.getWipStorageCode() == null || currentWipStorageStatusDto.getWipStorageStatus() == null) {
//            throw new BusinessException("站点信息查询失败，请检查在制品信息");
//        }
//        //如果不是检验待进站状态，报错
//        boolean isStatus = currentWipStorageStatusDto.getWipStorageCode().equals(EnumValuesFactory.WipStorageCode.方棒检验.getKey())
//                && currentWipStorageStatusDto.getWipStorageStatus() == EnumValuesFactory.WipStorageStatus.待进站.getKey();
//        //todo 此站点卡控后期会重新加上
//        //现场有需求：不是圆棒检验待进站的棒子也能绑定，因此暂时取消此站点卡控
//        if (!isStatus){
//            return ResultGenerator.fail("晶棒:"+pdaBingDto.getSectionNo()+"不是检验待进站状态不允许当前操作！");
//        }

        //校验是否存在绑定记录，如果不存在则告警   todo 方棒绑定，不需要卡重复（现场要求）
//        List<SegmentBindInfoFb> bindInfos = segmentBindInfoFbService.findBySegmentNo(pdaBingDto.getSectionNo());
//        if (bindInfos.isEmpty()){
//            return ResultGenerator.fail("晶棒:"+pdaBingDto.getSectionNo()+"未执行过绑定操作不允许解绑！");
//        }

//        String sectionNo = pdaBingDto.getSectionNo();
//        PlanProcessingOrder byCode = planProcessingOrderService.findByCode(sectionNo);
//        if (null == byCode) {
//            return ResultGenerator.fail("加工工单表中无此编号： " + sectionNo);
//        }
//        if (null == byCode.getStatus() || byCode.getStatus() != 1) {
//            return ResultGenerator.fail("此编号： " + sectionNo + " 不在加工中状态");
//        }
//        if (!EnumValuesFactory.WipStorageCode.圆棒检验.getValue().equals(byCode.getWipStorage().getProcessName())) {
//            return ResultGenerator.fail("此编号： " + sectionNo + " 站点不在圆棒检验");
//        }
//        // 待进站和已进站通过
//        if (byCode.getWipStorage().getStatus() == EnumValuesFactory.WipStorageStatus.已出站.getKey()
//        ) {
//            return ResultGenerator.fail("此编号： " + sectionNo + " 已出站");
//        }

        //解绑先下发给mcs
        pdaBingDto.setBingUser(BaseContextHandler.getUsername());
        String data = JSONObject.toJSONString(pdaBingDto);
        String url = mcsServiceUrl + unPdaBing;
        ResponseEntity<String> responseEntity = restUtils.send(data, url, "");
        String send = responseEntity.getBody();
        JSONObject jsonObject = JSONObject.parseObject(send);
        String code = jsonObject.getString("status");
        if (!"Success".equals(code)) {
            throw new BusinessException("人工单晶上线体解绑失败：" + send + " - " + data);
        }


//        // 此处是删除之前的绑定记录，而不是新增
//        SegmentBindInfoFb bindInfo = bindInfos.get(0);
//        segmentBindInfoFbService.delete(bindInfo.getId());
        return ResultGenerator.success();
    }

    @Override
    public Result updateWarehouse(WarehouseDto warehouseDto) {
        String data = JSONObject.toJSONString(warehouseDto);
        String url = mcsServiceUrl + "/" + updateWarehouse;
//        String url = "http://10.141.0.130:8806/agv/mesToMcsController/updateWarehouse";
        ResponseEntity<String> responseEntity = restUtils.send(data, url, "");
        String send = responseEntity.getBody();
        JSONObject jsonObject = JSONObject.parseObject(send);
        String code = jsonObject.getString("status");
        if (!"Success".equals(code)) {
            throw new BusinessException("更新库位载具失败：" + send + " - " + data);
        }
        // 送验绑定下发MCS
//        if (!StringUtils.isEmpty(warehouseDto.getFrockCode())) {
//            InspectionRecordDto inspectionRecordDto = new InspectionRecordDto();
//            inspectionRecordDto.setPailNum(warehouseDto.getFrockCode());
//            return inspectionRecordService.sendMCS(inspectionRecordDto);
//        }

        // 送验绑定下发MCS
//        ybMesThreadPoolExecutor.execute(new Runnable() {
//            @Override
//            public void run() {
//                // 下发MCS
//                try {
//                    if (!StringUtils.isEmpty(warehouseDto.getFrockCode())) {
//                        sendUpdateVehicleInfo(warehouseDto);
//                    }
//                } catch (Exception e) { // 下发MCS不影响主业务
//                    e.printStackTrace();
//                    log.error("下发圆棒信息至MCS", e);
//                }
//            }
//        });
        return ResultGenerator.success();
    }


    void sendUpdateVehicleInfo(WarehouseDto warehouseDto){
        List<ProductionBindingTray> productionBindingTrays = productionBindingTrayDao.findByTrayNoAndCrystalNo(warehouseDto.getFrockCode());
        if (productionBindingTrays.size()>=2){
            SybdCallDto sybdCallDto = new SybdCallDto();
            sybdCallDto.setFrockCode(warehouseDto.getFrockCode());
            sybdCallDto.setFrockType("5");
            List<String> _crystalNoArr = new ArrayList<String>();
            //所需晶棒详情
            List<LongCrystal> crystalInfos = new ArrayList<LongCrystal>();
            if (null != productionBindingTrays && productionBindingTrays.size() > 0) {
                for (ProductionBindingTray productionBindingTray : productionBindingTrays) {
                    if (com.sw.mes.core.utils.StringUtils.isBlank(productionBindingTray.getCrystalNo())) {
                        continue;
                    }
                    LongCrystal longCrystal = longCrystalDao.findByCrystalNo(productionBindingTray.getCrystalNo());
                    //将最后的晶棒绑定时间推送给mcs
                    if (productionBindingTrays.size() == 1){
                        longCrystal.setGmtUpdate(productionBindingTray.getBindingTime());
                    }else {
                        List<ProductionBindingTray> lastOneByTrayNoAndCrystalNo = productionBindingTrayDao.findLastOneByTrayNoAndCrystalNo(warehouseDto.getFrockCode());
                        if (null != lastOneByTrayNoAndCrystalNo && lastOneByTrayNoAndCrystalNo.size()>0){
                            longCrystal.setGmtUpdate(lastOneByTrayNoAndCrystalNo.get(0).getBindingTime());
                        }
                    }

                    _crystalNoArr.add(productionBindingTray.getCrystalNo());
                    crystalInfos.add(longCrystal);
                }
                //单晶编号
                sybdCallDto.setMaterialNo(com.sw.mes.core.utils.StringUtils.join(_crystalNoArr.toArray(), "|"));
                sybdCallDto.setMaterialDetailInfo(JSON.toJSONString(crystalInfos));
                String sendData = JSONObject.toJSONString(sybdCallDto);
                String updateVehicleUrl = mcsServiceUrl + "/" + SYCBD_URL;
                ResponseEntity<String> responseEntityForMcs = restUtils.send(sendData, updateVehicleUrl, "");
                String sendInfo = responseEntityForMcs.getBody();
                JSONObject jsonObjectFromMcs = JSONObject.parseObject(sendInfo);
                String codeFromMcs = jsonObjectFromMcs.getString("status");
                if ("Success".equals(codeFromMcs)) {
                } else {
                    throw new BusinessException("送验绑定下发MCS失败：" + sendInfo + " - " + sendData);
                }
            }
        }
    }

    @Override
    @ServiceLogs(description = "【装罐料MES->MCS】生产配方信息下发")
    public Result<FormulaSchemeToMesDto> formulaSchemeToMcs(Long formulaSchemeId) {
        FormulaScheme formulaScheme = formulaSchemeService.get(formulaSchemeId);
        if(formulaScheme == null){
            return ResultGenerator.fail("配方不存在!");
        }
        FormulaSchemeToMesDto dto = modelMapper.map(formulaScheme, FormulaSchemeToMesDto.class);
        dto.setBarrelShaped(formulaScheme.getBarrelShaped().stream().map(
                barrelShaped -> {
                    return modelMapper.map(barrelShaped, BarrelShapedToMcsDto.class);
                }).collect(Collectors.toList())
        );
        dto.setTypeFormula(formulaScheme.getTypeFormula().stream().map(
                typeFormula -> {
                    return modelMapper.map(typeFormula, TypeFormulaToMcsDto.class);
                }).collect(Collectors.toList()));
        dto.setFormulaSchemeDetailDtos(formulaSchemeDetailService.findByFormulaSchemeId(formulaScheme.getId()).stream()
                .map(formulaSchemeDetail -> {
                    return modelMapper.map(formulaSchemeDetail, FormulaSchemeDetailToMcsDto.class);
                })
                .collect(Collectors.toList()));

        ResultDto resultDto = requestUtilsMcs.canningMaterialPostForMcs(new RequestDto(formulaSchemeToMcsUrl, dto));
        if (resultDto == null || resultDto.getStatus() == null || resultDto.getStatus() != 200) {
            return ResultGenerator.fail("配方数据下发MCS失败！：" + resultDto.getMessage(), dto);
        }

        return ResultGenerator.success(dto);
    }

    @Override
    @ServiceLogs(description = "【装罐料MES->MCS】生产任务下发")
    public Result<IssueMoToMcsDto> issueMoInterface(Object obj) {
        IssueMoToMcsDto dto = new IssueMoToMcsDto();

        if(obj instanceof LoadingTask) {//装料任务
            LoadingTask task = (LoadingTask)obj;
            dto.setOrderNo("0-"+task.getId());
            dto.setOrderName(task.getEquipmentCode()+"-"+task.getLotNo());
            dto.setOrderType(0);
            dto.setArea(task.getArea());
            dto.setSeries(task.getSeries());
            dto.setEquipmentCode(task.getEquipmentCode());
            dto.setLotNo(task.getLotNo());
            dto.setAgainNum(0);
            dto.setAgainTime(task.getEtTime());
            List<WeightSchemeDto> weightSchemeList = new ArrayList<>();
            List<ProductionFurnaceMaterialSplit> split =
                    productionFurnaceMaterialSplitService.findByRawTypeAndTaskIdAndBucketIndex(0,task.getId(),1);
            if(split == null || split.size() < 1){
                return ResultGenerator.fail("分桶方案不存在！");
            }
            dto.setFormulaSchemeId(split.get(0).getSchemeId());
            dto.setFormulaSchemeCode(split.get(0).getSchemeCode());
            dto.setFormulaWeightSchemeId(split.get(0).getWeightSchemeId());
            dto.setBarrelSpecs(split.get(0).getBarrelSpecs());
            for(ProductionFurnaceMaterialSplit data : split){
                WeightSchemeDto weightSchemeDto = new WeightSchemeDto();
                weightSchemeDto.setBucketWeight(data.getBucketWeight());
                weightSchemeDto.setMaterialType(data.getMaterialType());
                weightSchemeDto.setMaterialClassName(data.getMaterialClassName());
                weightSchemeDto.setMaterialWeight(data.getMaterialWeight());
                weightSchemeList.add(weightSchemeDto);
            }
            dto.setWeightA(task.getWeight());
            dto.setWeightSchemeA(weightSchemeList);
            CrucibleInfoToMcsDto crucibleInfoToMcsDto = new CrucibleInfoToMcsDto();
            //查询坩埚定投信息
            CrucibleFixedCasting crucible = crucibleFixedCastingService.getCrucibleFixedCastingByEquipmentCode(task.getEquipmentCode());
            if(crucible != null){
                BeanUtils.copyProperties(crucible, crucibleInfoToMcsDto);
                List<WeightSchemeDto> weightSchemeListB = new ArrayList<>();
                WeightSchemeDto weightSchemeDto = new WeightSchemeDto();
                weightSchemeDto.setMaterialType(JSONObject.toJSONString(crucible));
                weightSchemeListB.add(weightSchemeDto);
                dto.setWeightSchemeB(weightSchemeListB);
            }
        }else if(obj instanceof AgainTaskDetail) {//灌料任务
            AgainTaskDetail task = (AgainTaskDetail)obj;
            dto.setOrderNo(task.getRawType() + "-" + task.getId());
            dto.setOrderName(task.getEquipmentCode()+"-"+task.getLotNo());
            dto.setOrderType(task.getRawType());
            dto.setArea(task.getArea());
            dto.setSeries(task.getSeries());
            dto.setEquipmentCode(task.getEquipmentCode());
            dto.setLotNo(task.getLotNo());
            dto.setAgainNum(task.getAgainNum());
            dto.setAgainTime(task.getAgainTime());
            String[] splitPail = task.getPailNum().split(",");
            String[] splitWeigth = task.getTaskWeigths().split(",");
            if(splitPail.length > 0) {
                List<WeightSchemeDto> weightSchemeListA = new ArrayList<>();
                List<ProductionFurnaceMaterialSplit> split =
                        productionFurnaceMaterialSplitService.findByRawTypeAndTaskIdAndBucketIndex(task.getRawType(), task.getAgainTaskId(), Integer.parseInt(splitPail[0]));
                if (split == null || split.size() < 1) {
                    return ResultGenerator.fail("分桶方案不存在！");
                }
                dto.setFormulaSchemeId(split.get(0).getSchemeId());
                dto.setFormulaSchemeCode(split.get(0).getSchemeCode());
                dto.setFormulaWeightSchemeId(split.get(0).getWeightSchemeId());
                dto.setBarrelSpecs(split.get(0).getBarrelSpecs());
                for (ProductionFurnaceMaterialSplit data : split) {
                    WeightSchemeDto weightSchemeDto = new WeightSchemeDto();
                    weightSchemeDto.setBucketWeight(data.getBucketWeight());
                    weightSchemeDto.setMaterialType(data.getMaterialType());
                    weightSchemeDto.setMaterialClassName(data.getMaterialClassName());
                    weightSchemeDto.setMaterialWeight(data.getMaterialWeight());
                    weightSchemeListA.add(weightSchemeDto);
                }
                dto.setWeightA(NumberUtil.Object2BigDecimal(splitWeigth[0]));
                dto.setWeightSchemeA(weightSchemeListA);
            }

            if(splitPail.length > 1) {
                List<WeightSchemeDto> weightSchemeListB = new ArrayList<>();
                List<ProductionFurnaceMaterialSplit> split =
                        productionFurnaceMaterialSplitService.findByRawTypeAndTaskIdAndBucketIndex(task.getRawType(), task.getAgainTaskId(), Integer.parseInt(splitPail[1]));
                if (split == null || split.size() < 1) {
                    return ResultGenerator.fail("分桶方案不存在！");
                }
                dto.setFormulaSchemeId(split.get(0).getSchemeId());
                dto.setFormulaSchemeCode(split.get(0).getSchemeCode());
                dto.setFormulaWeightSchemeId(split.get(0).getWeightSchemeId());
                dto.setBarrelSpecs(split.get(0).getBarrelSpecs());
                for (ProductionFurnaceMaterialSplit data : split) {
                    WeightSchemeDto weightSchemeDto = new WeightSchemeDto();
                    weightSchemeDto.setBucketWeight(data.getBucketWeight());
                    weightSchemeDto.setMaterialType(data.getMaterialType());
                    weightSchemeDto.setMaterialClassName(data.getMaterialClassName());
                    weightSchemeDto.setMaterialWeight(data.getMaterialWeight());
                    weightSchemeListB.add(weightSchemeDto);
                }
                dto.setWeightB(NumberUtil.Object2BigDecimal(splitWeigth[1]));
                dto.setWeightSchemeB(weightSchemeListB);
            }
        }else if(obj instanceof AgainTaskPrepare) {//预装料任务
            AgainTaskPrepare task = (AgainTaskPrepare)obj;
            dto.setOrderNo("3-" + task.getId());
            dto.setOrderName(task.getEquipmentCode()+"-"+task.getLotNo());
            dto.setOrderType(3);
            dto.setArea(task.getArea());
            dto.setSeries(task.getSeries());
            dto.setEquipmentCode(task.getEquipmentCode());
            dto.setLotNo(task.getLotNo());
            dto.setAgainNum(task.getAgainNum());
            dto.setAgainTime(task.getGmtCreate());
            String[] splitPail = task.getPailNum().split(",");
            String[] splitWeigth = task.getTaskWeigths().split(",");
            if(splitPail.length > 0) {
                List<WeightSchemeDto> weightSchemeListA = new ArrayList<>();
                List<ProductionFurnaceMaterialSplit> split =
                        productionFurnaceMaterialSplitService.findByRawTypeAndTaskIdAndBucketIndex(3, task.getId(), Integer.parseInt(splitPail[0]));
                if (split == null || split.size() < 1) {
                    return ResultGenerator.fail("分桶方案不存在！");
                }
                dto.setFormulaSchemeId(split.get(0).getSchemeId());
                dto.setFormulaSchemeCode(split.get(0).getSchemeCode());
                dto.setFormulaWeightSchemeId(split.get(0).getWeightSchemeId());
                dto.setBarrelSpecs(split.get(0).getBarrelSpecs());
                for (ProductionFurnaceMaterialSplit data : split) {
                    WeightSchemeDto weightSchemeDto = new WeightSchemeDto();
                    weightSchemeDto.setBucketWeight(data.getBucketWeight());
                    weightSchemeDto.setMaterialType(data.getMaterialType());
                    weightSchemeDto.setMaterialClassName(data.getMaterialClassName());
                    weightSchemeDto.setMaterialWeight(data.getMaterialWeight());
                    weightSchemeListA.add(weightSchemeDto);
                }
                dto.setWeightA(NumberUtil.Object2BigDecimal(splitWeigth[0]));
                dto.setWeightSchemeA(weightSchemeListA);
            }

            if(splitPail.length > 1) {
                List<WeightSchemeDto> weightSchemeListB = new ArrayList<>();
                List<ProductionFurnaceMaterialSplit> split =
                        productionFurnaceMaterialSplitService.findByRawTypeAndTaskIdAndBucketIndex(3, task.getId(), Integer.parseInt(splitPail[1]));
                if (split == null || split.size() < 1) {
                    return ResultGenerator.fail("分桶方案不存在！");
                }
                dto.setFormulaSchemeId(split.get(0).getSchemeId());
                dto.setFormulaSchemeCode(split.get(0).getSchemeCode());
                dto.setFormulaWeightSchemeId(split.get(0).getWeightSchemeId());
                dto.setBarrelSpecs(split.get(0).getBarrelSpecs());
                for (ProductionFurnaceMaterialSplit data : split) {
                    WeightSchemeDto weightSchemeDto = new WeightSchemeDto();
                    weightSchemeDto.setBucketWeight(data.getBucketWeight());
                    weightSchemeDto.setMaterialType(data.getMaterialType());
                    weightSchemeDto.setMaterialClassName(data.getMaterialClassName());
                    weightSchemeDto.setMaterialWeight(data.getMaterialWeight());
                    weightSchemeListB.add(weightSchemeDto);
                }
                dto.setWeightB(NumberUtil.Object2BigDecimal(splitWeigth[1]));
                dto.setWeightSchemeB(weightSchemeListB);
            }
        }

        ResultDto resultDto = requestUtilsMcs.canningMaterialPostForMcs(new RequestDto(issueMoToMcsUrl, dto));
        if (resultDto == null || resultDto.getStatus() == null || resultDto.getStatus() != 200) {
            return ResultGenerator.fail("生产任务数据下发MCS失败！：" + resultDto.getMessage(), dto);
        }

        return ResultGenerator.success(dto);
    }

    @Override
    @ServiceLogs(description = "【装罐料MES->MCS】取消生产任务下发")
    public Result<List<CancelMoDistributionToMcsDto>> cancelMoDistributionInterface(Object obj) {
        List<CancelMoDistributionToMcsDto> dtoList = new ArrayList<>();
        if(obj instanceof LoadingTask) {//装料任务
            CancelMoDistributionToMcsDto dto = new CancelMoDistributionToMcsDto();
            LoadingTask task = (LoadingTask)obj;
            dto.setOrderNo("0-"+task.getId());
            dto.setOrderType(0);
            dto.setReason(task.getOperationCause());
            dto.setCancelTime(task.getOperationTime());
            dtoList.add(dto);
        }else if(obj instanceof AgainTask) {//灌料任务
            AgainTask task = (AgainTask)obj;
            List<AgainTaskDetail> taskDetails = againTaskDetailService.findByAgainTaskId(task.getId());
            for(AgainTaskDetail againTaskDetail : taskDetails) {
                CancelMoDistributionToMcsDto dto = new CancelMoDistributionToMcsDto();
                dto.setOrderNo(againTaskDetail.getRawType() + "-" + againTaskDetail.getId());
                dto.setOrderType(againTaskDetail.getRawType());
                dto.setReason(task.getOperationCause());
                dto.setCancelTime(task.getOperationTime());
                dtoList.add(dto);
            }
        } else if(obj instanceof AgainTaskDetail) {//灌料任务
            AgainTaskDetail task = (AgainTaskDetail)obj;
            CancelMoDistributionToMcsDto dto = new CancelMoDistributionToMcsDto();
            dto.setOrderNo(task.getRawType() + "-" + task.getId());
            dto.setOrderType(task.getRawType());
            dto.setReason(task.getOperationCause());
            dto.setCancelTime(task.getOperationTime());
            dtoList.add(dto);
        } else if(obj instanceof AgainTaskPrepare){//预装料任务
            AgainTaskPrepare task = (AgainTaskPrepare)obj;
            CancelMoDistributionToMcsDto dto = new CancelMoDistributionToMcsDto();
            dto.setOrderNo(3 + "-" + task.getId());
            dto.setOrderType(3);
            dto.setReason("");
            dto.setCancelTime(new Date());
            dtoList.add(dto);

        }

        ResultDto resultDto = requestUtilsMcs.canningMaterialPostForMcs(new RequestDto(cancelMoDistributionToMcsUrl, dtoList));
        if (resultDto == null || resultDto.getStatus() == null || resultDto.getStatus() != 200) {
            return ResultGenerator.fail("取消生产任务数据下发MCS失败！：" + resultDto.getMessage(), dtoList);
        }

        return ResultGenerator.success(dtoList);
    }

    @Override
    public Result moTrayBinding(MoTrayBindingDto dto) {
        MoTrayBindingToMcsDto moTrayBindingToMcsDto = new MoTrayBindingToMcsDto();
        moTrayBindingToMcsDto.setTrayCode(dto.getTrayCode());
        moTrayBindingToMcsDto.setTrayState(2);
        moTrayBindingToMcsDto.setTrayType(dto.getTrayType());
        moTrayBindingToMcsDto.setMaterialType(dto.getMaterialType());
        moTrayBindingToMcsDto.setMaterialBatch(dto.getMaterialBatch());
        moTrayBindingToMcsDto.setMaterialNo(dto.getMaterialNo());
        //封装物料属性
        moTrayBindingToMcsDto.setMaterialProperty(fromDto(dto));
        List<BindingCassetteToMcsDto> list = new ArrayList<>();
        for(MoTrayBindingCassetteDetailDto cassette : dto.getCassetteDetail()){
            BindingCassetteToMcsDto bindingCassetteToMcsDto = new BindingCassetteToMcsDto();
            bindingCassetteToMcsDto.setCassetteCode(cassette.getCassetteCode());
            bindingCassetteToMcsDto.setPositionIndex(cassette.getPositionIndex());
            bindingCassetteToMcsDto.setCassetteState(cassette.getCassetteState());
            bindingCassetteToMcsDto.setCassetteType(dto.getCassetteType());
            bindingCassetteToMcsDto.setCassetteUse(dto.getCassetteUse());
            bindingCassetteToMcsDto.setMaterialType(dto.getMaterialType());
            bindingCassetteToMcsDto.setMaterialBatch(dto.getMaterialBatch());
            bindingCassetteToMcsDto.setMaterialNo(dto.getMaterialNo());
            bindingCassetteToMcsDto.setMaterialProperty(fromDto(dto));
            list.add(bindingCassetteToMcsDto);
        }

        moTrayBindingToMcsDto.setCassetteList(list);
        if (GlobalSwitch.enable(GlobalSwitchNamespace.NAMESPACE_AUTOMATION, "moTrayBinding", false)) {
            ResultDto resultDto = requestUtilsMcs.canningMaterialPostForMcs(new RequestDto("GG".equals(moTrayBindingToMcsDto.getTrayType()) ? moTrayBindingGGToMcsUrl : moTrayBindingToMcsUrl, moTrayBindingToMcsDto));
            if (resultDto == null || resultDto.getStatus() == null || resultDto.getStatus() != 200) {
                return ResultGenerator.fail("原料托盘绑定数据下发MCS失败！：" + resultDto.getMessage(), moTrayBindingToMcsDto);
            }
        }
        MaterialTrayBinding materialTrayBinding = materialTrayBindingService.findByTrayCode(dto.getTrayCode());
        if(materialTrayBinding == null) {
           materialTrayBinding = new MaterialTrayBinding();
        }
        MaterialTrayBindingDto materialTrayBindingDto = modelMapper.map(dto, MaterialTrayBindingDto.class);
        BeanUtils.copyProperties(materialTrayBindingDto, materialTrayBinding, BeanUtil.getIgnoreProperties(materialTrayBindingDto, null, null));
        materialTrayBinding.setOperateTime(new Date());
        materialTrayBinding.setOperateUser(BaseContextHandler.getUsername());
        materialTrayBindingService.saveOrUpdate(materialTrayBinding);
        return ResultGenerator.success(moTrayBindingToMcsDto);
    }

    @Override
    public String productTypeConversion(String productType) {
        List<DictionaryItem> toMCSProductSpec = dictionaryItemService.findByThemeValueAndEnable("ToMCSProductSpec", true);
        Map<String, DictionaryItem> specMap = toMCSProductSpec.stream().collect(Collectors.toMap(DictionaryItem::getName, Function.identity(), (t1, t2) -> t1));
        if (specMap.containsKey(productType)) {
            return specMap.get(productType).getValue();
        } else {
            return "0";
        }
    }

    @Override
    public Result exemption(PdaBingDto pdaBingDto) {
        String sectionNo = pdaBingDto.getSectionNo();
        PlanProcessingOrder byCode = planProcessingOrderService.findByCode(sectionNo);
        if (null == byCode) {
            return ResultGenerator.fail("加工工单表中无此编号： " + sectionNo);
        }
        if (null == byCode.getStatus() || byCode.getStatus() != 1) {
            return ResultGenerator.fail("此编号： " + sectionNo + " 不在加工中状态");
        }
        if (!EnumValuesFactory.WipStorageCode.圆棒检验.getValue().equals(byCode.getWipStorage().getProcessName())) {
            return ResultGenerator.fail("此编号： " + sectionNo + " 站点不在圆棒检验");
        }
        // 待进站和已进站通过
        if (byCode.getWipStorage().getStatus() == EnumValuesFactory.WipStorageStatus.已出站.getKey()) {
            return ResultGenerator.fail("此编号： " + sectionNo + " 已出站");
        }
        String url = mcsServiceUrl + exemption;
        ResponseEntity<String> responseEntity = restUtils.send(JSONObject.toJSONString(pdaBingDto), url, "");
        String send = responseEntity.getBody();
        JSONObject jsonObject = JSONObject.parseObject(send);
        String code = jsonObject.getString("status");
        if (!"Success".equals(code)) {
            throw new BusinessException("晶裂免检下发失败：" + sectionNo + " - " + send);
        }


        return ResultGenerator.success();
    }

    @Override
    public Result moWarehousingBinding(MoWarehousingBindingDto dto) {
        MaterialWarehousingBinding byMaterialBatch = materialWarehousingBindingService.findByMaterialBatch(dto.getMaterialBatch());
        if(ObjectUtils.isNotEmpty(byMaterialBatch)){
            return ResultGenerator.fail("该批次【"+ dto.getMaterialBatch() +"】已绑定库位【"+byMaterialBatch.getWarehouseStock() +"】不能重复绑定!");
        }

        MoWarehousingBindingToMcsDto moWarehousingBindingToMcsDto = new MoWarehousingBindingToMcsDto();
        moWarehousingBindingToMcsDto.setWarehouseStock(dto.getWarehouseStock());
        moWarehousingBindingToMcsDto.setForkliftLocationCode(dto.getForkliftLocationCode());
        moWarehousingBindingToMcsDto.setMaterialNo(dto.getMaterialNo());
        moWarehousingBindingToMcsDto.setWarehouseStatus(2);
        //封装物料属性
        MaterialDetailDto materialDetailDto = fromDto(dto);
        materialDetailDto.setBatchNo(dto.getMaterialBatch());
        materialDetailDto.setMaterialCode(dto.getMaterialNo());
        moWarehousingBindingToMcsDto.setMaterialDetailInfo(JSONObject.toJSONString(materialDetailDto));
        String taskCode = "";
        String taskMsg = "";
        if (GlobalSwitch.enable(GlobalSwitchNamespace.NAMESPACE_AUTOMATION, "moWarehousingBinding", false)) {
            //下发绑定关系
            ResultDto resultDto = requestUtilsMcs.canningMaterialPostForMcs(new RequestDto(moWarehousingBindingToMcsUrl, moWarehousingBindingToMcsDto));
            if (resultDto == null || resultDto.getStatus() == null || resultDto.getStatus() != 200) {
                return ResultGenerator.fail("原料库位绑定数据下发MCS失败！：" + resultDto.getMessage(), moWarehousingBindingToMcsDto);
            }

            try {
                AgvCallDto agvCall = new AgvCallDto();
                agvCall.setKeyword(EnumValuesAgv.AGVKeyword.原料拉动.getValue());//关键字
                agvCall.setStartPoint(dto.getWarehouseStock()); //开始工作位  - 当前传入库位编码
                agvCall.setTargetPoint("M01HC");//结束工作位
                //其他信息可根据配置信息自动填充
                taskCode = agvDispatchService.callAgv(agvCall);
                taskMsg = "呼叫完成";
            } catch (Exception e){
                taskMsg = "调度AGV任务失败: " + e.getMessage();
            }
        }
        MaterialWarehousingBinding materialWarehousingBinding = new MaterialWarehousingBinding();
        BeanUtils.copyProperties(dto, materialWarehousingBinding, BeanUtil.getIgnoreProperties(dto, null, null));
        materialWarehousingBinding.setAgvTaskCode(taskCode);
        materialWarehousingBinding.setAgvTaskMsg(StringUtils.substring(taskMsg, 0,100));
        materialWarehousingBinding.setOperateTime(new Date());
        materialWarehousingBinding.setOperateUser(BaseContextHandler.getUsername());
        materialWarehousingBindingService.saveOrUpdate(materialWarehousingBinding);

        return ResultGenerator.success(moWarehousingBindingToMcsDto);
    }


    public MaterialPropertyDto fromDto(MoTrayBindingDto dto) {
        return modelMapper.map(dto, MaterialPropertyDto.class);
    }

    public MaterialDetailDto fromDto(MoWarehousingBindingDto dto) {
        return modelMapper.map(dto, MaterialDetailDto.class);
    }

}