package cn.estsh.i3plus.ext.mes.pcn.apiservice.serviceimpl.step;

import cn.estsh.i3plus.ext.mes.pcn.pojo.context.MesProductionPartContext;
import cn.estsh.i3plus.ext.mes.pcn.pojo.context.MesProductionProcessContext;
import cn.estsh.i3plus.ext.mes.pcn.pojo.util.MesPcnExtConstWords;
import cn.estsh.i3plus.pojo.base.enumutil.CommonEnumUtil;
import cn.estsh.i3plus.pojo.base.enumutil.MesPcnEnumUtil;
import cn.estsh.i3plus.pojo.mes.bean.MesQueueOrder;
import cn.estsh.i3plus.pojo.mes.bean.MesWorkCenter;
import cn.estsh.i3plus.pojo.mes.bean.MesWorkOrder;
import cn.estsh.i3plus.pojo.mes.bean.MesWorkOrderAssembly;
import cn.estsh.i3plus.pojo.mes.model.StationRequestBean;
import cn.estsh.i3plus.pojo.mes.model.StationResultBean;
import cn.estsh.i3plus.pojo.mes.model.StepResult;
import cn.estsh.i3plus.pojo.mes.util.MesExtEnumUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * @Description : 生产工单顺序防错工步 【排序】
 * @Author : wangjie
 **/
@Slf4j
@Service("mesProductSeqCheckSortStepService")
public class MesProductSeqCheckSortStepService extends MesProductSeqCheckStepService {

    @Override
    public StepResult execute(StationRequestBean reqBean) {

        StationResultBean resultBean = new StationResultBean();

        StepResult stepResult = StepResult.getSuccessComplete();

        //获取上下文信息
        MesProductionProcessContext productionProcessContext = productionProcessContextStepService.dispatchCurCellEquipment(reqBean);

        //获取生产过程上下文对象有异常信息 抛出异常
        if (!productionProcessContext.getSuccess()) stepExpSendMsgAndThrowEx(reqBean, resultBean.writeDbLog(), productionProcessContext.getMessage());

        //存储生产过程上下文对象
        productionProcessContextStepService.dispatchProductionProcessContext(reqBean, productionProcessContext);

        //获取上下文产出零件信息
        List<MesProductionPartContext> productionPartContextList = productionDispatchContextStepService.getProductionPartContext(reqBean);

        //验证是否存在加工单
        if (!checkIsExistWorkOrder(productionPartContextList)) return stepSuccessCompleteAndSendMsgReturn(reqBean, resultBean.writeDbLog(), stepResult, "当前无加工单信息,无需进行加工单顺序防错验证!");

        //验证工位是否设置需要顺序防错
        if (!isNeedCheckProductSeq(productionPartContextList))
            return stepSuccessCompleteAndSendMsgReturn(reqBean, resultBean.writeDbLog(), stepResult, String.format("生产线[%s]工位[%s]未设置顺序防错,无需进行加工单顺序防错验证!", reqBean.getWorkCenterCode(), reqBean.getWorkCellCode()));

        //验证是否存在工艺强过码, 存在则保存 并返回强过的加工单
        List<String> workOrderNoList2Jump = doHandleCraftJumpCode(reqBean, productionPartContextList);
        if (!CollectionUtils.isEmpty(workOrderNoList2Jump))
            return stepSuccessCompleteAndSendMsgReturn(reqBean, resultBean.writeDbLog().scanInfo(workOrderNoList2Jump.toString()), stepResult, String.format("加工单%s跳过顺序防错验证成功!", workOrderNoList2Jump.toString()));

        //验证是否已经全部通过
        if (!isExistNeedCheckProductSeq(productionPartContextList)) return stepSuccessCompleteAndSendMsgReturn(reqBean, resultBean, stepResult, "加工单均已通过顺序防错验证!");

        //顺序防错验证处理
        doHandleProductSeqCheck(reqBean, resultBean, stepResult, productionProcessContext, productionPartContextList);

        return stepResult;

    }

    //顺序防错验证处理
    private void doHandleProductSeqCheck(StationRequestBean reqBean, StationResultBean resultBean, StepResult stepResult, MesProductionProcessContext productionProcessContext, List<MesProductionPartContext> productionPartContextList) {

        //排序线是否推单
        MesWorkCenter workCenter = productionProcessContext.getWorkCenter();
        Boolean isPushQueue = (StringUtils.isEmpty(workCenter.getIsPushQueue()) || workCenter.getIsPushQueue().compareTo(CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValue()) != 0) ? false : true;

        List<String> workOrderNoList = new ArrayList<>();

        for (MesProductionPartContext productionPartContext : productionPartContextList) {

            if (null == productionPartContext) continue;
            if (StringUtils.isEmpty(productionPartContext.getWorkOrderNo())) continue;
            if (productionPartContext.getCheckSeqResult().compareTo(MesPcnExtConstWords.ZERO) != 0) continue;

            //顺序防错验证
            Boolean result = doProductSeqCheckSort(reqBean, stepResult, productionProcessContext, productionPartContext, isPushQueue);

            productionPartContext.checkSeqResult(!result ? CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue() : CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValue());

            workOrderNoList.add(productionPartContext.getWorkOrderNo());

        }

        //保存上下文产出零件信息
        productionDispatchContextStepService.dispatchProductionPartContext(reqBean, productionPartContextList);

        if (stepResult.isCompleted()) this.sendMessage(reqBean, resultBean.writeDbLog().scanInfo(workOrderNoList.toString()), String.format("加工单%s顺序防错验证成功!", workOrderNoList.toString()), MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.TEXT);
        else this.sendMessage(reqBean, resultBean.writeDbLog().scanInfo(workOrderNoList.toString()), stepResult.getMsg(), MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT);

    }

    //前道工艺防错验证 【排序】
    private Boolean doProductSeqCheckSort(StationRequestBean reqBean, StepResult stepResult, MesProductionProcessContext productionProcessContext, MesProductionPartContext productionPartContext, Boolean isPushQueue) {

        String message = StringUtils.isEmpty(stepResult.getMsg()) ? MesPcnExtConstWords.EMPTY : stepResult.getMsg() + MesPcnExtConstWords.SEMICOLON;

        //根据生产工单顺序号,生产线代码,零件生产组代码查询上一个生产工单信息
        MesWorkOrder workOrder = workOrderExtService.getWorkOrder(reqBean.getOrganizeCode(), reqBean.getWorkCenterCode(), productionPartContext.getProductSeq(), productionPartContext.getPartProdGroupCode());

        if (null == workOrder) return true;

        if (workOrder.getWorkOrderStatus().compareTo(MesExtEnumUtil.ORDER_STATUS.PROCESS.getValue()) < 0)
            return stepResult.isCompleted(false).msg(String.format("%s加工单[%s]生产顺序号[%s]顺序防错验证失败,前一个加工单[%s]生产顺序号[%s]工单状态[%s]",
                    message, productionPartContext.getWorkOrderNo(), productionPartContext.getProductSeq(), workOrder.getWorkOrderNo(), workOrder.getProductSeq(), MesExtEnumUtil.ORDER_STATUS.valueOfDescription(workOrder.getWorkOrderStatus()))).isCompleted();

        if (workOrder.getWorkOrderStatus().compareTo(MesExtEnumUtil.ORDER_STATUS.CLOSE.getValue()) >= 0) return true;

        //----以下是加工中状态下的验证-----

        //根据生产工单,生产线,工位查询工位队列信息
        List<MesQueueOrder> queueOrderList = produceSnExtService.getQueueOrderList(reqBean.getOrganizeCode(), reqBean.getWorkCenterCode(), reqBean.getWorkCellCode(), workOrder.getWorkOrderNo());

        //排序线推单: 是在保存加工结果的时候insertDb队列信息, 存在队列则代表工单已经过当前工位
        if (isPushQueue && !CollectionUtils.isEmpty(queueOrderList)) return true;

        //排序线非推单: 没有队列或者没有创建状态的队列则代表顺序防错通过
        Optional<MesQueueOrder> optional = CollectionUtils.isEmpty(queueOrderList) ? null : queueOrderList.stream().filter(o -> (null != o && o.getStatus().compareTo(MesExtEnumUtil.QUEUE_ORDER_STATUS.CREATE.getValue()) == 0)).findFirst();
        if (!isPushQueue && (null == optional || !optional.isPresent())) return true;

        //根据未完成零件条码获取生产工单装配件清单
        List<String> productSnList = CollectionUtils.isEmpty(queueOrderList) ? null : queueOrderList.stream().filter(o -> (null != o && o.getStatus().compareTo(MesExtEnumUtil.QUEUE_ORDER_STATUS.CREATE.getValue()) == 0)).map(MesQueueOrder::getProductSn).collect(Collectors.toList());
        List<MesWorkOrderAssembly> workOrderAssemblyList = assemblyExtService.getWorkOrderAssemblyList(reqBean.getOrganizeCode(), reqBean.getWorkCenterCode(), reqBean.getWorkCellCode(), workOrder.getWorkOrderNo(), productSnList);
        Map<String, List<MesWorkOrderAssembly>> productSnMap = CollectionUtils.isEmpty(workOrderAssemblyList) ? null : workOrderAssemblyList.stream().filter(o -> null != o).collect(Collectors.groupingBy(MesWorkOrderAssembly::getProductSn));
        if (CollectionUtils.isEmpty(productSnMap)) return true;

        return stepResult.isCompleted(false).msg(String.format("%s加工单[%s]生产顺序号[%s]顺序防错验证失败,前一个加工单[%s]生产顺序号[%s]在当前工位存在未完成队列条码%s",
                message, productionPartContext.getWorkOrderNo(), productionPartContext.getProductSeq(), workOrder.getWorkOrderNo(), workOrder.getProductSeq(), productSnMap.keySet().toString())).isCompleted();

    }

}
