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

import cn.estsh.i3plus.ext.mes.pcn.api.base.ISxWorkOrderExtService;
import cn.estsh.i3plus.ext.mes.pcn.api.busi.IWorkOrderProcessBomService;
import cn.estsh.i3plus.ext.mes.pcn.api.busi.jx.IJxProdBindRecordExtService;
import cn.estsh.i3plus.ext.mes.pcn.pojo.bean.MesProcessBom;
import cn.estsh.i3plus.ext.mes.pcn.pojo.bean.MesProdBindRecordExt;
import cn.estsh.i3plus.ext.mes.pcn.pojo.bean.MesWorkOrderExt;
import cn.estsh.i3plus.ext.mes.pcn.pojo.bean.MesWorkOrderProcessBom;
import cn.estsh.i3plus.ext.mes.pcn.pojo.model.ProcessBomModel;
import cn.estsh.i3plus.ext.mes.pcn.pojo.model.WorkOrderExtModel;
import cn.estsh.i3plus.ext.mes.pcn.pojo.repository.MesProcessBomRepository;
import cn.estsh.i3plus.ext.mes.pcn.pojo.util.ConvertBeanExt;
import cn.estsh.i3plus.ext.mes.pcn.pojo.util.MesPcnExtConstWords;
import cn.estsh.i3plus.ext.mes.pcn.pojo.util.MesPcnExtEnumUtil;
import cn.estsh.i3plus.mes.pcn.actor.shipping.dispatch.IFsmCommonService;
import cn.estsh.i3plus.mes.pcn.actor.shipping.dispatch.IFsmRouteDataService;
import cn.estsh.i3plus.mes.pcn.api.iservice.busi.IShippingDispatchService;
import cn.estsh.i3plus.mes.pcn.serviceimpl.base.BaseStepService;
import cn.estsh.i3plus.mes.pcn.util.LocaleUtil;
import cn.estsh.i3plus.mes.pcn.util.PojoAttrUtil;
import cn.estsh.i3plus.platform.common.convert.ConvertBean;
import cn.estsh.i3plus.platform.common.tool.MathOperation;
import cn.estsh.i3plus.platform.common.util.MesPcnConstWords;
import cn.estsh.i3plus.pojo.base.bean.DdlPackBean;
import cn.estsh.i3plus.pojo.base.enumutil.CommonEnumUtil;
import cn.estsh.i3plus.pojo.base.enumutil.MesPcnEnumUtil;
import cn.estsh.i3plus.pojo.base.tool.DdlPreparedPack;
import cn.estsh.i3plus.pojo.mes.bean.MesKpsnRule;
import cn.estsh.i3plus.pojo.mes.bean.MesProdBindRecord;
import cn.estsh.i3plus.pojo.mes.model.AttrBean;
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.repository.MesKpsnRuleRepository;
import cn.estsh.impp.framework.boot.util.SpringContextsUtil;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.lang.reflect.Method;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description : 嘉兴绑定关键件工步
 * @Reference :
 * @Author : wangjie
 * @CreateDate : 2019-04-18
 * @Modify:
 **/
@Slf4j
@Service("jxBindKeyPartStepService")
public class JxBindKeyPartStepService extends BaseStepService {

    @Autowired
    private ISxWorkOrderExtService workOrderExtService;

    @Autowired
    private IWorkOrderProcessBomService workOrderProcessBomService;

    @Autowired
    private MesKpsnRuleRepository kpsnRuleRepository;

    @Autowired
    private IJxProdBindRecordExtService prodBindRecordExtService;

    @Autowired
    private MesProcessBomRepository processBomRepository;

    @Autowired
    private IShippingDispatchService shippingDispatchService;

    @Autowired
    private IFsmCommonService fsmCommonService;

    private static final String VALIDATION_CODE = "VALIDATION_CODE";
    private static final String SHOW_KPSN_RULE = "SHOW_KPSN_RULE";
    private static final String RELOAD_KEY_PART_CODE = "RELOAD_KEY_PART_CODE";

    @Override
    public StepResult init(StationRequestBean reqBean) {

        log.info("工厂{}生产线{}工位{}: --- STEP INIT --- JxBindKeyPartStepService --- START --- ", reqBean.getOrganizeCode(), reqBean.getWorkCenterCode(), reqBean.getWorkCellCode());

        StationResultBean resultBean = new StationResultBean();

        if (StringUtils.isEmpty(reqBean.getTray()) && StringUtils.isEmpty(reqBean.getProductSn())) return execNonCompleteAndSendMsgReturn(reqBean, resultBean, "入参缺少管理编码或产品条码!");

        Object moduleService = getModuleService(reqBean);

        Method method = getModuleServiceMethod(reqBean, resultBean, moduleService);

        StepResult stepResult = StepResult.getSuccessComplete();

        if (!StringUtils.isEmpty(doHandleBindKeyPartData(reqBean, resultBean, moduleService, method, 1, MesPcnExtConstWords.BIND_KEY_PART, null))) return stepResult;

        String curExecWorkOrderNo = getCurExecWorkOrderNo(reqBean, resultBean, moduleService);

        WorkOrderExtModel orderModel = getWorkOrderExtModel(reqBean, resultBean, curExecWorkOrderNo);

        List<ProcessBomModel> pbList = getProcessBomList(reqBean, orderModel);

        if (CollectionUtils.isEmpty(pbList)) return execSuccessCompleteAndSendMsgReturn(reqBean, resultBean, stepResult, "没有需要绑定的清单,请维护!");

        if (checkIsShowKpsnRule(reqBean)) restorePbList(reqBean, pbList);

        checkAndPackPbListIsExistBindedData(reqBean, orderModel, pbList);

        doHandleBindKeyPartData(reqBean, resultBean, moduleService, method, 2, MesPcnExtConstWords.BIND_KEY_PART, JSONObject.toJSONString(pbList));

        this.refresh(reqBean, resultBean, pbList);

        log.info("工厂{}生产线{}工位{}: --- STEP INIT --- JxBindKeyPartStepService --- SUCCESS --- ", reqBean.getOrganizeCode(), reqBean.getWorkCenterCode(), reqBean.getWorkCellCode());

        return StepResult.getSuccessComplete();

    }

    @Override
    public StepResult execute(StationRequestBean reqBean) {

        log.info("工厂{}生产线{}工位{}: --- STEP EXECUTE --- JxBindKeyPartStepService --- START --- ", reqBean.getOrganizeCode(), reqBean.getWorkCenterCode(), reqBean.getWorkCellCode());

        StationResultBean resultBean = new StationResultBean();

        if (StringUtils.isEmpty(reqBean.getTray()) && StringUtils.isEmpty(reqBean.getProductSn())) return execNonCompleteAndSendMsgReturn(reqBean, resultBean, "入参缺少管理编码或产品条码!");

        Object moduleService = getModuleService(reqBean);

        Method method = getModuleServiceMethod(reqBean, resultBean, moduleService);

        String appendItem = new StringJoiner(MesPcnExtConstWords.COMMA).add(MesPcnExtConstWords.BIND_KEY_PART).add(MesPcnExtConstWords.EXEC_BIND_KEY).toString();

        if (checkReloadKeyPartData(reqBean, resultBean, moduleService, method, appendItem)) execSendMsgAndThrowEx(reqBean, resultBean, "重载关键件成功!");

        StepResult stepResult = StepResult.getSuccessComplete();

        String suffix = StringUtils.isEmpty(reqBean.getProductSn()) ? String.format("管理编码[%s]", getManageCode(reqBean.getTray(), 1)) : String.format("产品条码[%s]", reqBean.getProductSn());

        if (checkIsJumpState(reqBean, resultBean, moduleService, method, appendItem, false))
            return execSuccessCompleteAndSendMsgReturn(reqBean, resultBean, stepResult, String.format("%s已跳过关键件绑定业务", suffix));

        Object data = doHandleBindKeyPartData(reqBean, resultBean, moduleService, method, 1, MesPcnExtConstWords.BIND_KEY_PART, null);

        if (null == data) data = execInit(reqBean, resultBean, moduleService, method);

        if (null == data) return execDynamicsCompleteAndSendMsgReturn(reqBean, resultBean, stepResult, checkIsJumpState(reqBean, resultBean, moduleService, method, appendItem, true), "没有需要绑定的清单,请维护!");

        List<ProcessBomModel> pbList = this.refresh(reqBean, resultBean, JSONObject.parseArray((String) data, ProcessBomModel.class));

        List<MesKpsnRule> kpsnRuleList = getKpsnRuleList(reqBean, pbList);

        String curExecWorkOrderNo = getCurExecWorkOrderNo(reqBean, resultBean, moduleService);

        WorkOrderExtModel orderModel = getWorkOrderExtModel(reqBean, resultBean, curExecWorkOrderNo);

        checkKpsnRule4PbList(reqBean, resultBean, kpsnRuleList, pbList, orderModel);

        if (checkPbListIsComplete(reqBean, resultBean, moduleService, method, appendItem, pbList, false))
            return execSuccessCompleteAndSendMsgReturn(reqBean, resultBean, stepResult, String.format("%s:关键件已绑定完毕!", suffix));

        List<MesKpsnRule> okList = matchKpsnRule4ScanInfo(reqBean, resultBean, moduleService, method, kpsnRuleList, suffix);

        ProcessBomModel processBomModel = getMatchPbData(reqBean, resultBean, pbList, okList, suffix);

        checkKeyPartIsRepeatBind(reqBean, resultBean, processBomModel, suffix);

        insertMesProdBindRecordExt(reqBean, orderModel, processBomModel, okList);
        
        overrideMatchPbData(processBomModel);

        this.refresh(reqBean, resultBean, pbList);

        if (!checkPbListIsComplete(reqBean, resultBean, moduleService, method, appendItem, pbList, true)) 
            execSendMsgAndThrowEx(reqBean, resultBean, String.format("关键件条码[%s]绑定%s成功,请继续扫描关键件!", reqBean.getScanInfo(), suffix));
        
        log.info("工厂{}生产线{}工位{}: --- STEP EXECUTE --- JxBindKeyPartStepService --- SUCCESS --- ", reqBean.getOrganizeCode(), reqBean.getWorkCenterCode(), reqBean.getWorkCellCode());

        return execSuccessCompleteAndSendMsgReturn(reqBean, resultBean, stepResult, String.format("关键件条码[%s]绑定%s成功,关键件绑定完毕!", reqBean.getScanInfo(), suffix));

    }

    private List<ProcessBomModel> getProcessBomList(StationRequestBean reqBean, WorkOrderExtModel orderModel) {
        List<MesProcessBom> processBomList = getProcessBomListByProcessCodeAndPartNo(reqBean.getOrganizeCode(), reqBean.getProcessCode(), orderModel.getPartNo());
        if (CollectionUtils.isEmpty(processBomList)) return null;
        if (MesPcnExtEnumUtil.WORK_ORDER_TYPE.REWORK_ORDER.getValue() != orderModel.getWorkOrderType()) return getProcessBomList(processBomList);
        return getProcessBomList(reqBean, orderModel, processBomList);
    }

    private List<ProcessBomModel> getProcessBomList(List<MesProcessBom> processBomList) {
        List<ProcessBomModel> pbList = null;
        for (MesProcessBom processBom : processBomList) {
            if (null == processBom) continue;
            ProcessBomModel pb = new ProcessBomModel();
            BeanUtils.copyProperties(processBom, pb);
            if (CollectionUtils.isEmpty(pbList)) pbList = new ArrayList<>();
            pbList.add(pb);
        }
        return pbList;
    }

    private List<ProcessBomModel> getProcessBomList(StationRequestBean reqBean, WorkOrderExtModel orderModel, List<MesProcessBom> processBomList) {
        List<MesWorkOrderProcessBom> workOrderProcessBomList = workOrderProcessBomService.getWorkOrderProcessBomList(reqBean.getOrganizeCode(), orderModel.getOrderNo(), reqBean.getProcessCode(), orderModel.getPartNo());
        if (CollectionUtils.isEmpty(workOrderProcessBomList)) return null;
        Map<String, List<MesProcessBom>> bindKeyPartNoMap = processBomList.stream().filter(o -> null != o).collect(Collectors.groupingBy(MesProcessBom::getItemPartNo));
        List<ProcessBomModel> pbList = null;
        for (MesWorkOrderProcessBom workOrderProcessBom : workOrderProcessBomList) {
            if (null == workOrderProcessBom) continue;
            List<MesProcessBom> itemList = bindKeyPartNoMap.get(workOrderProcessBom.getItemPartNo());
            if (CollectionUtils.isEmpty(itemList)) continue;
            ProcessBomModel pb = new ProcessBomModel();
            BeanUtils.copyProperties(itemList.get(0), pb);
            pb.setQty(workOrderProcessBom.getQty());
            if (CollectionUtils.isEmpty(pbList)) pbList = new ArrayList<>();
            pbList.add(pb);
        }
        return pbList;
    }

    private List<MesProcessBom> getProcessBomListByProcessCodeAndPartNo(String organizeCode, String processCode, String partNo) {
        return processBomRepository.findByProperty(
                new String[]{MesPcnExtConstWords.ORGANIZE_CODE, MesPcnExtConstWords.IS_DELETED, MesPcnExtConstWords.IS_VALID,
                        MesPcnExtConstWords.IS_BIND_KEY, MesPcnExtConstWords.PROCESS_CODE, MesPcnExtConstWords.PART_NO},
                new Object[]{organizeCode, CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(), CommonEnumUtil.IS_VAILD.VAILD.getValue(),
                        CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValue(), processCode, partNo});
    }

    private Boolean checkIsShowKpsnRule(StationRequestBean reqBean) {
        if (!CollectionUtils.isEmpty(reqBean.getWcpcMap()) && reqBean.getWcpcMap().containsKey(SHOW_KPSN_RULE)) return true;
        return false;
    }

    private void restorePbList(StationRequestBean reqBean, List<ProcessBomModel> pbList) {
        List<MesKpsnRule> kpsnRuleList = getKpsnRuleList(reqBean, pbList);
        Map<String, List<MesKpsnRule>> kpsnRuleMap = getKpsnRuleMap(kpsnRuleList);
        if (CollectionUtils.isEmpty(kpsnRuleMap)) return;
        for (ProcessBomModel pb : pbList) {
            List<MesKpsnRule> itemList = kpsnRuleMap.get(pb.getItemPartNo());
            if (CollectionUtils.isEmpty(itemList)) continue;
            pb.setLength(itemList.get(0).getLength());
            pb.setCheckContent(StringUtils.isEmpty(itemList.get(0).getFix1()) ? itemList.get(0).getFix2() : itemList.get(0).getFix1());
        }
    }

    private List<MesKpsnRule> getKpsnRuleList(StationRequestBean reqBean, List<ProcessBomModel> pbList) {
        List<String> itemPartNoList = new ArrayList<>();
        pbList.forEach(p -> itemPartNoList.add(p.getItemPartNo()));
        DdlPackBean packBean = DdlPackBean.getDdlPackBean(reqBean.getOrganizeCode());
        DdlPreparedPack.getInPackList(itemPartNoList, MesPcnExtConstWords.PART_NO, packBean);
        return kpsnRuleRepository.findByHqlWhere(packBean);
    }

    private Map<String, List<MesKpsnRule>> getKpsnRuleMap(List<MesKpsnRule> kpsnRuleList) {
        return CollectionUtils.isEmpty(kpsnRuleList) ? null :
                kpsnRuleList.stream().filter(o -> (null != o && !StringUtils.isEmpty(o.getPartNo()))).collect(Collectors.groupingBy(MesKpsnRule::getPartNo));
    }

    private void checkAndPackPbListIsExistBindedData(StationRequestBean reqBean, WorkOrderExtModel orderModel, List<ProcessBomModel> pbList) {

        List<MesProdBindRecordExt> prodBindRecordList = prodBindRecordExtService.getProdBindRecordExtListByPsOrMc(reqBean.getOrganizeCode(), orderModel.getOrderNo(), reqBean.getWorkCellCode(), reqBean.getProductSn(), getThirdPartyPid(reqBean.getTray()));
        Map<String, List<MesProdBindRecord>> bindedMap = CollectionUtils.isEmpty(prodBindRecordList) ? null :
                prodBindRecordList.stream().filter(o -> (null != o && !StringUtils.isEmpty(o.getItemPartNo()))).collect(Collectors.groupingBy(MesProdBindRecord::getItemPartNo));
        for (ProcessBomModel pb : pbList) {
            if (null == pb) continue;
            if (!CollectionUtils.isEmpty(bindedMap)) {
                if (!bindedMap.containsKey(pb.getItemPartNo())) continue;
                pb.setBoundQty(new Double(bindedMap.get(pb.getItemPartNo()).size()));
                if (MathOperation.compareTo(pb.getBoundQty(), pb.getQty()) >= 0) {
                    pb.setIsBind(true);
                    pb.setIsBindName("是");
                    pb.setColor(MesPcnExtConstWords.GREEN);
                }
            }
        }
    }

    private String getThirdPartyPid(String manageCode) {
        if (StringUtils.isEmpty(manageCode) || !manageCode.contains(MesPcnExtConstWords.AND)) return null;
        return getManageCode(manageCode, 2);
    }

    private String getManageCode(String manageCode, Integer length) {
        if (StringUtils.isEmpty(manageCode)) return null;
        String[] manageCodeArr = manageCode.split(MesPcnExtConstWords.AND);
        if (manageCodeArr.length >= length) return manageCodeArr[length - 1];
        else return null;
    }

    private List<ProcessBomModel> refresh(StationRequestBean reqBean, StationResultBean resultBean, List<ProcessBomModel> pbList) {
        List<AttrBean> attrBeanList = new ArrayList<>();
        PojoAttrUtil.loadPojoAttrs(attrBeanList, MesPcnExtConstWords.ITEM_PART_NO, LocaleUtil.transferLanguage(reqBean.getUserInfo(), "原材料物料号"));
        PojoAttrUtil.loadPojoAttrs(attrBeanList, MesPcnExtConstWords.ITEM_PART_NAME, LocaleUtil.transferLanguage(reqBean.getUserInfo(), "原材料物料名称"));
        PojoAttrUtil.loadPojoAttrs(attrBeanList, MesPcnExtConstWords.QTY, LocaleUtil.transferLanguage(reqBean.getUserInfo(), "需求数量"));
        if (checkIsShowKpsnRule(reqBean)) PojoAttrUtil.loadPojoAttrs(attrBeanList, MesPcnExtConstWords.CHECK_CONTENT, LocaleUtil.transferLanguage(reqBean.getUserInfo(), "校验字符"));
        PojoAttrUtil.loadPojoAttrs(attrBeanList, MesPcnExtConstWords.BOUND_QTY, LocaleUtil.transferLanguage(reqBean.getUserInfo(), "已绑数量"));
        PojoAttrUtil.loadPojoAttrs(attrBeanList, MesPcnExtConstWords.IS_BIND_NAME, LocaleUtil.transferLanguage(reqBean.getUserInfo(), "是否绑定"));

        resultBean.setBusiType(MesPcnEnumUtil.STATION_BUSI_TYPE.STEP_CONTENT.getValue());
        resultBean.setDataType(MesPcnEnumUtil.STATION_DATA_TYPE.TABLE.getValue());
        resultBean.setResultList(pbList);
        resultBean.setDataAttrList(attrBeanList);
        this.sendMessage(reqBean, resultBean);
        return pbList;
    }

    private Boolean checkReloadKeyPartData(StationRequestBean reqBean, StationResultBean resultBean, Object moduleService, Method method, String appendItem) {
        if (!StringUtils.isEmpty(reqBean.getScanInfo()) && !CollectionUtils.isEmpty(reqBean.getWcpcMap()) && reqBean.getWcpcMap().containsKey(RELOAD_KEY_PART_CODE) &&
                !StringUtils.isEmpty(reqBean.getWcpcMap().get(RELOAD_KEY_PART_CODE)) && reqBean.getWcpcMap().get(RELOAD_KEY_PART_CODE).equals(reqBean.getScanInfo())) {
            doHandleBindKeyPartData(reqBean, resultBean, moduleService, method, 3,  appendItem, null);
            this.sendMessage(reqBean, resultBean, "关键件重载码验证成功!即将重载关键件...", MesPcnEnumUtil.STATION_BUSI_TYPE.GUIDE, MesPcnEnumUtil.STATION_DATA_TYPE.TEXT);
            StationRequestBean chReq = new StationRequestBean();
            chReq.setClientInfo(shippingDispatchService.getActorClientInfo(reqBean));
            chReq.setInterfaceType(MesPcnConstWords.SHIPPING);
            chReq.setBusiType(MesPcnConstWords.WS_CMD_DO_SCAN);
            chReq.setUserInfo(reqBean.getUserInfo());
            chReq.setOrganizeCode(reqBean.getOrganizeCode());
            chReq.setWorkCellCode(reqBean.getWorkCellCode());
            chReq.setWorkCenterCode(reqBean.getWorkCenterCode());
            chReq.setTriggerAutoFsm(true);
            shippingDispatchService.doSendScanQueueNextExec(chReq);
            return true;
        }
        return false;
    }

    private Boolean checkIsJumpState(StationRequestBean reqBean, StationResultBean resultBean, Object moduleService, Method method, String appendItem, Boolean flag) {
        if (flag || (!StringUtils.isEmpty(reqBean.getScanInfo()) && !CollectionUtils.isEmpty(reqBean.getWcpcMap()) && reqBean.getWcpcMap().containsKey(VALIDATION_CODE) &&
                !StringUtils.isEmpty(reqBean.getWcpcMap().get(VALIDATION_CODE)) && reqBean.getWcpcMap().get(VALIDATION_CODE).equals(reqBean.getScanInfo()))) {
            doHandleBindKeyPartData(reqBean, resultBean, moduleService, method, 3, appendItem, null);
            return true;
        }
        return false;
    }

    private Object execInit(StationRequestBean reqBean, StationResultBean resultBean, Object moduleService, Method method) {
        this.init(reqBean);
        return doHandleBindKeyPartData(reqBean, resultBean, moduleService, method, 1, MesPcnExtConstWords.BIND_KEY_PART, null);
    }

    private void checkKpsnRule4PbList(StationRequestBean reqBean, StationResultBean resultBean, List<MesKpsnRule> kpsnRuleList, List<ProcessBomModel> pbList, WorkOrderExtModel orderModel) {
        Map<String, List<MesKpsnRule>> kpsnRuleMap = getKpsnRuleMap(kpsnRuleList);
        if (CollectionUtils.isEmpty(kpsnRuleMap)) execExpSendMsgAndThrowEx(reqBean, resultBean, String.format("生产工单[%s]对应的物料编码[%s]所需绑定的关键件物料均未配置关键件条码校验规则", orderModel.getOrderNo(), orderModel.getPartNo()));
        for (ProcessBomModel pb : pbList) {
            if (CollectionUtils.isEmpty(kpsnRuleMap.get(pb.getItemPartNo())))
                execExpSendMsgAndThrowEx(reqBean, resultBean, String.format("生产工单[%s]对应的物料编码[%s]所需绑定的关键件物料[%s]未配置关键件条码校验规则", orderModel.getOrderNo(), orderModel.getPartNo(), pb.getItemPartNo()));
        }
    }

    private Boolean checkPbListIsComplete(StationRequestBean reqBean, StationResultBean resultBean, Object moduleService, Method method, String appendItem, List<ProcessBomModel> pbList, Boolean isCacheFlag) {
        Optional<ProcessBomModel> unBindOpt = pbList.stream().filter(o -> (null != o && !o.getIsBindVal())).findFirst();
        if (null != unBindOpt && unBindOpt.isPresent()) {
            if (isCacheFlag) doHandleBindKeyPartData(reqBean, resultBean, moduleService, method, 2, MesPcnExtConstWords.BIND_KEY_PART, JSONObject.toJSONString(pbList));
            return false;
        } else {
            doHandleBindKeyPartData(reqBean, resultBean, moduleService, method, 3, appendItem, null);
            return true;
        }
    }

    private List<MesKpsnRule> matchKpsnRule4ScanInfo(StationRequestBean reqBean, StationResultBean resultBean, Object moduleService, Method method, List<MesKpsnRule> kpsnRuleList, String suffix) {
        List<MesKpsnRule> okList = null;
        if (!StringUtils.isEmpty(reqBean.getScanInfo())) {
            for (MesKpsnRule item : kpsnRuleList) {
                if (reqBean.getScanInfo().length() != item.getLengthVal()) continue;
                if (!checkIsNotEmpty(item.getFrom1Val(), item.getTo1Val(), item.getFix1())) continue;
                if (!reqBean.getScanInfo().substring(item.getFrom1Val() - 1, item.getTo1Val()).equals(item.getFix1())) continue;
                if (checkIsNotEmpty(item.getFrom2Val(), item.getTo2Val(), item.getFix2()) && !reqBean.getScanInfo().substring(item.getFrom2Val() - 1, item.getTo2Val()).equals(item.getFix2())) continue;

                if (CollectionUtils.isEmpty(okList)) okList = new ArrayList<>();
                okList.add(item);
            }
        }
        if (CollectionUtils.isEmpty(okList)) {
            if (StringUtils.isEmpty(doHandleBindKeyPartData(reqBean, resultBean, moduleService, method, 1, MesPcnExtConstWords.EXEC_BIND_KEY, null))) {
                doHandleBindKeyPartData(reqBean, resultBean, moduleService, method, 2, MesPcnExtConstWords.EXEC_BIND_KEY, CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValueStr());
                execSendGuideAndThrowEx(reqBean, resultBean, String.format("请扫描关键件!当前生产对象:%s", suffix));
            } else {
                if (!StringUtils.isEmpty(reqBean.getScanInfo()))
                    this.sendMessage(reqBean, resultBean, String.format("关键件条码[%s]没有匹配到规则,请检查扫描是否正确!", reqBean.getScanInfo()), MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT);

                execSendGuideAndThrowEx(reqBean, resultBean, String.format("请继续扫描关键件!当前生产对象:%s", suffix));
            }
        }
        return okList;
    }

    private Boolean checkIsNotEmpty(int from, int to, String fix) {
        if (StringUtils.isEmpty(from) || StringUtils.isEmpty(to) || StringUtils.isEmpty(fix)) return false;
        return true;
    }

    private ProcessBomModel getMatchPbData(StationRequestBean reqBean, StationResultBean resultBean, List<ProcessBomModel> pbList, List<MesKpsnRule> okList, String suffix) {
        List<String> okPartNoList = okList.stream().filter(o -> null != o).map(MesKpsnRule::getPartNo).collect(Collectors.toList());
        Optional<ProcessBomModel> pb = pbList.stream().filter(o -> (null != o && okPartNoList.contains(o.getItemPartNo()) && (StringUtils.isEmpty(o.getIsBind()) || !o.getIsBind()))).findFirst();
        if (null == pb || !pb.isPresent()) {
            this.sendMessage(reqBean, resultBean, String.format("与关键件条码[%s]匹配的关键件的绑定数量已达标,操作失败!", reqBean.getScanInfo()), MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT);
            execSendGuideAndThrowEx(reqBean, resultBean, String.format("请继续扫描关键件!当前生产对象:%s", suffix));
        }
        return pb.get();
    }

    private void checkKeyPartIsRepeatBind(StationRequestBean reqBean, StationResultBean resultBean, ProcessBomModel processBomModel, String suffix) {
        if (processBomModel.getIsRepeatVal() == CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValue()) return;
        List<MesProdBindRecord> prodBindRecordDbList = prodBindRecordExtService.getProdBindRecordListByKpSn(reqBean.getOrganizeCode(), reqBean.getScanInfo());
        Optional<MesProdBindRecord> prodBindRecordOp = CollectionUtils.isEmpty(prodBindRecordDbList) ? null :
                prodBindRecordDbList.stream().filter(o -> (null != o && MesPcnExtEnumUtil.MES_ACTION_TYPE.BIND.getValue() == o.getActionType())).findFirst();
        if (null == prodBindRecordOp || !prodBindRecordOp.isPresent()) return;

        this.sendMessage(reqBean, resultBean, String.format("关键件条码[%s]已被绑定过其他产品,操作失败!", reqBean.getScanInfo()), MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT);
        execSendGuideAndThrowEx(reqBean, resultBean, String.format("请继续扫描关键件!当前生产对象:%s", suffix));
    }


    private void insertMesProdBindRecordExt(StationRequestBean reqBean, WorkOrderExtModel orderModel, ProcessBomModel processBomModel, List<MesKpsnRule> okList) {
        MesKpsnRule matchKpsnRule = okList.stream().filter(o -> (null != o && o.getPartNo().equals(processBomModel.getItemPartNo()))).collect(Collectors.toList()).get(0);

        MesProdBindRecordExt pbr = new MesProdBindRecordExt();
        pbr.setWorkOrderNo(orderModel.getOrderNo());
        pbr.setSerialNumber(reqBean.getSerialNumber());
        pbr.setPartNo(orderModel.getPartNo());
        pbr.setWorkCenterCode(reqBean.getWorkCenterCode());
        pbr.setWorkCellCode(reqBean.getWorkCellCode());
        pbr.setItemPartNo(processBomModel.getItemPartNo());
        pbr.setItemPartName(processBomModel.getItemPartName());
        pbr.setKpSn(reqBean.getScanInfo());
        pbr.setKpQty(new Double(1));
        pbr.setIsBindKey(processBomModel.getIsBindKey());
        pbr.setActionType(MesPcnEnumUtil.MES_ACTION_TYPE.BIND.getValue());
        pbr.setOrganizeCode(reqBean.getOrganizeCode());
        pbr.setSupplierCode(matchKpsnRule.getSupplierCode());
        pbr.setProcessCode(processBomModel.getProcessCode());
        pbr.setProcessName(processBomModel.getProcessName());
        pbr.setPartNameRdd(orderModel.getPartNameRdd());
        pbr.setProductSn(reqBean.getProductSn());
        pbr.setManageCode(getManageCode(reqBean.getTray(), 1));
        pbr.setThirdPartyPid(getThirdPartyPid(reqBean.getTray()));
        ConvertBean.serviceModelInitialize(pbr, reqBean.getUserInfo());
        pbr.setLotNo(pbr.getCreateDatetime());
        new ConvertBeanExt(pbr).convertBean(pbr);
        prodBindRecordExtService.insertProdBindRecordExtNoRollback(pbr);
    }

    private void overrideMatchPbData(ProcessBomModel processBomModel) {
        processBomModel.setBoundQty(StringUtils.isEmpty(processBomModel.getBoundQtyVal()) ? new Double(1) : MathOperation.add(processBomModel.getBoundQtyVal(), new Double(1)));
        if (MathOperation.compareTo(processBomModel.getBoundQty(), processBomModel.getQty()) >= 0) {
            processBomModel.setIsBind(true);
            processBomModel.setIsBindName("是");
            processBomModel.setColor(MesPcnExtConstWords.GREEN);
        }
    }

    private Object getModuleService(StationRequestBean reqBean) {
        fsmCommonService.checkWcpcMapForDoScan(reqBean);
        return SpringContextsUtil.getBean(reqBean.getWcpcMap().get(MesPcnConstWords.MODULE_OBJECT));
    }

    private Method getModuleServiceMethod(StationRequestBean reqBean, StationResultBean resultBean, Object moduleService) {
        Method method = null;
        try {
            method = moduleService.getClass().getMethod(MesPcnExtConstWords.doHandleBindKeyPartData, reqBean.getClass(), Integer.class, String.class, String.class);
        } catch (Exception e) {
        }
        if (null == method) execExpSendMsgAndThrowEx(reqBean, resultBean, String.format("展示组件缺失[%s]方法", MesPcnExtConstWords.doHandleBindKeyPartData));
        return method;
    }

    private Object doHandleBindKeyPartData(StationRequestBean reqBean, StationResultBean resultBean, Object moduleService, Method method, Integer flag, String item, String data) {
        Object obj = null;
        try {
            obj = method.invoke(moduleService, reqBean, flag, item, data);
        } catch (Exception e) {
            execExpSendMsgAndThrowEx(reqBean, resultBean, String.format("参数ITEM[%s]FLAG[%s]调用展示组件[%s]方法执行异常:[%s]", item, flag, MesPcnExtConstWords.doHandleBindKeyPartData, e.getMessage()));
        }
        return obj;
    }

    private String getCurExecWorkOrderNo(StationRequestBean reqBean, StationResultBean resultBean, Object moduleService) {

        String curExecWorkOrderNo = null;
        try {
            Method method = moduleService.getClass().getDeclaredMethod(MesPcnExtConstWords.doHandleCurExecWorkOrder, reqBean.getClass(), Integer.class, String.class);
            method.setAccessible(true);
            curExecWorkOrderNo = (String) method.invoke(moduleService, reqBean, 1, null);
        } catch (Exception e) {
            execExpSendMsgAndThrowEx(reqBean, resultBean, String.format("执行展示组件内部方法[%s]参数[flag=1,value=null]出现异常:%s", MesPcnExtConstWords.doHandleCurExecWorkOrder, e.getMessage()));
        }

        if (StringUtils.isEmpty(curExecWorkOrderNo)) execExpSendMsgAndThrowEx(reqBean, resultBean, "此前操作的工单号已丢失,请选择启动状态的生产工单!");
        return curExecWorkOrderNo;
    }

    private WorkOrderExtModel getWorkOrderExtModel(StationRequestBean reqBean, StationResultBean resultBean, String curExecWorkOrderNo) {
        WorkOrderExtModel orderModel = !reqBean.getDataMap().containsKey(MesPcnExtConstWords.WORK_ORDER) ? null :
                JSONObject.parseObject(JSONObject.toJSONString(reqBean.getDataMap().get(MesPcnExtConstWords.WORK_ORDER)), WorkOrderExtModel.class);
        if (null == orderModel) {
            MesWorkOrderExt workOrderExt = workOrderExtService.getWorkOrderExtByOrderNo(reqBean.getOrganizeCode(), curExecWorkOrderNo);
            if (null != workOrderExt) {
                orderModel = new WorkOrderExtModel();
                BeanUtils.copyProperties(workOrderExt, orderModel, MesPcnExtConstWords.ID);
            }
        }
        if (null == orderModel) execExpSendMsgAndThrowEx(reqBean, resultBean, String.format("此前操作的工单号[%s]对应的信息不存在!", curExecWorkOrderNo));
        return orderModel;
    }

}

