package cn.estsh.i3plus.ext.mes.pcn.apiservice.actor.shipping.strategy;

import cn.estsh.i3plus.mes.pcn.actor.shipping.FiniteStateMachineActor;
import cn.estsh.i3plus.mes.pcn.actor.shipping.dispatch.IFsmCommonService;
import cn.estsh.i3plus.mes.pcn.actor.shipping.dispatch.IFsmDispatchService;
import cn.estsh.i3plus.mes.pcn.actor.shipping.strategy.IActorReceiveStrategy;
import cn.estsh.i3plus.mes.pcn.api.iservice.base.IModuleService;
import cn.estsh.i3plus.mes.pcn.api.iservice.base.IPartService;
import cn.estsh.i3plus.mes.pcn.api.iservice.base.IProduceErrorRecordService;
import cn.estsh.i3plus.mes.pcn.api.iservice.base.IProduceSnService;
import cn.estsh.i3plus.mes.pcn.api.iservice.busi.IShippingDispatchService;
import cn.estsh.i3plus.mes.pcn.util.LocaleUtil;
import cn.estsh.i3plus.mes.pcn.websocket.StationWebSocket;
import cn.estsh.i3plus.platform.common.convert.ConvertBean;
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.*;
import cn.estsh.i3plus.pojo.mes.model.StationRequestBean;
import cn.estsh.i3plus.pojo.mes.repository.MesStepGroupRepository;
import cn.estsh.i3plus.pojo.mes.repository.MesWorkCellParamCfgRepository;
import cn.estsh.impp.framework.boot.exception.ImppBusiException;
import cn.estsh.impp.framework.boot.util.SpringContextsUtil;
import com.google.common.util.concurrent.*;
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 org.squirrelframework.foundation.fsm.UntypedStateMachine;
import org.squirrelframework.foundation.fsm.UntypedStateMachineBuilder;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ExecutorService;
import java.util.stream.Collectors;

/**
 * 执行扫描
 * @author wangjie
 * @date 2020/6/15 09:55
 * @desc
 */
@Slf4j
@Service
public class ActorReceiveStrategyScanExtService implements IActorReceiveStrategy {

    @Autowired
    private IFsmCommonService fsmCommonService;

    @Autowired
    private IFsmDispatchService fsmDispatchService;

    @Autowired
    private MesWorkCellParamCfgRepository workCellParamCfgRepository;

    @Autowired
    private IProduceSnService produceSnService;

    @Autowired
    private IPartService partService;

    @Autowired
    private IProduceErrorRecordService produceErrorRecordService;

    @Autowired
    private MesStepGroupRepository stepGroupRepository;

    @Autowired
    private IShippingDispatchService shippingDispatchService;

    @Autowired
    private ExecutorService executorService;

    @Override
    public void exec(StationRequestBean requestBean) {
        try {
            if (islog(requestBean))
                log.info("工厂{}生产线{}工位{}:ACTOR SCAN --- START ---", requestBean.getOrganizeCode(), requestBean.getWorkCenterCode(), requestBean.getWorkCellCode());

            checkScanInfoIsNotNull(requestBean);
            StationRequestBean chReq = fsmCommonService.getCachedStationRequestBean(requestBean);

            if (chReq == null) {
                chReq = new StationRequestBean();
                BeanUtils.copyProperties(requestBean, chReq);
            } else {
                // 添加一些新的可能改变的元素
                fsmCommonService.assembleReqBeanChangingValue(requestBean, chReq);
                chReq.setStepDialogStatus(requestBean.getStepDialogStatus());
            }

            //前置校验WcpcMap场景:taskComplete时,状态机onSuccess时解锁,如果此时存在未处理的扫描队列,前端init到后端的执行速度会偶发晚于后端自动执行的的doScan,
            //此时StationRequestBean对象为null,缓存中没有WcpcMap数据,需要直接查库
            fsmCommonService.checkWcpcMapForDoScan(chReq);

            if (islog(requestBean))
                log.info("工厂{}生产线{}工位{}:ACTOR SCAN --- EXEC --- 1 ---- ", requestBean.getOrganizeCode(), requestBean.getWorkCenterCode(), requestBean.getWorkCellCode());

            //校验工位必备参数[MODULE_OBJECT]
            String moduleObject = fsmCommonService.getAndCheckWcpcMapIsContainsKey(requestBean, chReq.getWcpcMap(), MesPcnConstWords.MODULE_OBJECT);
            if (StringUtils.isEmpty(moduleObject)) {

                log.info("工厂{}生产线{}工位{}:UN LOCK START --- SOURCE[StrategyScan-ModuleObject] --- StationRequestBean[{}]",
                        chReq.getOrganizeCode(), chReq.getWorkCenterCode(), chReq.getWorkCellCode(), chReq.toString());

                shippingDispatchService.doScanQueueUnLock(requestBean.getOrganizeCode(), fsmCommonService.getFsmCacheKey(requestBean), chReq);
                return;
            }

            if (islog(requestBean))
                log.info("工厂{}生产线{}工位{}:ACTOR SCAN --- EXEC --- 2 ---- ", requestBean.getOrganizeCode(), requestBean.getWorkCenterCode(), requestBean.getWorkCellCode());

            // 初始化运行时的数据
            if (!initRuntimeValue(chReq)) return;

            if (islog(requestBean))
                log.info("工厂{}生产线{}工位{}:ACTOR SCAN --- EXEC --- 3 ---- ", requestBean.getOrganizeCode(), requestBean.getWorkCenterCode(), requestBean.getWorkCellCode());

            // 找到流程状态
            List<MesStateMachineStatus> statuses = fsmCommonService.getFsmRouteStatus(chReq);

            if (islog(requestBean))
                log.info("工厂{}生产线{}工位{}:ACTOR SCAN --- EXEC --- 4 ---- ", requestBean.getOrganizeCode(), requestBean.getWorkCenterCode(), requestBean.getWorkCellCode());

            //校验状态机流程的有效性
            if (!fsmCommonService.checkFsmValid(chReq, statuses)) {

                log.info("工厂{}生产线{}工位{}:UN LOCK START --- SOURCE[StrategyScan-checkFsmValid] --- StationRequestBean[{}]",
                        chReq.getOrganizeCode(), chReq.getWorkCenterCode(), chReq.getWorkCellCode(), chReq.toString());

                shippingDispatchService.doScanQueueUnLock(requestBean.getOrganizeCode(), fsmCommonService.getFsmCacheKey(requestBean), chReq);
                return;
            }
            // 初始化状态机
            UntypedStateMachineBuilder stateMachineBuilder = FiniteStateMachineActor.buildFsm(chReq.getUserInfo(), statuses);

            if (islog(requestBean))
                log.info("工厂{}生产线{}工位{}:ACTOR SCAN --- EXEC --- 5 ---- ", requestBean.getOrganizeCode(), requestBean.getWorkCenterCode(), requestBean.getWorkCellCode());

            //封装流程工序状态机到StationRequestBean
            fsmCommonService.packChReqRouteProcessState(chReq, statuses);

            if (islog(requestBean))
                log.info("工厂{}生产线{}工位{}:ACTOR SCAN --- EXEC --- 6 ---- ", requestBean.getOrganizeCode(), requestBean.getWorkCenterCode(), requestBean.getWorkCellCode());

            //根据命令转换bean
            changeStateByCmdType(chReq);

            if (islog(requestBean))
                log.info("工厂{}生产线{}工位{}:ACTOR SCAN --- EXEC --- 7 ---- ", requestBean.getOrganizeCode(), requestBean.getWorkCenterCode(), requestBean.getWorkCellCode());

            //上一行代码已经在执行跳过工序逻辑
            if (!StringUtils.isEmpty(chReq.getForceJumpProcess()) && chReq.getForceJumpProcess()) {

                log.info("工厂{}生产线{}工位{}:UN LOCK START --- SOURCE[StrategyScan-ForceJumpProcess] --- StationRequestBean[{}]",
                        chReq.getOrganizeCode(), chReq.getWorkCenterCode(), chReq.getWorkCellCode(), chReq.toString());

                shippingDispatchService.doScanQueueUnLock(requestBean.getOrganizeCode(), fsmCommonService.getFsmCacheKey(requestBean), chReq);
                return;
            }

            if (islog(requestBean))
                log.info("工厂{}生产线{}工位{}:ACTOR SCAN --- EXEC --- 8 ---- ", requestBean.getOrganizeCode(), requestBean.getWorkCenterCode(), requestBean.getWorkCellCode());

            if (null == chReq.getCurFsmState()) {
                Optional<MesStateMachineStatus> firstStateOption = fsmCommonService.getFirstState(chReq.getFsmStates());
                if (null != firstStateOption && firstStateOption.isPresent()) {
                    chReq.setCurFsmState(fsmCommonService.copyFsmState(firstStateOption.get()));
                }

                if (islog(requestBean))
                    log.info("工厂{}生产线{}工位{}:ACTOR SCAN --- EXEC --- 8.1 ---- ", requestBean.getOrganizeCode(), requestBean.getWorkCenterCode(), requestBean.getWorkCellCode());

            }

            if (islog(requestBean))
                log.info("工厂{}生产线{}工位{}:ACTOR SCAN --- EXEC --- 9 ---- ", requestBean.getOrganizeCode(), requestBean.getWorkCenterCode(), requestBean.getWorkCellCode());


            fireStateMachine(stateMachineBuilder, fsmCommonService.getFsmCacheKey(chReq), chReq);

            if (islog(requestBean))
                log.info("工厂{}生产线{}工位{}:ACTOR SCAN --- EXEC --- 10 ---- ", requestBean.getOrganizeCode(), requestBean.getWorkCenterCode(), requestBean.getWorkCellCode());

        } catch (Exception ex) {

            if (islog(requestBean))
                log.info("工厂{}生产线{}工位{}:ACTOR SCAN --- EXEC --- 11 ---- ", requestBean.getOrganizeCode(), requestBean.getWorkCenterCode(), requestBean.getWorkCellCode());

            log.error(ex.getMessage());
            StationWebSocket.sendMessage(requestBean, LocaleUtil.transferLanguage(requestBean.getUserInfo(), ex.getMessage()),
                    MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT);
            shippingDispatchService.doScanQueueUnLock(requestBean.getOrganizeCode(), fsmCommonService.getFsmCacheKey(requestBean), requestBean);
        }
    }

    private Boolean islog(StationRequestBean requestBean) {
        if (!StringUtils.isEmpty(requestBean.getWorkCellCode()) &&
                (requestBean.getWorkCellCode().equals("BIK1-25") || requestBean.getWorkCellCode().equals("BIK2-31") || requestBean.getWorkCellCode().equals("EB1-29")))
            return true;
        else
            return false;
    }

    public synchronized void fireStateMachine(UntypedStateMachineBuilder builder, String fsmCacheKey, StationRequestBean requestBean) {
        if (null == requestBean.getCurFsmState()) {
            if (islog(requestBean))
                log.info("工厂{}生产线{}工位{}:ACTOR SCAN --- EXEC --- 9.0 ---- ", requestBean.getOrganizeCode(), requestBean.getWorkCenterCode(), requestBean.getWorkCellCode());
            return;
        }

        if (islog(requestBean))
            log.info("工厂{}生产线{}工位{}:ACTOR SCAN --- EXEC --- 9.1 ---- ", requestBean.getOrganizeCode(), requestBean.getWorkCenterCode(), requestBean.getWorkCellCode());

        FiniteStateMachineActor.cancelRemoveTask(fsmCacheKey);

        if (islog(requestBean))
            log.info("工厂{}生产线{}工位{}:ACTOR SCAN --- EXEC --- 9.2 ---- ", requestBean.getOrganizeCode(), requestBean.getWorkCenterCode(), requestBean.getWorkCellCode());

        UntypedStateMachine fsm = builder.newStateMachine(requestBean.getCurFsmState().getStatusCode());

        if (islog(requestBean))
            log.info("工厂{}生产线{}工位{}:ACTOR SCAN --- EXEC --- 9.3 ---- ", requestBean.getOrganizeCode(), requestBean.getWorkCenterCode(), requestBean.getWorkCellCode());

        //状态机监听回调
        FiniteStateMachineActor.getFsmListenerServiceMap().forEach((k, v) -> v.exec(fsm, requestBean));

        if (islog(requestBean))
            log.info("工厂{}生产线{}工位{}:ACTOR SCAN --- EXEC --- 9.4 ---- ", requestBean.getOrganizeCode(), requestBean.getWorkCenterCode(), requestBean.getWorkCellCode());

        fsmCommonService.putStationRequestBean(requestBean, "FsmDispatchService:fireStateMachine");

        ListeningExecutorService listenExecutor = MoreExecutors.listeningDecorator(executorService);
        // 异步回调
        ListenableFuture<Object> listenFuture = ListenableFutureTask.create(() -> {

            if (islog(requestBean))
                log.info("工厂{}生产线{}工位{}:ACTOR SCAN --- EXEC --- 9.5 ---- ", requestBean.getOrganizeCode(), requestBean.getWorkCenterCode(), requestBean.getWorkCellCode());

            fsm.fire(requestBean.getCurFsmState().getTriggerEvent(), requestBean);
            return null;
        });
        FiniteStateMachineActor.addTask(fsmCacheKey, listenFuture);
        listenExecutor.submit((ListenableFutureTask) listenFuture);

        if (islog(requestBean))
            log.info("工厂{}生产线{}工位{}:ACTOR SCAN --- EXEC --- 9.6 ---- ", requestBean.getOrganizeCode(), requestBean.getWorkCenterCode(), requestBean.getWorkCellCode());

        Futures.addCallback(listenFuture, new FutureCallback<Object>() {
            @Override
            public void onSuccess(Object result) {
                doFireStateMachineOnSuccess(requestBean);

                log.info("工厂{}生产线{}工位{}:UN LOCK START --- SOURCE[fireStateMachine-onSuccess] --- StationRequestBean[{}]",
                        requestBean.getOrganizeCode(), requestBean.getWorkCenterCode(), requestBean.getWorkCellCode(), requestBean.toString());

                shippingDispatchService.doScanQueueUnLock(requestBean.getOrganizeCode(), fsmCacheKey, requestBean);
                log.info("[{}]状态机执行完成", fsmCacheKey);
            }

            @Override
            public void onFailure(Throwable t) {

                log.info("工厂{}生产线{}工位{}:UN LOCK START --- SOURCE[fireStateMachine-onFailure] --- StationRequestBean[{}]",
                        requestBean.getOrganizeCode(), requestBean.getWorkCenterCode(), requestBean.getWorkCellCode(), requestBean.toString());

                shippingDispatchService.doScanQueueUnLock(requestBean.getOrganizeCode(), fsmCacheKey, requestBean);
                log.error("[{}]状态机执行发生错误：{}", fsmCacheKey, t.getMessage());
            }
        }, listenExecutor);
    }

    private void doFireStateMachineOnSuccess(StationRequestBean requestBean) {
        StationRequestBean cachedRequestBean = fsmCommonService.getCachedStationRequestBean(requestBean);

        if (MesPcnEnumUtil.STATUS_TYPE.FINISH.getValue() == cachedRequestBean.getCurFsmState().getStatusType()) {
            try {
                doStatesCompleted(requestBean);
            } catch (Exception ex) {
                log.info("doFireStateMachineOnSuccess 执行异常:{}", ex.getMessage());
            }
        }

    }

    public void doStatesCompleted(StationRequestBean requestBean) {
        doModule(fsmCommonService.getCachedStationRequestBean(requestBean));
        fsmCommonService.flushCache(requestBean);
        // 清除不允许开启监听
        String allowStartKey = fsmCommonService.getFsmCacheKey(requestBean, MesPcnConstWords.ALLOW_START_MONITOR, MesPcnConstWords.SHIPPING_ACTOR_SUFFIX);
        FiniteStateMachineActor.removeAllowStartMonitorMap(allowStartKey);
        StationWebSocket.sendMessage(requestBean, "状态点都已完成，请继续", MesPcnEnumUtil.STATION_BUSI_TYPE.TASK_COMPLETE,
                MesPcnEnumUtil.STATION_DATA_TYPE.TEXT);
    }

    public void doModule(StationRequestBean requestBean) {
        IModuleService moduleService;
        Map<String, String> wcpcMap = fsmCommonService.getCachedWorkCellParam(requestBean);
        if (CollectionUtils.isEmpty(wcpcMap)) {
            StationWebSocket.sendMessage(requestBean, LocaleUtil.transferLanguage(requestBean.getUserInfo(),
                    "没有找到工作单元参数，请联系运维人员！"),
                    MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT);
            return;
        }
        if (StringUtils.isEmpty(wcpcMap.get(MesPcnConstWords.MODULE_OBJECT))) {
            StationWebSocket.sendMessage(requestBean, LocaleUtil.transferLanguage(requestBean.getUserInfo(),
                    "工作单元参数{ModuleObject}未维护生产组件！"),
                    MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT);
            return;
        }
        moduleService = (IModuleService) SpringContextsUtil.getBean(wcpcMap.get(MesPcnConstWords.MODULE_OBJECT));
        moduleService.execute(requestBean);
    }

    /**
     * 判断scanInfo是否为空，并且当强制执行的工步信息为空时，报错，说明是一个错误的输入
     * x
     *
     * @param requestBean
     */
    private void checkScanInfoIsNotNull(StationRequestBean requestBean) {
        if (StringUtils.isEmpty(requestBean.getScanInfo()) && StringUtils.isEmpty(requestBean.getForceSpecStepCode())
                && StringUtils.isEmpty(requestBean.getButtonCode()) && !requestBean.getForceJumpProcess() && !requestBean.getTriggerAutoFsm()) {
            String err = LocaleUtil.transferLanguage(requestBean.getUserInfo(),
                    "无效的扫描信息，没有如下内容（扫描信息，强制执行,工步按钮）");
            StationWebSocket.sendMessage(requestBean, err, MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT);
            throw new ImppBusiException(err);
        }
    }

    /**
     * 初始化{@link StationRequestBean}运行参数
     * 初始化工作单元参数，初始化并缓存第一次扫描的缓存
     *
     * @param requestBean
     */
    private Boolean initRuntimeValue(StationRequestBean requestBean) {
        initWorkCellParam(requestBean);

        String loadType = fsmCommonService.getAndCheckWcpcMapIsContainsKey(requestBean, requestBean.getWcpcMap(), MesPcnConstWords.LOAD_FSM_ROUTE_TYPE);
        if (StringUtils.isEmpty(loadType)) {
            if (islog(requestBean))
                log.info("工厂{}生产线{}工位{}:ACTOR SCAN --- EXEC --- 2.1 ---- ", requestBean.getOrganizeCode(), requestBean.getWorkCenterCode(), requestBean.getWorkCellCode());
            return false;
        }

        boolean isFirstInit = false;
        if (fsmCommonService.getCachedFirstScanKey(requestBean) == null) {
            isFirstInit = true;
        }
        if (loadType.equals(MesPcnEnumUtil.LOAD_FSM_ROUTE_TYPE.BY_AUTO.getValue())) {
            //执行第一次扫描的组件方法
            if (isFirstInit) {

                if (islog(requestBean))
                    log.info("工厂{}生产线{}工位{}:ACTOR SCAN --- EXEC --- 2.2 ---- ", requestBean.getOrganizeCode(), requestBean.getWorkCenterCode(), requestBean.getWorkCellCode());

                fsmDispatchService.doModuleFirstScan(requestBean.getWcpcMap(), requestBean);
            }
            //自动加载不需要设置任何值
            fsmCommonService.putFirstScanKey(requestBean, requestBean);
//            fsmCommonService.putFirstScanKey(requestBean, requestBean, "cn.estsh.i3plus.pojo.mes.model.StationRequestBean");
        } else if (loadType.equals(MesPcnEnumUtil.LOAD_FSM_ROUTE_TYPE.BY_PART.getValue())) {
            MesProduceSn produceSn = initProduceSn(requestBean);
            MesPart part;
            if (null == produceSn) {
                part = initPart(requestBean);
                if (null == part) {
                    String err = LocaleUtil.transferLanguage(requestBean.getUserInfo(), "扫描内容不是过程条码或零件号");
                    StationWebSocket.sendMessage(requestBean, err, MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT);
                    return false;
                }
                requestBean.setPartNo(part.getPartNo());
                requestBean.setPptCode(part.getPptCode());
                fsmCommonService.putFirstScanKey(requestBean, part);
//                fsmCommonService.putFirstScanKey(requestBean, part, "cn.estsh.i3plus.pojo.mes.bean.MesPart");
            } else {
                requestBean.setSerialNumber(produceSn.getSerialNumber());
                requestBean.setWorkOrderNo(produceSn.getWorkOrderNo());
                requestBean.setPartNo(produceSn.getPartNo());
                part = partService.getPartByNo(requestBean.getOrganizeCode(), produceSn.getPartNo());
                if (null != part) {
                    requestBean.setPptCode(part.getPptCode());
                }
                fsmCommonService.putFirstScanKey(requestBean, produceSn);
//                fsmCommonService.putFirstScanKey(requestBean, produceSn, "cn.estsh.i3plus.pojo.mes.bean.MesProduceSn");
            }
        }
        return true;
    }

    /**
     * 根据不同的cmd命令 变化当前State
     *
     * @param requestBean
     * @return
     */
    private StationRequestBean changeStateByCmdType(StationRequestBean requestBean) {
        String shippingCmd;
        //判断是跳过还是强制执行 如果都不是就返回最原始的requestBean
        String jumpStateParam = requestBean.getWcpcMap().get(MesPcnEnumUtil.STATION_REQUEST_BEAN_CMD.JUMP_STATE.getCode());
        if (!StringUtils.isEmpty(jumpStateParam) && jumpStateParam.equals(requestBean.getScanInfo())) {
            shippingCmd = MesPcnEnumUtil.STATION_REQUEST_BEAN_CMD.JUMP_STATE.getCode();
        } else if (!StringUtils.isEmpty(requestBean.getForceSpecStepCode())) {
            shippingCmd = MesPcnEnumUtil.STATION_REQUEST_BEAN_CMD.FORCE_STATE.getCode();
        } else if (requestBean.getForceJumpProcess()) {
            shippingCmd = MesPcnEnumUtil.STATION_REQUEST_BEAN_CMD.FORCE_JUMP_PROCESS.getCode();
        } else {
            return requestBean;
        }

        if (islog(requestBean))
            log.info("工厂{}生产线{}工位{}:ACTOR SCAN --- EXEC --- 6.1 ---- ", requestBean.getOrganizeCode(), requestBean.getWorkCenterCode(), requestBean.getWorkCellCode());

        Optional<MesStateMachineStatus> nextStatusOpt = null;
        if (shippingCmd.equals(MesPcnEnumUtil.STATION_REQUEST_BEAN_CMD.JUMP_STATE.getCode())) {
            if (null != requestBean.getCurFsmState()) {
                List<MesStateMachineStatus> nextStatusList = requestBean.getFsmStates().stream()
                        .filter(o -> (null != o && o.getStatusCode().equals(requestBean.getCurFsmState().getNextStatus()))).collect(Collectors.toList());
                if (!CollectionUtils.isEmpty(nextStatusList)) {
                    nextStatusOpt = nextStatusList.stream()
                            .filter(o -> (null != o && o.getTriggerEvent().equals(MesPcnConstWords.SUCCESS))).findFirst();
                    if (null == nextStatusOpt || !nextStatusOpt.isPresent()) {
                        nextStatusOpt = nextStatusList.stream()
                                .filter(o -> (null != o && !o.getTriggerEvent().equals(MesPcnConstWords.FAILURE))).findFirst();
                        if (null == nextStatusOpt || !nextStatusOpt.isPresent()) {
                            nextStatusOpt = Optional.of(nextStatusList.get(0));
                        }
                    }
                    if (null != nextStatusOpt && nextStatusOpt.isPresent()) {
                        saveErrorRecord(requestBean, nextStatusOpt.get(), MesPcnEnumUtil.PRODUCE_ERROR_RECORD.JUMP_STATE);
                        requestBean.setScanInfo(null);
                    }
                }
            }
        } else if (shippingCmd.equals(MesPcnEnumUtil.STATION_REQUEST_BEAN_CMD.FORCE_STATE.getCode())) {

            if (islog(requestBean))
                log.info("工厂{}生产线{}工位{}:ACTOR SCAN --- EXEC --- 6.2 ---- ", requestBean.getOrganizeCode(), requestBean.getWorkCenterCode(), requestBean.getWorkCellCode());

            List<MesStepGroup> stepGroups = findStepGroupsByStepCode(requestBean);
            List<Long> steps = stepGroups.stream().map(MesStepGroup::getAmgId).collect(Collectors.toList());
            // 找到第一个包含这个工步的状态点
            nextStatusOpt = requestBean.getFsmStates().stream().filter(d -> steps.contains(d.getTriggerAmgId())).findFirst();
            if (null != nextStatusOpt && nextStatusOpt.isPresent()) {
                requestBean.getDataMap().put("FORCE:" + requestBean.getForceSpecStepCode(), CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValue());
            }
        } else if (shippingCmd.equals(MesPcnEnumUtil.STATION_REQUEST_BEAN_CMD.FORCE_JUMP_PROCESS.getCode())) {
            requestBean.setClientInfo(requestBean.getOrganizeCode() + "@" + requestBean.getWorkCenterCode() + "@" + requestBean.getWorkCellCode());
            requestBean.setInterfaceType(MesPcnConstWords.SHIPPING);
            requestBean.setBusiType(MesPcnConstWords.WS_CMD_JUMP_PROCESS);
            shippingDispatchService.doSend(requestBean);
            return requestBean;
        }
        if (null != nextStatusOpt && nextStatusOpt.isPresent()) {
            requestBean.setCurFsmState(fsmCommonService.copyFsmState(nextStatusOpt.get()));
            fsmCommonService.putStationRequestBean(requestBean, "ActorReceiveStrategyScanService:changeStateByCmdType");
        }

        if (islog(requestBean))
            log.info("工厂{}生产线{}工位{}:ACTOR SCAN --- EXEC --- 6.3 ---- ", requestBean.getOrganizeCode(), requestBean.getWorkCenterCode(), requestBean.getWorkCellCode());

        return requestBean;
    }

    /**
     * 初始化工位参数
     *
     * @param requestBean
     * @return 工位参数
     */
    private Map<String, String> initWorkCellParam(StationRequestBean requestBean) {
        Map<String, String> wcpcMap = fsmCommonService.getCachedWorkCellParam(requestBean);
        if (CollectionUtils.isEmpty(wcpcMap)) {
            wcpcMap = new HashMap<>();
            List<MesWorkCellParamCfg> wcpcList = workCellParamCfgRepository.findByProperty(
                    new String[]{MesPcnConstWords.ORGANIZE_CODE, MesPcnConstWords.IS_VALID, MesPcnConstWords.IS_DELETED, MesPcnConstWords.WORK_CENTER_CODE, MesPcnConstWords.WORK_CELL_CODE},
                    new Object[]{requestBean.getOrganizeCode(), CommonEnumUtil.IS_VAILD.VAILD.getValue(), CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(), requestBean.getWorkCenterCode(), requestBean.getWorkCellCode()});
            // 工位参数可能为空，不做空校验
            for (MesWorkCellParamCfg item : wcpcList) {
                wcpcMap.put(item.getParamCode(), item.getParamValue());
            }
            fsmCommonService.putWorkCellParam(requestBean, wcpcMap);
        }
        requestBean.setWcpcMap(wcpcMap);
        return wcpcMap;
    }

    /**
     * 初始化扫描条码
     *
     * @param requestBean
     * @return
     */
    private MesProduceSn initProduceSn(StationRequestBean requestBean) {
        Object cachedProduceSn = fsmCommonService.getCachedFirstScanKey(requestBean);
        if (cachedProduceSn != null && cachedProduceSn instanceof MesPart) {
            return null;
        }
        //缓存不存在 则去数据库获取
        if (cachedProduceSn == null) {
            MesProduceSn produceSnDb = produceSnService.getProduceSnBySnProduct(requestBean.getScanInfo(), requestBean.getOrganizeCode());
            if (produceSnDb == null) {
                return null;
            }
            return produceSnDb;
        }
        return (MesProduceSn) cachedProduceSn;
    }

    /**
     * 初始化扫描零件号
     *
     * @param requestBean
     * @return
     */
    private MesPart initPart(StationRequestBean requestBean) {
        Object cachedPart = fsmCommonService.getCachedFirstScanKey(requestBean);
        if (cachedPart != null && cachedPart instanceof MesProduceSn) {
            return null;
        }
        //缓存不存在 则去数据库获取
        if (cachedPart == null) {
            MesPart partDb = partService.getPartByNo(requestBean.getOrganizeCode(), requestBean.getScanInfo());
            if (partDb == null) {
                return null;
            }
            return partDb;
        }
        return (MesPart) cachedPart;
    }

    private void saveErrorRecord(StationRequestBean requestBean, MesStateMachineStatus fsmState, MesPcnEnumUtil.PRODUCE_ERROR_RECORD errType) {
        try {
            MesProduceErrorRecord produceErrorRecord = new MesProduceErrorRecord();
            produceErrorRecord.setErrorType(errType.getValue());
            produceErrorRecord.setSerialNumber(requestBean.getSerialNumber());
            produceErrorRecord.setPartNo(requestBean.getPartNo());
            produceErrorRecord.setWorkCenterCode(requestBean.getWorkCenterCode());
            produceErrorRecord.setWorkCellCode(requestBean.getWorkCellCode());
            produceErrorRecord.setProcessCode(requestBean.getProcessCode());
            produceErrorRecord.setStatusCode(fsmState.getStatusCode());
            produceErrorRecord.setOrganizeCode(requestBean.getOrganizeCode());
            ConvertBean.serviceModelInitialize(produceErrorRecord, requestBean.getUserInfo());
            produceErrorRecordService.saveRecord(produceErrorRecord);
        } catch (Exception ex) {
            log.error("保存发运扫描异常记录失败:" + ex.getMessage());
        }
    }

    /**
     * 根据工步代码找到包含这个工步代码的触发调用的状态点
     *
     * @param requestBean
     * @return
     */
    private List<MesStepGroup> findStepGroupsByStepCode(StationRequestBean requestBean) {
        DdlPackBean packBean = DdlPackBean.getDdlPackBean(requestBean.getOrganizeCode());
        DdlPreparedPack.getStringEqualPack(requestBean.getForceSpecStepCode(), "stepCode", packBean);
        return stepGroupRepository.findByHqlWhere(packBean);
    }

}
