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

import cn.estsh.i3plus.ext.mes.pcn.api.base.IProdBindRecordExtService;
import cn.estsh.i3plus.ext.mes.pcn.api.base.IRouteProcessExtService;
import cn.estsh.i3plus.ext.mes.pcn.api.busi.IErrorLineOffService;
import cn.estsh.i3plus.ext.mes.pcn.api.busi.IMissingPartService;
import cn.estsh.i3plus.ext.mes.pcn.api.busi.IProduceSnExtService;
import cn.estsh.i3plus.ext.mes.pcn.pojo.bean.*;
import cn.estsh.i3plus.ext.mes.pcn.pojo.model.ProcessBomModel;
import cn.estsh.i3plus.ext.mes.pcn.pojo.model.bu.BuErrorMessageModel;
import cn.estsh.i3plus.ext.mes.pcn.pojo.model.bu.BuMesKpsnRuleModel;
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.mes.pcn.actor.shipping.dispatch.IFsmCommonService;
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.bean.MesProdRouteOptParam;
import cn.estsh.i3plus.pojo.mes.bean.MesRouteProcess;
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.i3plus.pojo.mes.repository.MesProdBindRecordRepository;
import cn.estsh.impp.framework.boot.util.ImppRedis;
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 javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description : 工步业务-绑定关键件
 * @Reference :
 * @Author : wangjie
 * @CreateDate : 2019-04-18
 * @Modify:
 **/
@Slf4j
@Service("sxBuBindKeyPartStepService")
public class SxBuBindKeyPartStepService extends BaseStepService {

    @Resource(name = MesPcnExtConstWords.REDIS_RES_PCN)
    private ImppRedis redisMesPcn;

    @Autowired
    private MesKpsnRuleRepository kpsnRuleRepository;

    @Autowired
    private IProduceSnExtService produceSnExtService;

    @Autowired
    private MesProdBindRecordRepository prodBindRecordRepository;

    @Autowired
    private IProdBindRecordExtService prodBindRecordExtService;

    @Autowired
    private MesProcessBomRepository processBomRepository;

    @Autowired
    private IShippingDispatchService shippingDispatchService;

    @Autowired
    private IFsmCommonService fsmCommonService;

    @Autowired
    private IMissingPartService missingPartService;

    @Autowired
    private IErrorLineOffService errorLineOffService;

    @Autowired
    private IRouteProcessExtService routeProcessExtService;

    private static final String VALIDATION_CODE = "VALIDATION_CODE";
    private static final String RELOAD_KEY_PART_CODE = "RELOAD_KEY_PART_CODE";
    private static final String EXEC_BIND_KEY = "EXEC_BIND_KEY";
    private static final String MISSING_PART_FLAG = "MISSING_PART_FLAG";
    //补件确认标志
    private static final String FRE_PART_CELL = "FRE_PART_CELL";
    //清空关键件绑定记录
    private static final String CLEAR_KEY_PROD_BIND = "CLEAR_KEY_PROD_BIND";

    @Override
    public StepResult init(StationRequestBean reqBean) {
        log.info("SxBuBindKeyPartStepService[init] ws请求参数 {}", reqBean);
        StationResultBean resultBean = new StationResultBean();
        String err;

        MesProduceSnExt produceSnExt;
        if (reqBean != null && !StringUtils.isEmpty(reqBean.getSerialNumber())) {
            produceSnExt = produceSnExtService.getProduceSnExtBySn(reqBean.getOrganizeCode(), reqBean.getSerialNumber());
            if (produceSnExt == null) {
                err = LocaleUtil.transferLanguage(reqBean.getUserInfo(), "条码在系统中不存在");
                this.sendMessage(reqBean, resultBean, err, MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT);
                return StepResult.getNonComplete(err);
            }
        } else {
            err = LocaleUtil.transferLanguage(reqBean.getUserInfo(), "条码在系统中不存在");
            this.sendMessage(reqBean, resultBean, err, MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT);
            return StepResult.getNonComplete(err);
        }

        String bindKeyPartCacheKey = getCacheKey(reqBean, MesPcnExtConstWords.BIND_KEY_PART);
        List<ProcessBomModel> pbList = (List<ProcessBomModel>) redisMesPcn.getHash(bindKeyPartCacheKey, MesPcnExtConstWords.BIND_KEY_PART);
        if (!CollectionUtils.isEmpty(pbList)) {
            return StepResult.getSuccessComplete();
        }

        pbList = getProcessBomList(reqBean, produceSnExt);

        if (CollectionUtils.isEmpty(pbList)) {
            err = LocaleUtil.transferLanguage(reqBean.getUserInfo(), "没有需要绑定的清单，请维护！");
            this.sendMessage(reqBean, resultBean, err, MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT);
        } else {
            List<String> itemPartNoList = new ArrayList<>();
            pbList = pbList.stream().sorted(Comparator.comparing(ProcessBomModel::getSeq)).collect(Collectors.toList());
            pbList.forEach(p -> itemPartNoList.add(p.getItemPartNo()));
            List<MesKpsnRule> kpsnRuleList = getKpsnRuleList(reqBean, itemPartNoList);
            for (ProcessBomModel pb : pbList) {
                if (!CollectionUtils.isEmpty(kpsnRuleList)) {
                    for (MesKpsnRule mesKpsnRule : kpsnRuleList) {
                        if (mesKpsnRule.getPartNo().equals(pb.getItemPartNo())) {
                            pb.setLength(mesKpsnRule.getLength());
                            pb.setCheckContent(StringUtils.isEmpty(mesKpsnRule.getFix1()) ? mesKpsnRule.getFix2() : mesKpsnRule.getFix1());
                            break;
                        }
                    }
                }
            }

            Optional<Map<String, MesProdRouteOptParam>> stepParamMap = getStepParams(reqBean);
            String missingPartFlag = null;
            if (stepParamMap.isPresent()) {
                MesProdRouteOptParam param = stepParamMap.get().get(MISSING_PART_FLAG);
                if (null != param && !StringUtils.isEmpty(param.getParamValue())) {
                    missingPartFlag = param.getParamValue();
                }
            }

            checkAndPackPbListIsExistBindedData(pbList, reqBean, produceSnExt, missingPartFlag);

            redisMesPcn.putHash(bindKeyPartCacheKey, MesPcnExtConstWords.BIND_KEY_PART, pbList, MesPcnEnumUtil.EXPIRE_TIME.NEVER.getValue());
            this.refresh(reqBean, pbList);
        }
        return StepResult.getSuccessComplete();
    }

    @Override
    public StepResult execute(StationRequestBean reqBean) {
        log.info("SxBuBindKeyPartStepService[execute] ws请求参数 {}", reqBean);
        StationResultBean resultBean = new StationResultBean();
        String err;

        String bindKeyPartCacheKey = getCacheKey(reqBean, MesPcnExtConstWords.BIND_KEY_PART);

        Map<String, String> wcpcMap = fsmCommonService.getCachedWorkCellParam(reqBean);
        if (!CollectionUtils.isEmpty(wcpcMap) && wcpcMap.containsKey(RELOAD_KEY_PART_CODE) && !StringUtils.isEmpty(wcpcMap.get(RELOAD_KEY_PART_CODE)) &&
                !StringUtils.isEmpty(reqBean.getScanInfo()) && wcpcMap.get(RELOAD_KEY_PART_CODE).equals(reqBean.getScanInfo())) {
            redisMesPcn.deleteKey(bindKeyPartCacheKey);
            err = LocaleUtil.transferLanguage(reqBean.getUserInfo(), "关键件重载码验证成功!即将重载关键件...");
            this.sendMessage(reqBean, resultBean, err, 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);
            err = LocaleUtil.transferLanguage(reqBean.getUserInfo(), "重载关键件成功!");
            this.sendMessage(reqBean, resultBean, err, MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.TEXT);
            foundExThrowNoShowMsg();
        }

        List<ProcessBomModel> pbList = (List<ProcessBomModel>) redisMesPcn.getHash(bindKeyPartCacheKey, MesPcnExtConstWords.BIND_KEY_PART);

        Optional<Map<String, MesProdRouteOptParam>> stepParamMap = getStepParams(reqBean);
        if (stepParamMap.isPresent()) {
            MesProdRouteOptParam param1 = stepParamMap.get().get(VALIDATION_CODE);
            if (null != param1 && !StringUtils.isEmpty(param1.getParamValue()) &&
                    !StringUtils.isEmpty(reqBean.getScanInfo()) && param1.getParamValue().equals(reqBean.getScanInfo())) {
                redisMesPcn.deleteKey(bindKeyPartCacheKey);
                return StepResult.getSuccessComplete();
            }
        }

        if (CollectionUtils.isEmpty(pbList)) {
            this.init(reqBean);
            pbList = (List<ProcessBomModel>) redisMesPcn.getHash(bindKeyPartCacheKey, MesPcnExtConstWords.BIND_KEY_PART);
            if (CollectionUtils.isEmpty(pbList)) {
                redisMesPcn.deleteKey(bindKeyPartCacheKey);
                return StepResult.getSuccessComplete();
            }
        } else {
            this.refresh(reqBean, pbList);
        }

        if(StringUtils.isEmpty(reqBean.getScanInfo())){
            err = LocaleUtil.transferLanguage(reqBean.getUserInfo(), "请扫描关键件 !");
            this.sendMessage(reqBean, resultBean, err, MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.TEXT);
            foundExThrowNoShowMsg();
        }

        List<String> itemPartNoList = new ArrayList<>();
        pbList = pbList.stream().sorted(Comparator.comparing(ProcessBomModel::getSeq)).collect(Collectors.toList());
        pbList.forEach(p -> itemPartNoList.add(p.getItemPartNo()));
        List<BuMesKpsnRuleModel> kpsnRuleList = new ArrayList<>();
        for (int index = 0; index < itemPartNoList.size(); index++) {
            List<MesKpsnRule> itemKpsnRuleList = getKpsnRuleList(reqBean, itemPartNoList.get(index));
            if (CollectionUtils.isEmpty(itemKpsnRuleList)) {
                sendMessage(reqBean, resultBean,
                        String.format(LocaleUtil.transferLanguage(reqBean.getUserInfo(), "物料号[%s]未配置关键件条码校验规则"), itemPartNoList.get(index)),
                        MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT);
                foundExThrowNoShowMsg();
            }
            List<ProcessBomModel> finalPbList = pbList;
            int finalIndex = index;
            List<BuMesKpsnRuleModel> finalKpsnRuleList = kpsnRuleList;
            itemKpsnRuleList.stream().forEach(itemKpsnRule -> {
                BuMesKpsnRuleModel model = new BuMesKpsnRuleModel();
                BeanUtils.copyProperties(itemKpsnRule, model);
                model.setSeq(finalPbList.get(finalIndex).getSeq());
                finalKpsnRuleList.add(model);
            });
        }
//        for (String itemPartNo : itemPartNoList) {
//
////            kpsnRuleList.addAll(itemKpsnRuleList);
//        }

        String missingPartFlag = null;
        if (stepParamMap.isPresent()) {
            MesProdRouteOptParam param = stepParamMap.get().get(MISSING_PART_FLAG);
            if (null != param && !StringUtils.isEmpty(param.getParamValue())) {
                missingPartFlag = param.getParamValue();
            }
        }

        List<ProcessBomModel> finalProcessBomModelList;
        if (!StringUtils.isEmpty(missingPartFlag) && missingPartFlag.equals(CommonEnumUtil.IS_VAILD.VAILD.getValueStr())) {
            finalProcessBomModelList = pbList.stream().filter(o -> (null != o && !o.getIsMissingVal())).collect(Collectors.toList());
        } else {
            finalProcessBomModelList = pbList;
        }
        Optional<ProcessBomModel> unBindOpt = CollectionUtils.isEmpty(finalProcessBomModelList) ? null : finalProcessBomModelList.stream().filter(o -> !o.getIsBindVal()).findFirst();
        if (null == unBindOpt || !unBindOpt.isPresent()) {            //所有的待绑定清单都已绑定完毕
            //this.refresh(reqBean, Arrays.asList());
            redisMesPcn.deleteKey(bindKeyPartCacheKey);
            err = String.format(LocaleUtil.transferLanguage(reqBean.getUserInfo(), "产品条码[%s]:关键件绑定完毕!"), reqBean.getSerialNumber());
            this.sendMessage(reqBean, resultBean, err, MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.TEXT);
            return StepResult.getSuccessComplete();
        }

        Optional<ProcessBomModel> bomModelOptional = pbList.stream().filter(processBomModel ->
                !processBomModel.getIsBindVal() && !processBomModel.getIsMissingVal() && processBomModel.getSeq() != 0).min(Comparator.comparing(ProcessBomModel::getSeq));

        ProcessBomModel pbBySeq = bomModelOptional.isPresent() ? bomModelOptional.get() : null;

        String scanInfo = reqBean.getScanInfo();
        List<BuMesKpsnRuleModel> okList = null;
        Map<String, Object> scanCheckMap = new HashMap<>(2);
        if (!StringUtils.isEmpty(scanInfo)) {
            //有序扫描
            for (BuMesKpsnRuleModel item : kpsnRuleList) {
                if(pbBySeq != null && pbBySeq.getItemPartNo().equals(item.getPartNo())){
                    okList = getBuMesKpsnRuleModels(scanInfo, okList, item);
                }
            }

            //缺件关键件扫描（扫描报错提示不可扫描）
            if(CollectionUtils.isEmpty(okList)){
                for (BuMesKpsnRuleModel item : kpsnRuleList) {
                    okList = getBuMesKpsnRuleModels(scanInfo, okList, item);
                }
                scanCheckMap = missingPartScanCheck(pbList, okList);
                if(!CollectionUtils.isEmpty(okList)){
                    okList = null;
                }
            }
            //无序扫描
            if(CollectionUtils.isEmpty(okList)){
                kpsnRuleList = kpsnRuleList.stream().filter(kpsnRuleModel -> kpsnRuleModel.getSeq() == 0).collect(Collectors.toList());
                for (BuMesKpsnRuleModel item : kpsnRuleList) {
                    okList = getBuMesKpsnRuleModels(scanInfo, okList, item);
                }
                if(CollectionUtils.isEmpty(scanCheckMap)){
                    scanCheckMap = missingPartScanCheck(pbList, okList);
                }
            }

        }

        if (CollectionUtils.isEmpty(okList)) {
            Object flag = redisMesPcn.getHash(bindKeyPartCacheKey, EXEC_BIND_KEY);
            if (StringUtils.isEmpty(flag) || !(Boolean) flag) {
                err = LocaleUtil.transferLanguage(reqBean.getUserInfo(), "请扫描关键件！");
                this.sendMessage(reqBean, resultBean, err, MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.TEXT);
                redisMesPcn.putHash(bindKeyPartCacheKey, EXEC_BIND_KEY, true, MesPcnEnumUtil.EXPIRE_TIME.NEVER.getValue());
                foundExThrowNoShowMsg();
            } else {
                BuErrorMessageModel errorMessageModel = new BuErrorMessageModel();
                String errorMessage;
                if(!CollectionUtils.isEmpty(scanCheckMap)){
                    pbBySeq = (ProcessBomModel)scanCheckMap.get("PROCESS_BOM");
                }
                if(pbBySeq != null){
                    if(!CollectionUtils.isEmpty(scanCheckMap)){
                        errorMessage = (String) scanCheckMap.get("ERROR_MESSAGE");
                    }else{
                        errorMessage = String.format("没有匹配到规则，请检查扫描是否正确！当前扫描子物料[%s]序号为[%s]", pbBySeq.getItemPartNo(), (int)pbBySeq.getSeq());
                    }

                    errorMessageModel.setPartNo(pbBySeq.getPartNo());
                    errorMessageModel.setPartNameRdd(pbBySeq.getPartNameRdd());
                    errorMessageModel.setItemPartNo(pbBySeq.getItemPartNo());
                    errorMessageModel.setItemPartName(pbBySeq.getItemPartName());
                }else{
                    errorMessage = "没有匹配到规则，请检查扫描是否正确";
                }
                errorMessageModel.setWorkOrderNo(reqBean.getWorkOrderNo());
                errorMessageModel.setSerialNumber(reqBean.getSerialNumber());
                errorMessageModel.setErrorMessage(errorMessage);
                errorMessageModel.setScanInfo(reqBean.getScanInfo());
                errorMessageModel.setErrorStepCode("sxBuBindKeyPartStepService");
                errorMessageModel.setErrorStepName("关键件绑定工步");
                redisMesPcn.putHash(getCacheKey(reqBean, MesPcnExtConstWords.ERROR_MESSAGE), MesPcnExtConstWords.ERROR_MESSAGE, errorMessageModel, MesPcnEnumUtil.EXPIRE_TIME.NEVER.getValue());
                sendMessage(reqBean, resultBean,
                        LocaleUtil.transferLanguage(reqBean.getUserInfo(), errorMessage),
                        MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT);
                StepResult stepResult = StepResult.getSuccessComplete();
                stepResult.setNextTriggerEvent(CLEAR_KEY_PROD_BIND);
                return stepResult;
            }
        }

        List<String> okPartNoList = okList.stream().filter(o -> null != o).map(BuMesKpsnRuleModel::getPartNo).collect(Collectors.toList());

        Optional<ProcessBomModel> pb;
        if (!StringUtils.isEmpty(missingPartFlag) && missingPartFlag.equals(CommonEnumUtil.IS_VAILD.VAILD.getValueStr())) {
            pb = pbList.stream().filter(o -> (null != o && okPartNoList.contains(o.getItemPartNo()) && (StringUtils.isEmpty(o.getIsBind()) || !o.getIsBind())
                    && (StringUtils.isEmpty(o.getIsMissing()) || !o.getIsMissing()))).findFirst();
        } else {
            pb = pbList.stream().filter(o -> (null != o && okPartNoList.contains(o.getItemPartNo()) && (StringUtils.isEmpty(o.getIsBind()) || !o.getIsBind()))).findFirst();
        }
        if (!pb.isPresent()) {
            sendMessage(reqBean, resultBean,
                    LocaleUtil.transferLanguage(reqBean.getUserInfo(), "绑定数量已满足工位BOM中该关键件的总数量"),
                    MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT);
            foundExThrowNoShowMsg();
        }

        ProcessBomModel processBomModel = pb.get();
        BuMesKpsnRuleModel matchKpsnRuleModel = okList.stream().filter(o -> (null != o && o.getPartNo().equals(processBomModel.getItemPartNo()))).collect(Collectors.toList()).get(0);
        MesKpsnRule matchKpsnRule = new MesKpsnRule();
        BeanUtils.copyProperties(matchKpsnRuleModel, matchKpsnRule);
        //是否可以重复投料
        if (processBomModel.getIsRepeatVal() == CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue()) {
            MesProdBindRecord pbr = prodBindRecordRepository.getByProperty(
                    new String[]{MesPcnExtConstWords.ORGANIZE_CODE, MesPcnExtConstWords.IS_VALID, MesPcnExtConstWords.IS_DELETED,
                            MesPcnExtConstWords.ACTION_TYPE, MesPcnExtConstWords.KP_SN},
                    new Object[]{reqBean.getOrganizeCode(), CommonEnumUtil.IS_VAILD.VAILD.getValue(), CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(),
                            MesPcnEnumUtil.MES_ACTION_TYPE.BIND.getValue(), reqBean.getScanInfo()});
            if (pbr != null) {
                sendMessage(reqBean, resultBean,
                        String.format(LocaleUtil.transferLanguage(reqBean.getUserInfo(), "条码[%s]已被绑定使用过，请确认！"), reqBean.getScanInfo()),
                        MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT);
                foundExThrowNoShowMsg();
            }
        }

        //默认不回滚(下面不满绑定数量会抛异常)
        insertMesProdBindRecordExt(reqBean, processBomModel, matchKpsnRule);

        processBomModel.setLength(matchKpsnRule.getLength());
        processBomModel.setCheckContent(StringUtils.isEmpty(matchKpsnRule.getFix1()) ? matchKpsnRule.getFix2() : matchKpsnRule.getFix1());
        processBomModel.setBoundQty(StringUtils.isEmpty(processBomModel.getBoundQtyVal()) ? 1.0d : processBomModel.getBoundQtyVal() + 1.0d);
        if (MathOperation.compareTo(processBomModel.getBoundQty(), processBomModel.getQty()) >= 0) {
            processBomModel.setIsBind(true);
            processBomModel.setIsBindName("是");
            processBomModel.setColor(MesPcnExtConstWords.GREEN);
        }

        redisMesPcn.putHash(bindKeyPartCacheKey, MesPcnExtConstWords.BIND_KEY_PART, pbList, MesPcnEnumUtil.EXPIRE_TIME.NEVER.getValue());
        this.refresh(reqBean, pbList);
        sendMessage(reqBean, resultBean,
                String.format(LocaleUtil.transferLanguage(reqBean.getUserInfo(), "条码：%s 绑定成功！"), reqBean.getScanInfo()),
                MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.TEXT);

        if (!StringUtils.isEmpty(missingPartFlag) && missingPartFlag.equals(CommonEnumUtil.IS_VAILD.VAILD.getValueStr())) {
            pbList = pbList.stream().filter(o -> (null != o && !o.getIsMissingVal())).collect(Collectors.toList());
        }
        pb = pbList.stream().filter(a -> !a.getIsBindVal()).findFirst();
        if (pb.isPresent()) {            //所有的待绑定清单都已绑定完毕
            err = LocaleUtil.transferLanguage(reqBean.getUserInfo(), "请继续扫描关键件！");
            this.sendMessage(reqBean, resultBean, err, MesPcnEnumUtil.STATION_BUSI_TYPE.GUIDE, MesPcnEnumUtil.STATION_DATA_TYPE.TEXT);

            //不能return false 如果状态点设置了FAILURE 会直接进入下一个状态点 而不是STOP
            foundExThrowNoShowMsg();
        }

        //this.refresh(reqBean, Arrays.asList());
        redisMesPcn.deleteKey(bindKeyPartCacheKey);
        err = String.format(LocaleUtil.transferLanguage(reqBean.getUserInfo(), "产品条码[%s]:关键件绑定完毕!"), reqBean.getSerialNumber());
        this.sendMessage(reqBean, resultBean, err, MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.TEXT);
        return StepResult.getSuccessComplete();
    }

    /**
     * 缺件关间件扫描检查
     * @param pbList
     * @param okList
     */
    private Map<String, Object> missingPartScanCheck(List<ProcessBomModel> pbList, List<BuMesKpsnRuleModel> okList) {
        Map<String, Object> resultMap = new HashMap<>();
        if(!CollectionUtils.isEmpty(pbList) && !CollectionUtils.isEmpty(okList)){
            List<ProcessBomModel> finalPbList = pbList;
            okList.stream().forEach(item -> {
                finalPbList.stream().forEach(processBomModel -> {
                    if(item.getPartNo().equals(processBomModel.getItemPartNo()) && processBomModel.getIsMissingVal()){
                        resultMap.put("ERROR_MESSAGE", String.format("当前扫描关键件已缺件，请扫下一个！当前子物料[%s]序号为[%s]", item.getPartNo(), item.getSeq()));
                        resultMap.put("PROCESS_BOM", processBomModel);
//                        sendMessage(reqBean, resultBean,
//                                LocaleUtil.transferLanguage(reqBean.getUserInfo(), "当前关键件已缺件，请扫下一个！"),
//                                MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT);
//                        foundExThrowNoShowMsg();
                    }
                });
            });
        }
        return resultMap;
    }

    private List<BuMesKpsnRuleModel> getBuMesKpsnRuleModels(String scanInfo, List<BuMesKpsnRuleModel> okList, BuMesKpsnRuleModel item) {
        if (scanInfo.length() != item.getLengthVal()) {
            return okList;
        }
        if (!scanInfo.substring(item.getFrom1Val() - 1, item.getTo1Val()).equals(item.getFix1())) {
            return okList;
        }
        if (item.getFrom2Val() != 0 && item.getTo2Val() != 0 && !StringUtils.isEmpty(item.getFix2())) {
            if (!scanInfo.substring(item.getFrom2Val() - 1, item.getTo2Val()).equals(item.getFix2())) {
                return okList;
            }
        }
        if (CollectionUtils.isEmpty(okList)) {
            okList = new ArrayList<>();
        }
        okList.add(item);
        return okList;
    }

    private void insertMesProdBindRecordExt(StationRequestBean reqBean, ProcessBomModel processBomModel, MesKpsnRule matchKpsnRule) {
        MesProduceSnExt produceSnExt = produceSnExtService.getProduceSnExtBySn(reqBean.getOrganizeCode(), reqBean.getSerialNumber());
        MesProdBindRecordExt pbr = new MesProdBindRecordExt();
        pbr.setWorkOrderNo(produceSnExt.getWorkOrderNo());
        pbr.setSerialNumber(produceSnExt.getSerialNumber());
        pbr.setPartNo(produceSnExt.getPartNo());
        pbr.setWorkCenterCode(reqBean.getWorkCenterCode());
        pbr.setWorkCellCode(reqBean.getWorkCellCode());
        pbr.setItemPartNo(processBomModel.getItemPartNo());
        pbr.setItemPartName(processBomModel.getItemPartName());
        pbr.setKpSn(reqBean.getScanInfo());
        pbr.setKpQty(1.0d);
        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());
        ConvertBean.serviceModelInitialize(pbr, reqBean.getUserInfo());
        new ConvertBeanExt(pbr).convertBean(pbr);
        prodBindRecordExtService.insertProdBindRecordExtNoRollback(pbr);
    }

    @Override
    public StepResult jumpStep(StationRequestBean reqBean) {
        String bindKeyPartCacheKey = getCacheKey(reqBean, MesPcnExtConstWords.BIND_KEY_PART);
        redisMesPcn.deleteKey(bindKeyPartCacheKey);
        return super.jumpStep(reqBean);
    }

    private void refresh(StationRequestBean reqBean, List<ProcessBomModel> pbList) {
        List<AttrBean> attrBeanList = new ArrayList<>();
        PojoAttrUtil.loadPojoAttrs(attrBeanList, MesPcnExtConstWords.SEQ, LocaleUtil.transferLanguage(reqBean.getUserInfo(), "序号"));
        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(), "需求数量"));
//        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(), "是否绑定"));

        StationResultBean resultBean = new StationResultBean();
        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);
    }

    private List<ProcessBomModel> getProcessBomList(StationRequestBean reqBean, MesProduceSnExt produceSnExt) {
        List<ProcessBomModel> pbList = null;
        List<MesProcessBom> processBomList = new ArrayList<>();

        Map<String, String> wcpcMap = fsmCommonService.getCachedWorkCellParam(reqBean);
        if (CollectionUtils.isEmpty(wcpcMap) || !wcpcMap.containsKey(FRE_PART_CELL)) {
            processBomList = getProcessBomListByProcessCodeAndPartNo(reqBean.getOrganizeCode(), reqBean.getProcessCode(), produceSnExt.getPartNo());
            if (CollectionUtils.isEmpty(processBomList)) {
                return pbList;
            }

            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);
            }
        } else {
            List<MesErrorLineOffDetail> errorLineOffDetailList = errorLineOffService
                    .getErrorLineOffDetailListBySnAndOrder(reqBean.getOrganizeCode(), produceSnExt.getSerialNumber(), produceSnExt.getWorkOrderNo());
            if (!CollectionUtils.isEmpty(errorLineOffDetailList)) {

                List<MesRouteProcess> routeProcessList = routeProcessExtService.getRouteProcessByRoute(reqBean.getOrganizeCode(), reqBean.getRouteCode());
                for (MesRouteProcess routeProcess : routeProcessList) {
                    if (null == routeProcess) {
                        continue;
                    }
                    processBomList.addAll(getProcessBomListByProcessCodeAndPartNo(reqBean.getOrganizeCode(), routeProcess.getProcessCode(), produceSnExt.getPartNo()));
                }

                Map<String, List<MesProcessBom>> bindKeyPartNoMap = CollectionUtils.isEmpty(processBomList) ? null :
                        processBomList.stream().filter(o -> null != o).collect(Collectors.groupingBy(MesProcessBom::getItemPartNo));
                errorLineOffDetailList = errorLineOffDetailList.stream()
                        .filter(o -> (null != o && !CollectionUtils.isEmpty(bindKeyPartNoMap) && bindKeyPartNoMap.containsKey(o.getItemPartNo()))).collect(Collectors.toList());
                if (!CollectionUtils.isEmpty(errorLineOffDetailList)) {
                    for (MesErrorLineOffDetail errorLineOffDetail : errorLineOffDetailList) {
                        if (null == errorLineOffDetail) {
                            continue;
                        }
                        List<MesProcessBom> itemList = bindKeyPartNoMap.get(errorLineOffDetail.getItemPartNo());
                        ProcessBomModel pb = new ProcessBomModel();
                        BeanUtils.copyProperties(itemList.get(0), pb);
                        pb.setQty(itemList.stream().filter(o -> (null != o && !StringUtils.isEmpty(o.getQty()))).mapToDouble(MesProcessBom::getQty).sum());
                        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 List<MesKpsnRule> getKpsnRuleList(StationRequestBean reqBean, List<String> itemPartNoList) {
        DdlPackBean packBean = DdlPackBean.getDdlPackBean(reqBean.getOrganizeCode());
        DdlPreparedPack.getInPackList(itemPartNoList, MesPcnExtConstWords.PART_NO, packBean);
        return kpsnRuleRepository.findByHqlWhere(packBean);
    }

    private List<MesKpsnRule> getKpsnRuleList(StationRequestBean reqBean, String itemPartNo) {
        DdlPackBean packBean = DdlPackBean.getDdlPackBean(reqBean.getOrganizeCode());
        DdlPreparedPack.getStringEqualPack(itemPartNo, MesPcnExtConstWords.PART_NO, packBean);
        return kpsnRuleRepository.findByHqlWhere(packBean);
    }

    private void checkAndPackPbListIsExistBindedData(List<ProcessBomModel> pbList, StationRequestBean reqBean, MesProduceSnExt produceSnExt, String missingPartFlag) {
        List<MesProdBindRecord> prodBindRecordList = prodBindRecordExtService
                .getProdBindRecordList(reqBean.getOrganizeCode(), produceSnExt.getWorkOrderNo(), produceSnExt.getSerialNumber(), reqBean.getWorkCellCode());
        List<String> missingPartNoList = null;
        if (!StringUtils.isEmpty(missingPartFlag)) {
            if (missingPartFlag.equals(CommonEnumUtil.IS_VAILD.VAILD.getValueStr())) {
                //正常绑定关键件工位突出显示缺件的数据（在下面的逻辑中体现）
                List<MesMissingPart> missingPartList = missingPartService.getMissingPartByWorkOrderNo(reqBean.getOrganizeCode(), produceSnExt.getWorkOrderNo());
                missingPartNoList = CollectionUtils.isEmpty(missingPartList) ? new ArrayList<>() :
                        missingPartList.stream().filter(o -> (null != o && !StringUtils.isEmpty(o.getItemPartNo()))).map(MesMissingPart::getItemPartNo).collect(Collectors.toList());
            } else {
                //缺件：pbList数据就是已缺件数据
                missingPartNoList = pbList.stream().filter(o -> (null != o && !StringUtils.isEmpty(o.getItemPartNo()))).map(ProcessBomModel::getItemPartNo).collect(Collectors.toList());
            }
        }

        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 (!StringUtils.isEmpty(missingPartFlag) && missingPartNoList.contains(pb.getItemPartNo())) {
                pb.setIsMissing(true);
                pb.setIsBindName("缺件");
                pb.setColor(MesPcnExtConstWords.YELLOW);
            }
            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);
                }
            }
        }
    }

}

