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

import com.alibaba.fastjson.JSON;
import com.sw.mes.base.global.GlobalSwitch;
import com.sw.mes.base.global.GlobalSwitchNamespace;
import com.sw.mes.base.global.SwitchConfig;
import com.sw.mes.base.system.entity.DictionaryItem;
import com.sw.mes.base.system.entity.SysLog;
import com.sw.mes.base.system.service.DictionaryItemService;
import com.sw.mes.base.system.service.SysLogService;
import com.sw.mes.base.workinprocess.entity.PlanProcessingOrder;
import com.sw.mes.base.workinprocess.service.PlanProcessingOrderService;
import com.sw.mes.core.api.system.StoreFeignClients;
import com.sw.mes.core.context.BaseContextHandler;
import com.sw.mes.core.dto.store.StoreOperatorDetailDto;
import com.sw.mes.core.dto.store.StoreOperatorDto;
import com.sw.mes.core.enums.EnumValuesFactory;
import com.sw.mes.core.enums.StoreBusinessTypeEnum;
import com.sw.mes.core.enums.StoreOperatorTypeEnum;
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.core.utils.BeanUtil;
import com.sw.mes.core.utils.IpUtils;
import com.sw.mes.core.utils.NumberUtil;
import com.sw.mes.core.utils.StringUtils;
import com.sw.mes.enumvalue.EnumValuesAgv;
import com.sw.mes.base.factory.init.entity.Equipment;
import com.sw.mes.base.factory.init.service.EquipmentService;
import com.sw.mes.enumvalue.EnumValuesEap;
import com.sw.mes.enumvalue.EnumValuesServer;
import com.sw.mes.mmcs.service.MMcsInterfaceService;
import com.sw.mes.mqtt.service.NotificationService;
import com.sw.mes.outside.service.EapService;
import com.sw.mes.outside.util.EAPUtils;
import com.sw.mes.sap.SapServer;
import com.sw.mes.sap.entity.ReportSapWorkinghours;
import com.sw.mes.sap.service.ReportSapGoodsmvtService;
import com.sw.mes.sap.service.ReportSapWorkinghoursService;
import com.sw.mes.wms.dto.ReportWmsRecordDto;
import com.sw.mes.wms.service.GenerateReportWms;
import com.sw.mes.wms.service.ReportWmsRecordService;
import com.sw.mes.yb.agv.dto.AgvCallDto;
import com.sw.mes.yb.agv.service.AgvDispatchService;
import com.sw.mes.yb.ipc.dto.ButtonClickDto;
import com.sw.mes.yb.ipc.mapping.ButtonType;
import com.sw.mes.yb.ipc.service.IBaseButtonHandler;
import com.sw.mes.yb.plan.entity.ProductionOrder;
import com.sw.mes.yb.plan.entity.ProductionSchedule;
import com.sw.mes.yb.plan.service.ProductionOrderService;
import com.sw.mes.yb.plan.service.ProductionScheduleService;
import com.sw.mes.yb.production.dto.AgainTask.AgainTaskDto;
import com.sw.mes.yb.production.dto.AgainTaskDetail.AgainTaskDetailDto;
import com.sw.mes.yb.production.dto.BlastFurnaceDetail.BlastFurnaceDetailDto;
import com.sw.mes.yb.production.dto.CallTakeCrystalAgvDto;
import com.sw.mes.yb.production.dto.InputFurnaceDetailDto;
import com.sw.mes.yb.production.dto.LoadingTask.LoadingTaskDto;
import com.sw.mes.yb.production.entity.*;
import com.sw.mes.yb.production.notification.AgainTaskDetailMessage;
import com.sw.mes.yb.production.notification.AgainTaskMessage;
import com.sw.mes.yb.production.service.*;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.modelmapper.ModelMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.stream.Collectors;

import static com.sw.mes.base.global.GlobalSwitchNamespace.CODE_SWITCH;
import static com.sw.mes.base.global.GlobalSwitchNamespace.NAMESPACE_AUTOMATION;

/**
 * 物料操作 点击处理
 *
 * @author 李儒
 */
@Service
@Transactional
@Slf4j
public class MaterialOperationClickServiceImpl implements IBaseButtonHandler {

    @Autowired
    private EquipmentWorkHoursLogService equipmentWorkHoursLogService;

    @Autowired
    private LongCrystalService longCrystalService;
    @Autowired
    private AgainTaskService againTaskService;
    @Autowired
    private AgainTaskDetailService againTaskDetailService;
    @Autowired
    private LoadingTaskService loadingTaskService;
    @Autowired
    private PlanProcessingOrderService planProcessingOrderService;
    @Autowired
    private ProcessPathService processPathService;
    @Autowired
    private AgvDispatchService agvDispatchService;
    @Autowired
    private EquipmentService equipmentService;
    @Autowired
    private EapService eapService;
    @Autowired
    private NotificationService notificationService;

    @Autowired
    private MMcsInterfaceService mMcsInterfaceService;
    @Autowired
    private SapServer sapServer;
    @Autowired
    private BlastFurnaceDetailService blastFurnaceDetailService;
    @Autowired
    ModelMapper modelMapper;
    @Autowired
    StoreFeignClients storeFeignClients;
    @Autowired
    InputFurnaceDetailService inputFurnaceDetailService;

    @Autowired
    ReportWmsRecordService reportWmsRecordService;

    @Autowired
    GenerateReportWms generateReportWms;

    @Autowired
    DictionaryItemService dictionaryItemService;

    @Autowired
    private ReportSapWorkinghoursService sapWorkinghoursService;

    @Autowired
    private ProcessWorkingHoursService processWorkingHoursService;

    @Autowired
    private InputFurnaceBurdenService inputFurnaceBurdenService;

    @Autowired
    private ProductionScheduleService productionScheduleService;

    @Autowired
    private ReportSapWorkinghoursService reportSapWorkinghoursService;

    @Autowired
    private SysLogService sysLogService;

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

    @Autowired
    private InspectionRecordService inspectionRecordService;

    @Override
    public Object execute(ButtonClickDto dto) {

        if (dto.getButtonName().equals("取消叫料")) {
            String lotNo = dto.getLotNo();
            if (StringUtils.isBlank(lotNo)) {
                throw new RuntimeException("未获取到当前炉次号,请开炉后再次尝试");
            }

            String operationCause = (String) dto.getParams().get("operationCause");

            boolean isOpertor = false;
            AgainTask againTask = againTaskService.getByEquipmentAndStateLastTask(dto.getEquipmentCode(), dto.getLotNo(), AgainTaskDto.rawStatus_0);
            if (againTask == null) {
                LoadingTask loadingTask = loadingTaskService.getByEquipmentAndStateLastTask(dto.getEquipmentCode(), dto.getLotNo(), LoadingTaskDto.rawStatus_0);
                if (loadingTask != null) {
                    loadingTask.setRawStatus(LoadingTaskDto.rawStatus_2);
                    loadingTask.setOperationCause(operationCause);
                    loadingTask.setUserName(dto.getUserName());
                    loadingTask.setOperationTime(new Date());
                    loadingTaskService.saveOrUpdate(loadingTask);

//                    //下发生产任务接口
//            		mMcsInterfaceService.issueMoInterface(loadingTask);

                    isOpertor = true;
                }
            } else {
                againTask.setRawStatus(AgainTaskDto.rawStatus_2);
                againTask.setOperationCause(operationCause);
                againTask.setUserName(dto.getUserName());
                againTask.setOperationTime(new Date());
                againTaskService.saveOrUpdate(againTask);

                //下发生产任务接口
                //mMcsInterfaceService.issueMoInterface(againTask);

                isOpertor = true;
            }

            if (!isOpertor) {
                throw new RuntimeException("暂无可取消任务");
            }
            return "操作:取消叫料";
        }
        else if (dto.getButtonName().equals("生产退料")) {
            String lotNo = dto.getLotNo();
            if (StringUtils.isBlank(lotNo)) {
                throw new RuntimeException("未获取到当前炉次号,请开炉后再次尝试");
            }

            backTask(dto);

            return "操作:生产退料";
        } else if (dto.getButtonName().equals("重新叫料")) {
            String lotNo = dto.getLotNo();
            if (StringUtils.isBlank(lotNo)) {
                throw new RuntimeException("未获取到当前炉次号,请开炉后再次尝试");
            }
            try {
                repeatOpenTask(dto);
            }catch (Exception e){
                e.printStackTrace();
                throw new RuntimeException(e.getMessage());
            }
            return "操作:重新叫料";

        } else if ("产出确认".equals(dto.getButtonName())) {
            Long id = NumberUtil.Object2Long(dto.getParams().get("id"), null);
            if (id == null) {
                throw new RuntimeException("params参数中需要包含id字段(对应长单晶production_long_crystal.id)");
            }
            try {
                //对重量的格式做正确性校验
                String stringWeight = dto.getParams().get("weight").toString();
                isBigdecimal(stringWeight);

                BigDecimal weight = NumberUtil.Object2BigDecimal(dto.getParams().get("weight"));
                BigDecimal length = NumberUtil.Object2BigDecimal(dto.getParams().get("length"));
                Integer againNum = NumberUtil.Object2Integer(dto.getParams().get("againNum"), null);
                Integer crystalNum = NumberUtil.Object2Integer(dto.getParams().get("crystalNum"), null);
                Integer isDone = NumberUtil.Object2Integer(dto.getParams().get("isDone"), 0);
                Integer isCrystal = NumberUtil.Object2Integer(dto.getParams().get("isCrystal"), 1);  // 多晶：0, 单晶：1（默认）

                if (againNum != null) {
                    if (againNum < 0) {
                        throw new BusinessException("复投次数不能小于0");
                    }
                    if (againNum > 30) {
                        throw new BusinessException("复投次数不能大于30");
                    }
                }else {
                    throw new BusinessException("复投次数不能为空");
                }
                if (crystalNum != null) {
                    if (crystalNum < 1) {
                        throw new BusinessException("颗次不能小于1");
                    }
                    if (crystalNum > 30) {
                        throw new BusinessException("颗次不能大于30");
                    }
                }else {
                    throw new BusinessException("颗次不能为空");
                }

                String windUp = (String) dto.getParams().get("windUp");
                String closureIdentification = (String) dto.getParams().get("closureIdentification");
                LongCrystal longCrystal1 = longCrystalService.findBLotNoAndClosureIdentification(dto.getLotNo(), "W");
                if (StringUtils.isNotBlank(closureIdentification) && "W".equals(closureIdentification)) {
                    //卡控:一个炉次只能有一根完结尾
                    if (null != longCrystal1 && EnumValuesFactory.CrystalStatus.待确认.getKey() != longCrystal1.getCrystalStatus()) {
                        throw new RuntimeException(longCrystal1.getLotNo() + "炉次存在完结尾晶棒,编号为 :" + longCrystal1.getCrystalNo());
                    }
                }
                String crystalErrorLevelOne = (String) dto.getParams().get("crystalErrorLevelOne");
                crystalErrorLevelOne = crystalErrorLevelOne == null ? "" : crystalErrorLevelOne;
                String crystalErrorLevelTwo = (String) dto.getParams().get("crystalErrorLevelTwo");
                crystalErrorLevelTwo = crystalErrorLevelTwo == null ? "" : crystalErrorLevelTwo;
                LongCrystal longCrystal = longCrystalService.get(id);
                if (longCrystal == null) {
                    throw new RuntimeException("单晶id不存在");
                }
                if (longCrystal.getCrystalStatus() != EnumValuesFactory.CrystalStatus.待确认.getKey()) {
                    throw new RuntimeException("该单晶已确认，请重新获取数据");
                }

                if (isCrystal != null && isCrystal == 0){   // 多晶：0, 单晶：1
                    longCrystal.setIsCrystal(0);
                }else {
                    longCrystal.setIsCrystal(1);
                }

                //修改炉次工单的投次数，颗次计数
                LongCrystal longCrystalLotLast = longCrystalService.getLastCrystalNo(longCrystal.getEquipmentCode());
                if (dto.getParams().get("outputMode") == null && longCrystalLotLast != null && longCrystalLotLast.getId().equals(longCrystal.getId())) {
                    throw new BusinessException("请选择取段方式");
                }
                Integer outputMode = NumberUtil.Object2Integer(dto.getParams().get("outputMode"), 0);

                PlanProcessingOrder planProcessingOrder = planProcessingOrderService.get(longCrystal.getLotId());

                //迭代添加炉次一级异常信息
                String lotErrorLevelOne = planProcessingOrder.getLotErrorLevelOne();
                lotErrorLevelOne = lotErrorLevelOne == null ? "" : lotErrorLevelOne;
                if (!lotErrorLevelOne.contains(crystalErrorLevelOne)) {
                    lotErrorLevelOne += crystalErrorLevelOne + ",";
                }
                planProcessingOrder.setLotErrorLevelOne(lotErrorLevelOne);
                //设置当前晶棒一级异常信息
                longCrystal.setCrystalErrorLevelOne(lotErrorLevelOne);


                //迭代添加炉次二次级异常信息
                String lotErrorLevelTwo = planProcessingOrder.getLotErrorLevelTwo();
                lotErrorLevelTwo = lotErrorLevelTwo == null ? "" : lotErrorLevelTwo;
                if (!lotErrorLevelTwo.contains(crystalErrorLevelTwo)) {
                    lotErrorLevelTwo += crystalErrorLevelTwo + ",";
                }
                planProcessingOrder.setLotErrorLevelTwo(lotErrorLevelTwo);
                //设置当前晶棒二级异常信息
                longCrystal.setCrystalErrorLevelTwo(lotErrorLevelTwo);

                //设置已确认异常
                longCrystal.setCrystalStatus(EnumValuesFactory.CrystalStatus.未送验.getKey());

                longCrystal.setWeight(weight);
                longCrystal.setLength(length);
                longCrystal.setAgainNum(againNum);
                longCrystal.setCrystalNum(crystalNum);
                longCrystal.setWindUp(windUp);
                longCrystal.setOutputConfirmationTime(new Date());
                if(StringUtils.isEmpty(closureIdentification)){
                    longCrystal.setClosureIdentification("无");
                } else {
                    longCrystal.setClosureIdentification(closureIdentification);
                }
                //longCrystal.setIsDone(isDone);

                // 检查复投次数录入是否正确
                AgainTask againTask = againTaskService.findCompletedTopByLotNo(longCrystal.getLotNo());
                if (GlobalSwitch.enable(GlobalSwitchNamespace.NAMESPACE_YB_CHECK, "QDJJCheckAgainNum", false)){
                    if (ObjectUtils.isEmpty(againTask)) {
                        throw new RuntimeException("未查询到炉次【"+longCrystal.getLotNo()+"】存在完成状态的复投任务");
                    }
                    if (againTask.getAgainNum().compareTo(longCrystal.getAgainNum()) != 0) {
                        throw new RuntimeException("最近一次的加料次数为"+againTask.getAgainNum()+"，请确认产出的加料次数是否符合产出平衡逻辑！");
                    }
                }

                // 检查颗次是否自增
                if (GlobalSwitch.enable(GlobalSwitchNamespace.NAMESPACE_YB_CHECK, "checkCrystalNum", false)){
                    LongCrystal lastCrystal = longCrystalService.findLastRightByLotNoAndAgainNum(longCrystal.getLotNo(), longCrystal.getAgainNum(), longCrystal.getId());
                    int lastRightCrystalNum = 1;
                    if (!ObjectUtils.isEmpty(lastCrystal)){
                        lastRightCrystalNum = lastCrystal.getCrystalNum() + 1;
                    }
                    if (lastRightCrystalNum != crystalNum){
                        throw new RuntimeException("根据颗次自增检查，当前晶棒颗次应为【"+lastRightCrystalNum+"】,请检查确认！");
                    }
                }

                // 投料状态卡控
                if (GlobalSwitch.enable(GlobalSwitchNamespace.NAMESPACE_YB_CHECK, "checkInputMaterial", false)){
                    // 是否存在未确认的投料
                    List<InputFurnaceBurden> taskList1 = inputFurnaceBurdenService.findTask(longCrystal.getLotNo(), longCrystal.getAgainNum(), 0);
                    if (!CollectionUtils.isEmpty(taskList1)) {
                        throw new RuntimeException("加料次数"+longCrystal.getAgainNum()+"存在未确认的加料信息，请先在IPC中确认投料");
                    }
                    // 是否存在未加料的情况
                    List<InputFurnaceBurden> taskList2 = inputFurnaceBurdenService.findTask(longCrystal.getLotNo(), longCrystal.getAgainNum(), 1);
                    if (CollectionUtils.isEmpty(taskList2)) {
                        throw new RuntimeException("加料次数"+longCrystal.getAgainNum()+"无确认完成的加料信息，请确认是否完成配料或灌料");
                    }
                }

                // 检查投料，晶棒完结标示是否一致
                if (GlobalSwitch.enable(GlobalSwitchNamespace.NAMESPACE_YB_CHECK, "checkWindUp", false)){
                    if ((againTask.getIsFillEnd() == 1 && !"W".equals(longCrystal.getWindUp()))
                        || (againTask.getIsFillEnd() == 0 && "W".equals(longCrystal.getWindUp()))){
                        throw new RuntimeException("产出晶棒与对应复投任务的【完结标识】不一致，请检查确认");
                    }
                }

                // 检查上次复投产出状态
                if (GlobalSwitch.enable(GlobalSwitchNamespace.NAMESPACE_YB_CHECK, "QDJJCheckLastTimeOutPut", false)
                        && longCrystal.getAgainNum() >= 2
                        && againTask.getOutputCrystal() != null && againTask.getOutputCrystal()){
                    // 获取上次投料产出
                    Integer lastAgainNum = longCrystal.getAgainNum() - 1;
                    List<LongCrystal> LastCrystalList = longCrystalService.findByLotNoAndAgainNum(longCrystal.getLotNo(), lastAgainNum);
                    if (CollectionUtils.isEmpty(LastCrystalList)) {
                        throw new RuntimeException("上次（第"+lastAgainNum+"次）加料没有晶棒产出，请确认后再进行本次产出确认！");
                    }
                    boolean isConfirmAll = true;
                    for (LongCrystal crystal : LastCrystalList) {
                        if(crystal.getCrystalStatus() == EnumValuesFactory.CrystalStatus.待确认.getKey()){
                            isConfirmAll = false;
                            break;
                        }
                    }
                    if (!isConfirmAll) {
                        throw new RuntimeException("上次（第"+lastAgainNum+"次）加料产出的晶棒有未确认状态，请先确认产出！");
                    }
                }

                //保存炉次异常信息
                planProcessingOrderService.saveOrUpdate(planProcessingOrder);
                //调用单晶编号生成方法,自动保存数据
                eapService.generateCrystalNo(longCrystal, outputMode, windUp);

                // 如果不存在未确认晶棒，且加工工单表已关闭，则关闭排程
                List<LongCrystal> longCrystalList = longCrystalService.findUnconfirmedByLotNo(longCrystal.getLotNo());
                if (planProcessingOrder.getStatus() == EnumValuesFactory.PlanProcessingOrderStatus.加工完成.getKey()
                    && CollectionUtils.isEmpty(longCrystalList)){
                    ProductionSchedule schedule = productionScheduleService.findByLotNo(longCrystal.getLotNo());
                    schedule.setStatus(EnumValuesServer.ProductionScheduleStatus.已完成.getKey());
                    schedule.setStatusInfo("加工工单已关闭，该炉次无未确认产出晶棒");
                    schedule.setCloseTime(new Date());
                    productionScheduleService.saveOrUpdate(schedule);
                }


                //匹配订单
                try {
                    longCrystalService.completionLongCrystalOrder(longCrystal.getLotNo(), longCrystal.getCrystalNo(), new Date(), longCrystal.getMaxDiam(), longCrystal.getMinDiam(), true);
                } catch (Exception e) {
                    e.printStackTrace();
                }

                //增加产量公式
                sapServer.addWorkHour(longCrystal, planProcessingOrder);

//                // SAP工时报工
//                try {
//                    SwitchConfig config = GlobalSwitch.switchConfig(CODE_SWITCH, "crystalWorkHour", false);
//                    if(config.isEnable()){
//                        newReportSapLongCrystalHours(longCrystal);
//                    } else {
//                        //原来的方法
//                        reportSapLongCrystalHours(longCrystal);
//                    }
//                } catch (Exception e) {
//                    e.printStackTrace();
//                    log.info("单晶工时：" + e.getMessage());
//                }

                //发送取晶任务(包含毛棒信息下发)
                try {
                    SwitchConfig config = GlobalSwitch.switchConfig(NAMESPACE_AUTOMATION, "autoCrystal", false);
                    if(config.isEnable()){
                        String autoValue = config.getValue();
                        boolean auto = false;
                        if ("1".equals(autoValue)) {
                            auto = true;
                        } else {
                            List<String> list = Arrays.asList(autoValue.split(","));
                            if (list.contains(longCrystal.getSeries())) {
                                auto = true;
                            }
                        }
                        if(auto) generateAutomaticCrystalFetchingTask(longCrystal);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    log.info("取晶任务下发异常：" + e.getMessage());
                }


            } catch (Exception e) {
                e.printStackTrace();
                //手动回滚事务
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                throw new RuntimeException(e.getMessage());
            }
            if (StringUtils.isBlank((String) dto.getParams().get("crystalErrorLevelTwo"))
                    && StringUtils.isBlank((String) dto.getParams().get("crystalErrorLevelOne"))){
                return "操作:确认产出";
            }else {
                return "操作:产出异常";
            }

        }
        return "未知操作:" + dto.getButtonName();
    }

    /**
     * 上报SAP单晶工时消耗
     * @param longCrystal
     */
    private void reportSapLongCrystalHours(LongCrystal longCrystal){
        List<LongCrystal> crystalList = longCrystalService.findByLotNo(longCrystal.getLotNo());
        ReportSapWorkinghours reportSap = new ReportSapWorkinghours();

        reportSap.setProductionOrderId(longCrystal.getOrderNo());   // 生产订单
        reportSap.setPlant("5041");     // 工厂
        reportSap.setWorkcenterId(longCrystal.getSeries());   // 订单工作中心
        reportSap.setCnfTimeUom("H");
        LocalDateTime start = null;
        LocalDateTime stop = LocalDateTime.ofInstant(crystalList.get(0).getGmtCreate().toInstant(), ZoneId.systemDefault());
        if (crystalList.size() == 1){    // 首棒
            // 查询
            ProcessWorkingHours hours = processWorkingHoursService.findByLotNoAndStep(longCrystal.getLotNo(), "抽真空");
            if (hours != null){
                start = LocalDateTime.ofInstant(hours.getStartTime().toInstant(), ZoneId.systemDefault());
            }
        }else if (crystalList.size() >= 2){  // 非首棒
            start = LocalDateTime.ofInstant(crystalList.get(1).getGmtCreate().toInstant(), ZoneId.systemDefault());
        }

        // 计算工时
        if (start != null && start.compareTo(stop) < 0){
            long minutesDiff = Duration.between(start, stop).toMinutes();
            double hoursDiff = (double)minutesDiff / 60;
            reportSap.setCnfTime(String.format("%.2f", hoursDiff));

            // 保存工时
            sapWorkinghoursService.saveOrUpdate(reportSap);
        }

    }

//    /**
//     * 上报SAP单晶工时消耗-New
//     * @param longCrystal
//     */
//    public void newReportSapLongCrystalHours(LongCrystal longCrystal){
//
//        ReportSapWorkinghours reportSap = new ReportSapWorkinghours();
//        // 设置保留两位小数
//        DecimalFormat decimalFormat = new DecimalFormat("#.##");
//        // 生产订单
//        reportSap.setProductionOrderId(longCrystal.getOrderNo());
//        // 工厂
//        reportSap.setPlant("5041");
//        // 订单工作中心
//        reportSap.setWorkcenterId(longCrystal.getSeries());
//        reportSap.setCnfTimeUom("H");
//        Long startTime = null;
//
//        List<LongCrystal> crystalList = longCrystalService.findByLotNo(longCrystal.getLotNo());
//        if(null != crystalList && crystalList.size() > 0){
//            LongCrystal longCrystal1 = crystalList.get(crystalList.size() - 1);
//            //首棒
//            if(longCrystal.getId().equals(longCrystal1.getId())){
//                // 查询
//                startTime = gettimeLong(longCrystal, startTime);
//                double result = (double) (longCrystal.getGmtCreate().getTime() - startTime)/ 3600000;
//                String formattedResult = decimalFormat.format(result);
//                reportSap.setCnfTime(formattedResult);
//                sapWorkinghoursService.saveOrUpdate(reportSap);
//                return;
//            }
//
//            //非首棒
//            LongCrystal longCrystal2 = crystalList.get(1);
//            double result = (double) (longCrystal.getGmtCreate().getTime() - longCrystal2.getGmtCreate().getTime()) / 3600000;
//            String formattedResult = decimalFormat.format(result);
//            reportSap.setCnfTime(formattedResult);
//            //todo 编号没有怎么弄
//            reportSap.setProcName("单晶工时");
//            reportSap.setRemark(longCrystal.getCrystalNo());
//            reportSap.setCnfDate(new Date());
//            ReportSapWorkinghours byCrystalNoAndBwart = reportSapWorkinghoursService.findByRemarkAndProcName(longCrystal.getCrystalNo(), "单晶工时");
//            if (null != byCrystalNoAndBwart) {
//                SysLog syslog = new SysLog();
//                syslog.setCreateTime(new Date());
//                syslog.setType("info");
//                syslog.setCreateUserName("SYSTEM");
//                syslog.setContent(JSON.toJSONString(reportSap));
//                syslog.setResult("单晶工时：晶棒【" + longCrystal.getCrystalNo() + "】已经报过工时");
//                syslog.setMethodName("handleReportConsumption()");
//                syslog.setServerAddr("");
//                syslog.setReqType("HTTP");
//                syslog.setReqIp(IpUtils.getLocalIP());
//                sysLogService.save(syslog);
//                return;
//            } else {
//                reportSapWorkinghoursService.saveOrUpdate(reportSap);
//            }
//            sapWorkinghoursService.saveOrUpdate(reportSap);
//        }
//    }
//
//    private Long gettimeLong(LongCrystal longCrystal, Long startTime) {
//        ProcessWorkingHours hours;
//        hours = processWorkingHoursService.findByLotNoAndStep(longCrystal.getLotNo(), "抽真空");
//        if(null == hours){
//            hours = processWorkingHoursService.findByLotNoAndStep(longCrystal.getLotNo(), "熔料工时");
//        }
//        if(null == hours){
//            List<LoadingTask> byLotNo = loadingTaskService.findByLotNo(longCrystal.getLotNo());
//            if(null != byLotNo && byLotNo.size() > 0){
//                startTime = byLotNo.get(0).getConfirmTime().getTime();
//            }
//        }
//        if (hours != null){
//            startTime = hours.getStartTime().getTime();
//        }
//        return startTime;
//    }

    /**
     * 校验重量参数能否转化为bigDecimal
     * @param bigDecimalString
     */
    private void isBigdecimal(String bigDecimalString){
        if (null == bigDecimalString || bigDecimalString.trim().length() == 0){
            throw new RuntimeException("重量参数不能为空！");
        }
        if (bigDecimalString.contains(" ")){
            throw new RuntimeException("重量参数格式不正确！");
        }
        char[] chars = bigDecimalString.toCharArray();
        int sz = chars.length;
        int i = (chars[0] == '-') ? 1 : 0;
        if(i == sz)
            throw new RuntimeException("重量参数格式不正确！");

        if(chars[i] == '.')
            throw new RuntimeException("重量参数格式不正确！");//除了负号，第一位不能为'小数点'
        boolean radixPoint = false;
        for(; i < sz; i++){
            if(chars[i] == '.'){
                if(radixPoint)
                    throw new RuntimeException("重量参数格式不正确！");
                radixPoint = true;
            }else if(!(chars[i] >= '0' && chars[i] <= '9')){
                throw new RuntimeException("重量参数格式不正确！");
            }
        }
    }



    private ReportWmsRecordDto buildReportWmsRecordDto(LongCrystal longCrystal) {
        ReportWmsRecordDto recordDto = new ReportWmsRecordDto();
        recordDto.setNo(longCrystal.getCrystalNo());
        recordDto.setType(1);
        recordDto.setCreateTime(new Date());
        recordDto.setCreateUser(BaseContextHandler.getUsername());
        recordDto.setPlanNo(generateReportWms.getPlanNo(recordDto.getType()));
        recordDto.setMaterialNo(longCrystal.getProductCode());
        recordDto.setMaterialQty(longCrystal.getWeight());
        recordDto.setSpecification(longCrystal.getSpecs());
        recordDto.setUnit("kg");
        recordDto.setLength(longCrystal.getLength());
        recordDto.setWidth(longCrystal.getWeight());
        recordDto.setRemark("");

        return recordDto;
    }

    public static void sendAgainTaskDetailMessage(AgainTaskDetail detail, NotificationService notificationService) {
        AgainTaskDetailMessage message = new AgainTaskDetailMessage();
        message.setArea(detail.getArea());
        message.setEquipmentCode(detail.getEquipmentCode());
        message.setId(detail.getId());
        message.setLotNo(detail.getLotNo());
        message.setSeries(detail.getSeries());
        notificationService.sendNotification(message);
    }

    private void backTask(ButtonClickDto dto) {
        String operationCause = (String) dto.getParams().get("reason");//退料
        //String weight = (String) dto.getParams().get("weight");
        Boolean isUnusual = Boolean.valueOf(dto.getParams().get("isUnusual").toString());

        //最新灌料完成任务
        if (dto.getDetailTaskId() == null) {//配料
            List<String> steNames = new ArrayList<String>();//工艺状态 不允许退料范围
            steNames.add(EAPUtils.stepMapping.get(1));//抽真空
            List<ProcessPath> processPath = processPathService.findByEquipmentCodeAndLotNoAndStepNameIn(dto.getEquipmentCode(), dto.getLotNo(), steNames);
            if (processPath.size() == 0) {
                LoadingTask loadingTask = loadingTaskService.getByEquipmentAndSuccessLastTask(dto.getEquipmentCode(), dto.getLotNo());
                if (loadingTask != null) {

                    if (loadingTask.getRawStatus().equals(LoadingTaskDto.rawStatus_3) || loadingTask.getRawStatus().equals(LoadingTaskDto.rawStatus_4)) {
                        loadingTask.setRawStatus(LoadingTaskDto.rawStatus_5);

                        loadingTask.setOperationCause(operationCause);
                        loadingTask.setUserName(dto.getUserName());
                        loadingTask.setOperationTime(new Date());

                        loadingTaskService.saveOrUpdate(loadingTask);
                        //生成退料任务审核单据
                        List<BlastFurnaceDetail> blastFurnaceDetails = blastFurnaceDetailService.getBlastFurnaceDetailList(loadingTask.getId());
                        List<BlastFurnaceDetailDto> blastFurnaceDetailDto = blastFurnaceDetails.stream().map(entity-> modelMapper.map(entity,BlastFurnaceDetailDto.class)).collect(Collectors.toList());
                        String equipmentCode = loadingTask.getEquipmentCode();
                        Integer receiverCode = BaseContextHandler.getUserID();
                        String  receiverName = BaseContextHandler.getUsername();
                        StoreOperatorDto storeOperatorDto = new StoreOperatorDto();
                        List<StoreOperatorDetailDto> storeOperatorDetailDtos = new ArrayList<>();
                        for(BlastFurnaceDetailDto detailDto:blastFurnaceDetailDto){
                            StoreOperatorDetailDto storeOperatorDetailDto = new StoreOperatorDetailDto();
                            String batchNo = detailDto.getBatchNo();
                            String materialCode = detailDto.getMaterialCode();
                            BigDecimal weightD;
                            if(detailDto.getMaterialName().contains("合金")){
                                weightD = Optional.ofNullable(detailDto.getWeight()).orElse(new BigDecimal("0"));
                            }else if(detailDto.getMaterialName().contains("坩埚")){
                                weightD = new BigDecimal("1");
                            }else {
//                                Integer bucketForty = Optional.ofNullable(detailDto.getBucketForty()).orElse(0);
//                                Integer bucketTen = Optional.ofNullable(detailDto.getBucketTen()).orElse(0);
//                                Integer weight1 = bucketForty*40+bucketTen*10;
//                                weightD = new BigDecimal(Integer.valueOf(weight1));
                                weightD = Optional.ofNullable(detailDto.getWeight()).orElse(new BigDecimal("0"));
                            }
                            String unit = detailDto.getUnit();
                            //String supplierName = dto.getSupplierName();
                            //storeOperatorDetailDto.setSupplierName(supplierName);
                            //String productCode = detailDto.getProductCode();
                            Long id = detailDto.getId();
                            Integer materialModelId = null;
                            if(id!= null){
                                materialModelId = Integer.valueOf(id.toString());
                            }
                            String materialName = detailDto.getMaterialName();
                            storeOperatorDetailDto.setMaterialModelId(materialModelId);
                            storeOperatorDetailDto.setMaterialModelName(materialName);
                            storeOperatorDetailDto.setBatchNo(batchNo);
                            storeOperatorDetailDto.setNum(weightD);
                            storeOperatorDetailDto.setUnitName(unit);
                            storeOperatorDetailDto.setMaterialModelCode(materialCode);
                            storeOperatorDetailDto.setOutReason(operationCause);
                            storeOperatorDetailDto.setSupplierName(detailDto.getFactoryBrand());
                            storeOperatorDetailDtos.add(storeOperatorDetailDto);
                        }
                        storeOperatorDto.setDeviceNo(equipmentCode);
                        storeOperatorDto.setOrderNo(loadingTask.getId().toString());
                        storeOperatorDto.setRemark(blastFurnaceDetailDto.get(0).getRemark());
                        storeOperatorDto.setReceiverCode(receiverCode.toString());
                        storeOperatorDto.setReceiverName(receiverName);
                        storeOperatorDto.setStoreBusinessTypeEnum(StoreBusinessTypeEnum.原料退线);
                        //备件下机/原料退线边仓=退库入库;线边仓领料=正常入库；热场退库入库=热场下机复评
                        storeOperatorDto.setStoreOperatorTypeEnum(StoreOperatorTypeEnum.原料退线边仓);
                        storeOperatorDto.setBusinessData(storeOperatorDetailDtos);
                        //工控机配料退料  线边仓交互
                        //需要审核退料
                		Result<String> result = storeFeignClients.inputStoreBill(storeOperatorDto);
                        if(!result.getCode().equals(ResultCode.SUCCESS.getCode())){
                            throw new RuntimeException(result.getMessage());
                        }
//			    		//下发生产任务接口
//	            		mMcsInterfaceService.issueMoInterface(loadingTask);
                    } else {
                        throw new RuntimeException("装料任务非取消状态无法重复叫料");
                    }

                    if (isUnusual) {
                        //退料呼叫
                        try {
                            Equipment equipment = equipmentService.findByCode(dto.getEquipmentCode());
                            String targetPoint = EnumValuesAgv.EquipmentAreaBLHCK.getText(equipment.getArea());

                            AgvCallDto agvCall = new AgvCallDto();
                            agvCall.setKeyword(EnumValuesAgv.AGVKeyword.生产退料.getValue());//关键字 根据配置中的信息固定写入  : 圆棒送验
                            agvCall.setStartPoint(dto.getEquipmentCode());
                            agvCall.setTargetPoint(targetPoint);
                            agvCall.setWeightId(loadingTask.getWeigthId() + "");
                            agvCall.setRecipeId(loadingTask.getRecipeId() + "");
                            agvCall.setFrockType("2");
                            //其他信息可根据配置信息自动填充
                            String taskCode = agvDispatchService.callAgv(agvCall);
                        } catch (Exception e) {
                            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                            throw new RuntimeException(e.getMessage());
                        }
                    }
                }
            }
        } else {
            AgainTaskDetail detail = againTaskDetailService.get(Long.valueOf(dto.getDetailTaskId()));
            if (detail != null) {
                if (detail.getRawStatus().equals(AgainTaskDetailDto.rawStatus_3) || detail.getRawStatus().equals(AgainTaskDetailDto.rawStatus_4) || detail.getRawStatus().equals(AgainTaskDetailDto.rawStatus_7)) {
                    detail.setRawStatus(LoadingTaskDto.rawStatus_5);

                    detail.setOperationCause(operationCause);
                    detail.setUserName(dto.getUserName());
                    detail.setOperationTime(new Date());

                    againTaskDetailService.saveOrUpdate(detail);

                    List<InputFurnaceDetail> inputFurnaceDetails = inputFurnaceDetailService.findByAgainTaskDetailId(detail.getId());
                    List<InputFurnaceDetailDto> detailDto = inputFurnaceDetails.stream().map(entity->modelMapper.map(entity,InputFurnaceDetailDto.class)).collect(Collectors.toList());
                    StoreOperatorDto storeOperatorDto = new StoreOperatorDto();
                    //设备号
                    String equipmentCode = detail.getEquipmentCode();
                    Integer receiverCode = BaseContextHandler.getUserID();
                    String  receiverName = BaseContextHandler.getUsername();
                    List<StoreOperatorDetailDto> storeOperatorDetailDtos = new ArrayList<>();
                    for (InputFurnaceDetailDto inputFurnaceDetailDto : detailDto) {
                        //组装扣减库存信息
                        StoreOperatorDetailDto storeOperatorDetailDto = new StoreOperatorDetailDto();
                        String batchNo = inputFurnaceDetailDto.getBatchNo();
                        String materialCode = inputFurnaceDetailDto.getMaterialCode();
                        BigDecimal weightD;
                        if(inputFurnaceDetailDto.getMaterialName().contains("合金")){
                            weightD = Optional.ofNullable(inputFurnaceDetailDto.getWeight()).orElse(new BigDecimal("0"));
                        }else{
//                          Integer bucketForty = Optional.ofNullable(inputFurnaceDetailDto.getBucketForty()).orElse(0);
//                          Integer bucketTen = Optional.ofNullable(inputFurnaceDetailDto.getBucketTen()).orElse(0);
//                          Integer weight1 = bucketForty*40+bucketTen*10;
//                          weightD = new BigDecimal(Integer.valueOf(weight1));
                            weightD = Optional.ofNullable(inputFurnaceDetailDto.getWeight()).orElse(new BigDecimal("0"));
                        }
                        //String supplierName = inputFurnaceDetailDto.getSupplierName();
                        String unit = inputFurnaceDetailDto.getUnit();
                        //String productCode = inputFurnaceDetailDto.getProductCode();
                        Integer materialModelId = null;
                        Long id = inputFurnaceDetailDto.getId();
                        if(id!= null){
                            materialModelId = Integer.valueOf(id.toString());
                        }
                        String materialName = inputFurnaceDetailDto.getMaterialName();
                        storeOperatorDetailDto.setMaterialModelId(materialModelId);
                        storeOperatorDetailDto.setMaterialModelName(materialName);
                        storeOperatorDetailDto.setBatchNo(batchNo);
                        storeOperatorDetailDto.setNum(weightD);
                        storeOperatorDetailDto.setUnitName(unit);
                        storeOperatorDetailDto.setMaterialModelCode(materialCode);
                        storeOperatorDetailDto.setOutReason(operationCause);
                        storeOperatorDetailDto.setSupplierName(inputFurnaceDetailDto.getFactoryBrand());
                        storeOperatorDetailDtos.add(storeOperatorDetailDto);
                    }
                    storeOperatorDto.setDeviceNo(equipmentCode);
                    storeOperatorDto.setOrderNo(detail.getId().toString());
                    storeOperatorDto.setRemark(detailDto.get(0).getRemark());
                    storeOperatorDto.setReceiverCode(receiverCode.toString());
                    storeOperatorDto.setReceiverName(receiverName);
                    storeOperatorDto.setStoreBusinessTypeEnum(StoreBusinessTypeEnum.原料退线);
                    //备件下机/原料退线边仓=退库入库;线边仓领料=正常入库；热场退库入库=热场下机复评
                    storeOperatorDto.setStoreOperatorTypeEnum(StoreOperatorTypeEnum.原料退线边仓);
                    storeOperatorDto.setBusinessData(storeOperatorDetailDtos);
                    //工控机灌料退料 线边仓交互
                    //需要审核退料
            		Result<String> result = storeFeignClients.inputStoreBill(storeOperatorDto);
                    if(!result.getCode().equals(ResultCode.SUCCESS.getCode())){
                        throw new RuntimeException(result.getMessage());
                    }
                    //发送MQTT通知
                    AgainTaskDetailMessage message = new AgainTaskDetailMessage();
                    message.setArea(detail.getArea());
                    message.setEquipmentCode(detail.getEquipmentCode());
                    message.setId(detail.getId());
                    message.setLotNo(detail.getLotNo());
                    message.setSeries(detail.getSeries());
                    notificationService.sendNotification(message);

                    if (isUnusual) {
                        //退料呼叫
                        try {
                            Equipment equipment = equipmentService.findByCode(dto.getEquipmentCode());
                            String targetPoint = EnumValuesAgv.EquipmentAreaBLHCK.getText(equipment.getArea());

                            AgvCallDto agvCall = new AgvCallDto();
                            agvCall.setKeyword(EnumValuesAgv.AGVKeyword.生产退料.getValue());//关键字 根据配置中的信息固定写入  : 圆棒送验
                            agvCall.setStartPoint(dto.getEquipmentCode());
                            agvCall.setTargetPoint(targetPoint);
                            agvCall.setWeightId(detail.getWeigthId() + "");
                            agvCall.setRecipeId(detail.getRecipeId() + "");
                            agvCall.setFrockType("1");
                            //其他信息可根据配置信息自动填充
                            String taskCode = agvDispatchService.callAgv(agvCall);
                        } catch (Exception e) {
                            throw new RuntimeException(e.getMessage());
                        }
                    }
                } else {
                    throw new RuntimeException("灌料任务非取消状态无法重复叫料");
                }
            }
        }
    }

    private void cancelTask(ButtonClickDto dto) {
        String operationCause = (String) dto.getParams().get("operationCause");

        if (dto.getAgainTaskId() == null) {
            LoadingTask loadingTask = loadingTaskService.getByEquipmentAndStateLastTask(dto.getEquipmentCode(), dto.getLotNo(), LoadingTaskDto.rawStatus_0);
            if (loadingTask != null) {
                if (loadingTask.getRawStatus().equals(LoadingTaskDto.rawStatus_0)) {
                    loadingTask.setRawStatus(LoadingTaskDto.rawStatus_2);
                    loadingTask.setOperationCause(operationCause);
                    loadingTask.setUserName(dto.getUserName());
                    loadingTask.setOperationTime(new Date());

                    loadingTaskService.saveOrUpdate(loadingTask);

//		    		//下发生产任务接口
//            		mMcsInterfaceService.issueMoInterface(loadingTask);
                } else {
                    throw new RuntimeException("装料任务非新建状态无法取消");
                }
            }
        } else {
            AgainTask againTask = againTaskService.get(dto.getAgainTaskId());
            if (againTask != null) {
                if (againTask.getRawStatus().equals(AgainTaskDto.rawStatus_0)) {
                    againTask.setRawStatus(AgainTaskDto.rawStatus_2);
                    againTask.setOperationCause(operationCause);
                    againTask.setUserName(dto.getUserName());
                    againTask.setOperationTime(new Date());
                    againTaskService.saveOrUpdate(againTask);

                    //下发生产任务接口
                    //mMcsInterfaceService.issueMoInterface(againTask);
                } else {
                    throw new RuntimeException("复投任务非新建状态不能取消此任务");
                }
            }
        }
    }

    private void repeatOpenTask(ButtonClickDto dto) {
        if (dto.getDetailTaskId() == null) {
            if (dto.getAgainTaskId() == null) {
                LoadingTask loadingTask = loadingTaskService.getByEquipmentAndSuccessLastTask(dto.getEquipmentCode(), dto.getLotNo());
               if(null == loadingTask){
                   throw new RuntimeException("当前炉次无最近成功的配料任务！");
               }
                if (loadingTask.getRawStatus().equals(LoadingTaskDto.rawStatus_2) || loadingTask.getRawStatus().equals(LoadingTaskDto.rawStatus_5)) {
                    //验证是否已重新叫料
                    boolean isDoubleTask = doubleTaskValidate(loadingTask);
                    if (isDoubleTask) {
                        throw new RuntimeException("相同炉次已存在叫料任务");
                    }

                    //创建新任务
                    LoadingTask newTask = new LoadingTask(loadingTask, LoadingTaskDto.rawStatus_0);
                    loadingTaskService.saveOrUpdate(newTask);

//		    		//下发生产任务接口
//		    		mMcsInterfaceService.issueMoInterface(newTask);

                } else {
                    throw new RuntimeException("非取消状态无法重复叫料");
                }
            } else {
                AgainTask againTask = againTaskService.get(Long.valueOf(dto.getAgainTaskId()));
                if (againTask.getRawStatus().equals(AgainTaskDto.rawStatus_2) || againTask.getRawStatus().equals(AgainTaskDto.rawStatus_5)) {

                    //验证是否已重新叫料
                    boolean isDoubleTask = doubleTaskValidate(againTask);
                    if (isDoubleTask) {
                        throw new RuntimeException("相同炉次已存在复投叫料任务");
                    }

                    //创建新任务
                    AgainTask newTask = new AgainTask(againTask, AgainTaskDto.rawStatus_0);
                    newTask.setUserName(BaseContextHandler.getUsername());
                    againTaskService.saveOrUpdate(newTask);

                    //下发生产任务接口
                    //mMcsInterfaceService.issueMoInterface(newTask);

                    //发送MQTT通知
                    AgainTaskMessage message = new AgainTaskMessage();
                    message.setArea(newTask.getArea());
                    message.setEquipmentCode(newTask.getEquipmentCode());
                    message.setId(newTask.getId());
                    message.setLotNo(newTask.getLotNo());
                    message.setSeries(newTask.getSeries());
                    notificationService.sendNotification(message);

                } else {
                    throw new RuntimeException("复投任务非取消状态无法重复叫料");
                }
            }
        } else {
            AgainTaskDetail detail = againTaskDetailService.get(Long.valueOf(dto.getDetailTaskId()));
            if (detail.getRawStatus().equals(AgainTaskDetailDto.rawStatus_2) || detail.getRawStatus().equals(AgainTaskDetailDto.rawStatus_5)) {

                //验证是否已重新叫料
                boolean isDoubleTask = doubleTaskValidate(detail);
                if (isDoubleTask) {
                    throw new RuntimeException("相同炉次同一桶已存在灌料叫料任务");
                }

                AgainTaskDetail newTask = new AgainTaskDetail(detail, AgainTaskDetailDto.rawStatus_0);
                againTaskDetailService.saveOrUpdate(newTask);

                //复投任务
                AgainTask againTask = againTaskService.get(detail.getAgainTaskId());
                if (againTask.getRawStatus().equals(AgainTaskDto.rawStatus_4) || againTask.getRawStatus().equals(AgainTaskDto.rawStatus_3)) {
                    againTask.setRawStatus(AgainTaskDto.rawStatus_1);
                }
                againTaskService.saveOrUpdate(againTask);

                // 修改下次灌料任务的前次任务ID
                List<AgainTaskDetail> nextTaskDetailList = againTaskDetailService.findByCarrierSort(detail.getAgainTaskId(), detail.getAgainNum(), (detail.getCarrierSort() + 1));
                if (!CollectionUtils.isEmpty(nextTaskDetailList)){
                    for (AgainTaskDetail nextTaskDetail : nextTaskDetailList) {
                        nextTaskDetail.setPreDetailId(newTask.getId());
                    }
                    againTaskDetailService.saveAll(nextTaskDetailList);
                }

                //下发生产任务接口
                //mMcsInterfaceService.issueMoInterface(againTask);

                //发送MQTT通知
                AgainTaskDetailMessage message = new AgainTaskDetailMessage();
                message.setArea(newTask.getArea());
                message.setEquipmentCode(newTask.getEquipmentCode());
                message.setId(newTask.getId());
                message.setLotNo(newTask.getLotNo());
                message.setSeries(newTask.getSeries());
                notificationService.sendNotification(message);

            } else {
                throw new RuntimeException("非取消状态无法重复叫料");
            }
        }


        if (dto.getAgainTaskId() == null) {

        } else {
            AgainTask againTask = againTaskService.get(dto.getAgainTaskId());
            //验证是否已重新叫料
            boolean isDoubleTask = doubleTaskValidate(againTask);
            if (isDoubleTask) {
                throw new RuntimeException("相同炉次已存在叫料任务");
            }

            //创建新任务
            AgainTask newTask = new AgainTask(againTask, AgainTaskDto.rawStatus_0);
            newTask.setUserName(dto.getUserName());
            againTaskService.saveOrUpdate(newTask);

            //下发生产任务接口
            //mMcsInterfaceService.issueMoInterface(newTask);

            //发送MQTT通知
            AgainTaskMessage message = new AgainTaskMessage();
            message.setArea(newTask.getArea());
            message.setEquipmentCode(newTask.getEquipmentCode());
            message.setId(newTask.getId());
            message.setLotNo(newTask.getLotNo());
            message.setSeries(newTask.getSeries());
            notificationService.sendNotification(message);
        }
    }

    @Override
    public void writeWorkHours(ButtonClickDto dto) {
        if (ButtonType.isCalculationWorkHours(dto.getButtonName())) {
            EquipmentWorkHoursLog log = new EquipmentWorkHoursLog();
            BeanUtil.copyProperties(dto, log);


            String changePath = "";

            //获取上次操作
            EquipmentWorkHoursLog preLog = equipmentWorkHoursLogService.getByEquipmentCodeLastOperation(dto.getEquipmentCode());
            if (preLog != null) {
                changePath = preLog.getButtonName();
                log.setStartTime(preLog.getEndTime());
                log.setWorkStep(ButtonType.getType(preLog.getButtonName()));
            }

            changePath = changePath + "->" + dto.getButtonName();

            log.setChangePath(changePath);
            log.setEndTime(new Date());

            if (log.getStartTime() != null && log.getEndTime() != null) {
                log.setTimeLong(log.getEndTime().getTime() - log.getStartTime().getTime());
            } else {
                log.setTimeLong(0L);
            }

            equipmentWorkHoursLogService.saveOrUpdate(log);
        }
    }


    /**
     * 多次叫料验证
     **/
    private boolean doubleTaskValidate(AgainTask task) {
        boolean isDoubleTask = false;
        List<AgainTask> allLotNoTask = againTaskService.findByLotNoAndAgainNum(task.getLotNo(), task.getAgainNum());
        for (AgainTask againTask : allLotNoTask) {
            if (!againTask.getRawStatus().equals(AgainTaskDto.rawStatus_2) && !againTask.getRawStatus().equals(AgainTaskDto.rawStatus_5)) {
                isDoubleTask = true;
                break;
            }
        }
        return isDoubleTask;
    }


    /**
     * 多次叫料验证
     **/
    private boolean doubleTaskValidate(AgainTaskDetail task) {
        boolean isDoubleTask = false;
        List<AgainTaskDetail> allLotNoTask = againTaskDetailService.findByLotNoAndPailNumAndAgainNum(task.getLotNo(), task.getPailNum(),task.getAgainNum());
        for (AgainTaskDetail againDetaiTask : allLotNoTask) {
            if (!againDetaiTask.getRawStatus().equals(AgainTaskDetailDto.rawStatus_2) && !againDetaiTask.getRawStatus().equals(AgainTaskDetailDto.rawStatus_5)) {
                isDoubleTask = true;
                break;
            }
        }
        return isDoubleTask;
    }

    /**
     * 多次叫料验证
     **/
    private boolean doubleTaskValidate(LoadingTask task) {
        boolean isDoubleTask = false;
        List<LoadingTask> allLotNoTask = loadingTaskService.findByLotNo(task.getLotNo());
        for (LoadingTask againTask : allLotNoTask) {
            if (!againTask.getRawStatus().equals(LoadingTaskDto.rawStatus_2) && !againTask.getRawStatus().equals(LoadingTaskDto.rawStatus_5)) {
                isDoubleTask = true;
                break;
            }
        }
        return isDoubleTask;
    }

    /**
     *
     * @param info
     */
    void generateAutomaticCrystalFetchingTask(LongCrystal info){
        CallTakeCrystalAgvDto dto = new CallTakeCrystalAgvDto();
        dto.setEquipmentCode(info.getEquipmentCode());
        dto.setSeries(info.getSeries());
        dto.setArea(info.getArea());
        dto.setCrystalNo(info.getCrystalNo());
        dto.setLength(info.getLength());
        dto.setLongCrystalId(info.getId());
        dto.setLongCrystal(info);
        dto.setIsAuto(2);
        inspectionRecordService.callTakeCrystalAgv(dto);
    }

}
