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

import cn.estsh.i3plus.ext.mes.pcn.api.busi.*;
import cn.estsh.i3plus.ext.mes.pcn.apiservice.util.DeepCloneUtil;
import cn.estsh.i3plus.ext.mes.pcn.pojo.context.*;
import cn.estsh.i3plus.ext.mes.pcn.pojo.util.MesPcnExtConstWords;
import cn.estsh.i3plus.mes.pcn.actor.shipping.dispatch.IFsmCommonService;
import cn.estsh.i3plus.mes.pcn.serviceimpl.fsm.BaseStepService;
import cn.estsh.i3plus.mes.pcn.serviceimpl.fsm.IStepService;
import cn.estsh.i3plus.pojo.base.enumutil.CommonEnumUtil;
import cn.estsh.i3plus.pojo.base.enumutil.MesPcnEnumUtil;
import cn.estsh.i3plus.pojo.mes.bean.MesProdRuleIgnoreCfg;
import cn.estsh.i3plus.pojo.mes.bean.MesWorkCenter;
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 cn.estsh.impp.framework.boot.util.SpringContextsUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description : 非排序无显示装配件匹配工步【倒推非排序产品加工规则】
 * @Author : wangjie
 **/
@Slf4j
@Service("mesAssemblyMatchNosortRetrodictStepService")
public class MesAssemblyMatchNosortRetrodictStepService extends BaseStepService {

    @Autowired
    private IFsmCommonService fsmCommonService;

    @Autowired
    private IMesProductionProcessContextStepService productionProcessContextStepService;

    @Autowired
    private IMesProductionDispatchContextStepService productionDispatchContextStepService;

    @Autowired
    private IMesProductionCustomContextStepService productionCustomContextStepService;

    @Autowired
    private IMesNumberRuleMatchDispatchService numberRuleMatchDispatchService;

    @Autowired
    private MesAssemblyShowNosortStepService assemblyShowNosortStepService;

    @Autowired
    private IMesAssemblyExtService assemblyExtService;

    @Autowired
    private IMesProdRuleCfgExtService prodRuleCfgExtService;

    @Autowired
    private IMesProductionRecordService productionRecordService;

    @Autowired
    private IMesTimeEfficientCfgMatchService timeEfficientCfgMatchService;

    @Override
    public StepResult execute(StationRequestBean reqBean) {

        StationResultBean resultBean = new StationResultBean();

        StepResult stepResult = StepResult.getSuccessComplete();

        //获取上下文信息: 处理加工不可用规则
        MesProductionProcessContext productionProcessContext = productionProcessContextStepService.dispatchProdRuleIgnoreCfgContext(reqBean);

        //配置错误 抛出异常
        if (!productionProcessContext.getSuccess()) stepExpSendMsgAndThrowEx(reqBean, resultBean.writeDbLog(), productionProcessContext.getMessage());

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

        if (productionDispatchContextStepService.checkProductionPartIsExistContext(reqBean)) stepExpSendMsgAndThrowEx(reqBean, resultBean.writeDbLog(), "当前存在产出零件数据,不支持执行当前工步,请检查工序模版并重置工序!");

        //获取进料主条码数据信息
        List<MesProductionPsInContext> productionPsInContextList = productionDispatchContextStepService.getProductionPsInContext(reqBean);
        //剔除空腔主条码
        List<MesProductionPsInContext> productionPsInContextListNoFinishCode = CollectionUtils.isEmpty(productionPsInContextList) ? null :
                productionPsInContextList.stream().filter(o -> (null != o && o.getIsFinishCode().compareTo(CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue()) == 0)).collect(Collectors.toList());
        //当前未匹配的主条码
        List<MesProductionPsInContext> curProductionPsInContextList = CollectionUtils.isEmpty(productionPsInContextList) ? null :
                productionPsInContextList.stream().filter(o -> (null != o && StringUtils.isEmpty(o.getForeignKey()) && o.getIsFinishCode().compareTo(CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue()) == 0)).collect(Collectors.toList());

        //获取上下文产品加工规则数据信息集合
        List<MesProdRuleContext> prodRuleContextList = productionDispatchContextStepService.getProdRuleDataContext(reqBean);

        if (!CollectionUtils.isEmpty(productionPsInContextListNoFinishCode) && !CollectionUtils.isEmpty(prodRuleContextList) &&
                productionPsInContextListNoFinishCode.size() == prodRuleContextList.size()) stepExpSendMsgAndThrowEx(reqBean, resultBean.writeDbLog(), "当前已存在非排序产品加工规则数据,不支持执行当前工步,请检查工序模版并重置工序!");

        //获取上下文生产扫/读信息:装配件条码
        List<MesEquipVariableCollectContext> equipVariableCollectContextList = productionDispatchContextStepService.getScanAssemblySnContext(reqBean);

        //删除上下文扫/读信息:装配件条码
        if (!CollectionUtils.isEmpty(equipVariableCollectContextList)) productionDispatchContextStepService.removeScanAssemblySnContext(reqBean);

        //从上下文中取出工位当前要使用的设备
        MesCellEquipContext cellEquipContext = productionProcessContext.getCurCellEquip();

        //当前主条码是空腔码
        if (!CollectionUtils.isEmpty(productionPsInContextList) && CollectionUtils.isEmpty(curProductionPsInContextList)) {
            //主条码数量是否满足腔数
            Boolean isEnoughQty = productionPsInContextList.size() == cellEquipContext.getCavity();
            //主条码数量满足腔数,调用生成零件条码工步
            if (isEnoughQty) ((IStepService) SpringContextsUtil.getBean("mesProductSnGenerateStepService")).executeInState(reqBean);

            return stepDynamicsCompleteAndSendMsgReturn(reqBean, resultBean.writeDbLog(), stepResult,
                    isEnoughQty ? true : stepResult.isCompleted(false).nextTriggerEvent(MesPcnExtConstWords.NEXT_TRIGGER_EVENT_PRODUCT_SN).isCompleted(),
                    MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.TEXT,
                    String.format("当前主条码为空腔码,无需匹配!当前扫描的主条码数量[%s]%s设备腔数[%s]!", productionPsInContextList.size(), isEnoughQty ? "已满足" : "未满足", cellEquipContext.getCavity()));
        }

        if (CollectionUtils.isEmpty(equipVariableCollectContextList)) return stepNonCompleteAndSendMsgReturn(reqBean, resultBean.writeDbLog(), stepResult.nextTriggerEvent(MesPcnExtConstWords.NEXT_TRIGGER_EVENT_ASSEMBLY), "当前不存在装配件条码!");

        //搜集装配件条码
        String assemblySn = equipVariableCollectContextList.stream().filter(o -> null != o).map(MesEquipVariableCollectContext::getEquipVariableValue).collect(Collectors.toList()).toString();

        //根据设备代码获取可复用条码的个数
        Integer repeatAssemblySnCount = productionCustomContextStepService.getRepeatAssemblySnCount(reqBean.getOrganizeCode(), reqBean.getWorkCenterCode(), reqBean.getWorkCellCode(), cellEquipContext.getEquipmentCode());
        Integer repeatAssemblySnAmount = repeatAssemblySnCount * (!CollectionUtils.isEmpty(curProductionPsInContextList) ? curProductionPsInContextList.size() : cellEquipContext.getCavity());
        //验证装配件条码个数是否匹配 腔数或者未匹配的主条码个数*每腔个数
        if ((equipVariableCollectContextList.size() + repeatAssemblySnAmount) != (!CollectionUtils.isEmpty(curProductionPsInContextList) ? curProductionPsInContextList.size() : cellEquipContext.getCavity()) * cellEquipContext.getBindQty()) {
            String suffix = repeatAssemblySnAmount == 0 ? MesPcnExtConstWords.EMPTY : String.format(",可复用个数[%s]", repeatAssemblySnAmount);
            if (!CollectionUtils.isEmpty(curProductionPsInContextList)) {
                productionDispatchContextStepService.dispatchProductionPsInContext(reqBean, productionPsInContextList.stream().filter(o -> (null != o && !StringUtils.isEmpty(o.getForeignKey()))).collect(Collectors.toList()));
                return stepNonCompleteAndSendMsgReturn(reqBean, resultBean.writeDbLog().scanInfo(assemblySn), stepResult.nextTriggerEvent(MesPcnExtConstWords.NEXT_TRIGGER_EVENT_PRODUCT_SN),
                        String.format("当前装配件条码个数[%s]%s不满足主条码个数[%s]每腔个数[%s]配置!", equipVariableCollectContextList.size(), suffix, curProductionPsInContextList.size(), cellEquipContext.getBindQty()));
            } else {
                return stepNonCompleteAndSendMsgReturn(reqBean, resultBean.writeDbLog().scanInfo(assemblySn), stepResult.nextTriggerEvent(MesPcnExtConstWords.NEXT_TRIGGER_EVENT_ASSEMBLY),
                        String.format("当前装配件条码个数[%s]%s不满足腔数[%s]每腔个数[%s]配置!", equipVariableCollectContextList.size(), suffix, cellEquipContext.getCavity(), cellEquipContext.getBindQty()));
            }
        }

        //当前反向匹配最外层的遍历次数
        Integer loopTimes = !CollectionUtils.isEmpty(productionPsInContextList) ? curProductionPsInContextList.size() : cellEquipContext.getCavity();

        //获取加工不可用规则
        Map<String, List<MesProdRuleIgnoreCfg>> prodRuleIgnoreCfgMap = productionProcessContextStepService.getProdRuleIgnoreCfgContextMap(reqBean, productionProcessContext);

        //获取设备下所有的装配件规则清单, 根据非排序加工规则ID分组
        Map<Long, List<MesProductionAssemblyNosortContext>> assemblyNosortCfgMap = doHandleAssemblyNosortCfg(reqBean, resultBean, stepResult, cellEquipContext, prodRuleIgnoreCfgMap);

        //无主条码则无加工规则, 有主条码可能无加工规则
        prodRuleContextList = CollectionUtils.isEmpty(prodRuleContextList) ? new ArrayList<>() : prodRuleContextList;
        //生成零件号业务处理
        prodRuleContextList = doHandleAssemblyGeneratePartNo(reqBean, resultBean, stepResult, cellEquipContext, loopTimes, productionProcessContext, productionPsInContextList, prodRuleContextList, assemblyNosortCfgMap, equipVariableCollectContextList, prodRuleIgnoreCfgMap);

        String suffix = !CollectionUtils.isEmpty(curProductionPsInContextList) ? String.format("当前主条码%s", curProductionPsInContextList.stream().filter(o -> null != o).map(MesProductionPsInContext::getProductSn).collect(Collectors.toList()).toString()) : MesPcnExtConstWords.EMPTY;

        //判断是否存在未消费的装配件条码
        Optional<MesEquipVariableCollectContext> optional = equipVariableCollectContextList.stream().filter(o -> (null != o && o.getIsConsume().compareTo(CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue()) == 0)).findFirst();
        if (null != optional && optional.isPresent()) {

            stepResult.msg(String.format("%s装配件条码%s匹配失败!%s", suffix, assemblySn, StringUtils.isEmpty(stepResult.getMsg()) ? MesPcnExtConstWords.EMPTY : stepResult.getMsg()));

            this.sendMessage(reqBean, new StationResultBean().writeDbLog().scanInfo(assemblySn),
                    String.format("%s%s", stepResult.getMsg(), StringUtils.isEmpty(stepResult.getObj()) ? MesPcnExtConstWords.EMPTY : stepResult.getObj()), MesPcnEnumUtil.STATION_BUSI_TYPE.RUNNING_INFO, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT);

            if (!CollectionUtils.isEmpty(curProductionPsInContextList)) productionDispatchContextStepService.dispatchProductionPsInContext(reqBean, productionPsInContextList.stream().filter(o -> (null != o && !StringUtils.isEmpty(o.getForeignKey()))).collect(Collectors.toList()));

            return stepNonCompleteAndSendMsgReturn(reqBean, resultBean, stepResult.nextTriggerEvent(!CollectionUtils.isEmpty(curProductionPsInContextList) ? MesPcnExtConstWords.NEXT_TRIGGER_EVENT_PRODUCT_SN : MesPcnExtConstWords.NEXT_TRIGGER_EVENT_ASSEMBLY), stepResult.getMsg());
        }

        //保存上下文产品加工规则信息集合
        productionDispatchContextStepService.dispatchProdRuleDataContext(reqBean, prodRuleContextList);

        //保存进料主条码数据
        if (!CollectionUtils.isEmpty(productionPsInContextList)) productionDispatchContextStepService.dispatchProductionPsInContext(reqBean, productionPsInContextList);

        //显示装配件信息
        assemblyShowNosortStepService.showProductionAssembly(reqBean, resultBean, productionProcessContext.getWorkCenter(), prodRuleContextList);

        //验证主条码是否全部匹配完毕
        if (!CollectionUtils.isEmpty(productionPsInContextList)) {
            //主条码数量是否满足腔数
            Boolean isEnoughQty = productionPsInContextList.size() == cellEquipContext.getCavity();
            //主条码数量满足腔数,调用生成零件条码工步
            if (isEnoughQty) ((IStepService) SpringContextsUtil.getBean("mesProductSnGenerateStepService")).executeInState(reqBean);

            return stepDynamicsCompleteAndSendMsgReturn(reqBean, resultBean.writeDbLog().scanInfo(assemblySn), stepResult,
                    isEnoughQty ? true : stepResult.isCompleted(false).nextTriggerEvent(MesPcnExtConstWords.NEXT_TRIGGER_EVENT_PRODUCT_SN).isCompleted(),
                    MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.TEXT,
                    String.format("%s装配件条码%s匹配成功!当前扫描的主条码数量[%s]%s设备腔数[%s]!", suffix, assemblySn, productionPsInContextList.size(), isEnoughQty ? "已满足" : "未满足", cellEquipContext.getCavity()),
                    MesPcnEnumUtil.PROMPT_SOUND.SUCCESS.getValue());
        }

        return stepSuccessCompleteAndSendMsgReturn(reqBean, resultBean.writeDbLog().scanInfo(assemblySn), stepResult, String.format("装配件条码%s匹配成功!", assemblySn),
                MesPcnEnumUtil.PROMPT_SOUND.SUCCESS.getValue());

    }

    //获取设备下所有的装配件规则清单, 根据非排序加工规则ID分组
    private Map<Long, List<MesProductionAssemblyNosortContext>> doHandleAssemblyNosortCfg(StationRequestBean reqBean, StationResultBean resultBean, StepResult stepResult, MesCellEquipContext cellEquipContext,
                                                                                          Map<String, List<MesProdRuleIgnoreCfg>> prodRuleIgnoreCfgMap) {

        //查询工位设备装配件规则信息
        List<MesProductionAssemblyNosortContext> assemblyNosortCfgList = productionProcessContextStepService.findAssemblyNosortCfgList(reqBean);

        //获取设备的装配件规则清单
        if (CollectionUtils.isEmpty(assemblyNosortCfgList) || !assemblyNosortCfgList.get(0).getEquipmentCode().equals(cellEquipContext.getEquipmentCode())) {
            assemblyNosortCfgList = assemblyExtService.getProductionAssemblyNosortContextList(reqBean.getOrganizeCode(), cellEquipContext.getEquipmentCode(), prodRuleIgnoreCfgMap);

            if (CollectionUtils.isEmpty(assemblyNosortCfgList))
                stepExpSendMsgAndThrowEx(reqBean, resultBean.writeDbLog(),
                        String.format("生产线[%s]工位[%s]设备[%s]未维护含有装配件规则信息的非排序加工规则信息", reqBean.getWorkCenterCode(), reqBean.getWorkCellCode(), cellEquipContext.getEquipmentName()));

            //存储设备的装配件清单
            productionProcessContextStepService.dispatchAssemblyNosortCfgContext(reqBean, assemblyNosortCfgList);

        }

        //根据非排序加工规则ID分组
        return assemblyNosortCfgList.stream().filter(o -> (null != o && !StringUtils.isEmpty(o.getPid()))).collect(Collectors.groupingBy(MesProductionAssemblyNosortContext::getPid));

    }

    //生成零件号业务处理
    private List<MesProdRuleContext> doHandleAssemblyGeneratePartNo(StationRequestBean reqBean, StationResultBean resultBean, StepResult stepResult, MesCellEquipContext cellEquipContext, Integer loopTimes,
                                                                    MesProductionProcessContext productionProcessContext, List<MesProductionPsInContext> productionPsInContextList, List<MesProdRuleContext> prodRuleContextList,
                                                                    Map<Long, List<MesProductionAssemblyNosortContext>> assemblyNosortCfgMap, List<MesEquipVariableCollectContext> equipVariableCollectContextList,
                                                                    Map<String, List<MesProdRuleIgnoreCfg>> prodRuleIgnoreCfgMap) {

        //从上下文中取出生产线对象
        MesWorkCenter workCenter = productionProcessContext.getWorkCenter();

        //拿到当前最大的foreignKey
        Optional<MesProdRuleContext> maxForeignKeyOptional = CollectionUtils.isEmpty(prodRuleContextList) ? null : prodRuleContextList.stream().filter(o -> (null != o && !StringUtils.isEmpty(o.getForeignKey()))).max(Comparator.comparing(MesProdRuleContext::getForeignKey));
        Integer foreignKey = (null != maxForeignKeyOptional && maxForeignKeyOptional.isPresent()) ? maxForeignKeyOptional.get().getForeignKey() : MesPcnExtConstWords.ZERO;

        for (int i = 0; i < loopTimes; i ++) {

            //遍历非排序加工规则ID
            for (Map.Entry<Long, List<MesProductionAssemblyNosortContext>> entry : assemblyNosortCfgMap.entrySet()) {

                if (null == entry) continue;

                //判断是否存在未消费的装配件条码
                List<MesEquipVariableCollectContext> unConsumeList = equipVariableCollectContextList.stream().filter(o -> (null != o && o.getIsConsume().compareTo(CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue()) == 0)).collect(Collectors.toList());
                if (CollectionUtils.isEmpty(unConsumeList)) break;

                //剔除不扫描/不显示且不扫描/仅目视的数据
                List<MesProductionAssemblyNosortContext> productionAssemblyNosortContextList = entry.getValue().stream().filter(o -> (null != o && !StringUtils.isEmpty(o.getMatchType()) && MesExtEnumUtil.ASSEMBLY_MATCH_TYPE.checkIsNeedScan(o.getMatchType()))).collect(Collectors.toList());
                if (CollectionUtils.isEmpty(productionAssemblyNosortContextList)) continue;

                //剔除装配件规则个数不等于每腔个数的数据
                if (cellEquipContext.getBindQty().compareTo(productionAssemblyNosortContextList.size()) != 0) continue;

                //收集未消费的临时数据
                List<MesEquipVariableCollectContext> equipVariableCollectContextListTemp = DeepCloneUtil.deepCloneList(unConsumeList);
                if (CollectionUtils.isEmpty(equipVariableCollectContextListTemp)) break;

                //遍历非排序加工规则ID对应的装配件规则清单
                for (MesProductionAssemblyNosortContext productionAssemblyNosortContext : productionAssemblyNosortContextList) {

                    if (null == productionAssemblyNosortContext) continue;

                    for (MesEquipVariableCollectContext equipVariableCollectContext : equipVariableCollectContextListTemp) {

                        //已被消费
                        if (null == equipVariableCollectContext || equipVariableCollectContext.getIsConsume().compareTo(CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValue()) == 0) continue;

                        //匹配规则
                        Map<String, Object> result = numberRuleMatchDispatchService.matchNumberRule(reqBean.getOrganizeCode(), equipVariableCollectContext.getEquipVariableValue(), productionAssemblyNosortContext);

                        //匹配失败
                        if (!(Boolean) result.get(MesPcnExtConstWords.RESULT)) {
                            String msg = (String) result.get(MesPcnExtConstWords.MESSAGE);
                            stepResult.obj(String.format("%s%s", StringUtils.isEmpty(stepResult.getObj()) ? MesPcnExtConstWords.EMPTY : stepResult.getObj(), StringUtils.isEmpty(msg) ? MesPcnExtConstWords.EMPTY : msg));
                            continue;
                        }

                        MesProductionAssemblyNosortContext filter = (MesProductionAssemblyNosortContext) result.get(MesPcnExtConstWords.DATA);

                        //前道防错
                        if (!StringUtils.isEmpty(filter.getProductSnId()) && !StringUtils.isEmpty(productionAssemblyNosortContext.getPreCraftCode())) {
                            if (CollectionUtils.isEmpty(productionRecordService.findProductionRecordListByCraft(reqBean.getOrganizeCode(), equipVariableCollectContext.getEquipVariableValue(), productionAssemblyNosortContext.getPreCraftCode()))) {
                                stepResult.msg(String.format("%s%s", StringUtils.isEmpty(stepResult.getMsg()) ? MesPcnExtConstWords.EMPTY : stepResult.getMsg(),
                                        String.format("零件条码[%s]前道防错工艺[%s]验证失败,未查询到加工记录信息!", equipVariableCollectContext.getEquipVariableValue(), productionAssemblyNosortContext.getPreCraftCode())));
                                continue;
                            }
                        }

                        //时效性验证
                        if (!StringUtils.isEmpty(filter.getProductSnId())) {
                            result = timeEfficientCfgMatchService.checkSnTimeliness(reqBean.getOrganizeCode(), equipVariableCollectContext.getEquipVariableValue(), filter.getSourceId(), MesExtEnumUtil.TIME_DATA_SOURCE.DATA_SOURCE30.getValue());
                            if (!(Boolean)result.get(MesPcnExtConstWords.RESULT)) {
                                stepResult.msg(String.format("%s%s", StringUtils.isEmpty(stepResult.getMsg()) ? MesPcnExtConstWords.EMPTY : stepResult.getMsg(), result.get(MesPcnExtConstWords.MESSAGE)));
                                continue;
                            }
                        }

                        //验证返回result里面是否存在assemblySn,存在特殊的规则会转换成新的条码
                        String assemblySn = !result.containsKey(MesPcnExtConstWords.ASSEMBLY_SN) ? equipVariableCollectContext.getEquipVariableValue() : (String) result.get(MesPcnExtConstWords.ASSEMBLY_SN);

                        //验证规则且唯一/自制件 在当前开模内是否存在重复
                        if (MesExtEnumUtil.ASSEMBLY_MATCH_TYPE.checkUniqueRuleInMould(productionAssemblyNosortContext.getMatchType()) && !numberRuleMatchDispatchService.checkAssemblySnUniqueInMould(workCenter, prodRuleContextList, productionAssemblyNosortContextList, assemblySn)) {
                            stepResult.msg(String.format("%s[%s]不能重复装配!", StringUtils.isEmpty(stepResult.getMsg()) ? MesPcnExtConstWords.EMPTY : stepResult.getMsg(), assemblySn));
                            continue;
                        }

                        //装配件清单该数据标记已装配 (如果是自制件赋值productSnId)
                        productionAssemblyNosortContext.assemblyStatus(assemblySn).productSnId(filter.getProductSnId());

                        //临时数据标记已消费
                        equipVariableCollectContext.isConsume();

                        break;

                    }

                    String getRepeatAssemblySn = productionCustomContextStepService.getRepeatAssemblySn(reqBean.getOrganizeCode(), reqBean.getWorkCenterCode(), reqBean.getWorkCellCode(), productionAssemblyNosortContext);
                    if (!StringUtils.isEmpty(getRepeatAssemblySn)) productionAssemblyNosortContext.assemblyStatus(getRepeatAssemblySn);

                    //判断当前装配件规则是否被成功匹配条码
                    if (productionAssemblyNosortContext.getAssemblyStatus().compareTo(MesExtEnumUtil.ASSEMBLY_STATUS.ASSEMBLY_STATUS_30.getValue()) == 0) break;

                }

                //判断当前装配件规则清单是否完全匹配剩余未消费的条码
                Optional<MesProductionAssemblyNosortContext> optionalRule = productionAssemblyNosortContextList.stream().filter(o -> (null != o && o.getAssemblyStatus().compareTo(MesExtEnumUtil.ASSEMBLY_STATUS.ASSEMBLY_STATUS_30.getValue()) == 0)).findFirst();
                if (null != optionalRule && optionalRule.isPresent()) continue;

                //验证加工规则是否有效
                MesProdRuleContext prodRuleContext = prodRuleCfgExtService.getProdRuleNosortContextByPid(new MesProdRuleContext(
                        reqBean.getOrganizeCode(), reqBean.getWorkCenterCode(), reqBean.getWorkCellCode(), reqBean.getProcessCode(), productionProcessContext.getCraftCode()).pid(productionAssemblyNosortContextList.get(0).getPid()));
                //加工规则关联不可用规则信息
                prodRuleContext = prodRuleCfgExtService.getProdRuleNosortContextByPid(prodRuleContext, prodRuleIgnoreCfgMap);

                //根据PID获取非排序加工规则 数据无效
                if (null == prodRuleContext) continue;

                Boolean productSnIsMatchFlag = false;
                String errMsg = MesPcnExtConstWords.EMPTY;
                if (!CollectionUtils.isEmpty(productionPsInContextList)) {

                    for (MesProductionPsInContext productionPsInContext : productionPsInContextList) {

                        if (null == productionPsInContext || !StringUtils.isEmpty(productionPsInContext.getForeignKey()) || productionPsInContext.getIsFinishCode().compareTo(CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValue()) == 0) continue;

                        //验证主条码是否满足当前匹配成功的产品加工规则
                        Map<String, Object> result = checkPsInIsMatchProdRule(reqBean.getOrganizeCode(), productionPsInContext, prodRuleContext);
                        if (!(Boolean) result.get(MesPcnExtConstWords.RESULT)) {
                            errMsg = (String) result.get(MesPcnExtConstWords.MESSAGE);
                            continue;
                        }

                        //时效性验证
                        if (!StringUtils.isEmpty(productionPsInContext.getPartNo())) {
                            result = timeEfficientCfgMatchService.checkSnTimeliness(reqBean.getOrganizeCode(), productionPsInContext.getProductSn(), prodRuleContext.getPid(), MesExtEnumUtil.TIME_DATA_SOURCE.DATA_SOURCE20.getValue());
                            if (!(Boolean) result.get(MesPcnExtConstWords.RESULT)) {
                                errMsg = (String) result.get(MesPcnExtConstWords.MESSAGE);
                                continue;
                            }
                        }

                        productSnIsMatchFlag = true;
                        errMsg = MesPcnExtConstWords.EMPTY;

                        //主条码赋值数据关联键
                        productionPsInContext.foreignKey(foreignKey += 1);
                        break;

                    }

                }

                if (!productSnIsMatchFlag && !CollectionUtils.isEmpty(productionPsInContextList)) {
                    stepResult.msg(String.format("%s%s", StringUtils.isEmpty(stepResult.getMsg()) ? MesPcnExtConstWords.EMPTY : stepResult.getMsg(), errMsg));
                    continue;
                }

                //装配件条码标记被消费状态
                productionAssemblyNosortContextList.forEach(o -> {
                    Optional<MesEquipVariableCollectContext> evccOp = equipVariableCollectContextList.stream().filter(v -> (null != v && v.getIsConsume().compareTo(CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue()) == 0 && v.getEquipVariableValue().equals(o.getAssemblySn()))).findFirst();
                    if (null != evccOp && evccOp.isPresent()) evccOp.get().isConsume();
                });

                //加工规则赋值装配件数据
                prodRuleContext.assemblyDataJson(productionAssemblyNosortContextList).foreignKey(!productSnIsMatchFlag ? foreignKey += 1 : foreignKey);

                prodRuleContextList.add(prodRuleContext);

            }

        }

        return prodRuleContextList;

    }

    private Map<String, Object> checkPsInIsMatchProdRule(String organizeCode, MesProductionPsInContext productionPsInContext, MesProdRuleContext prodRuleContext) {
        //根据进料零件条码匹配进料零件规则
        if (StringUtils.isEmpty(productionPsInContext.getPartNo())) return numberRuleMatchDispatchService.matchNumberRule(organizeCode, productionPsInContext.getProductSn(), prodRuleContext);

        Map<String, Object> result = new HashMap<>();
        result.put(MesPcnExtConstWords.RESULT, true);
        //根据进料零件号匹配产品加工规则
        if (!StringUtils.isEmpty(productionPsInContext.getPartNo()) && (StringUtils.isEmpty(prodRuleContext.getInPartNo()) || !prodRuleContext.getInPartNo().equals(productionPsInContext.getPartNo()))) {
            result.put(MesPcnExtConstWords.RESULT, false);
            if (StringUtils.isEmpty(prodRuleContext.getInPartNo()))
                result.put(MesPcnExtConstWords.MESSAGE, String.format("条码[%s]零件号[%s]匹配的加工规则ID[%s]信息未维护进料零件号!", productionPsInContext.getProductSn(), productionPsInContext.getPartNo(), prodRuleContext.getPid()));
            else result.put(MesPcnExtConstWords.MESSAGE, String.format("条码[%s]零件号[%s]不匹配加工规则维护的进料零件号[%s]!", productionPsInContext.getProductSn(), productionPsInContext.getPartNo(), prodRuleContext.getInPartNo()));
        }

        return result;
    }

}
