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

import cn.estsh.i3plus.ext.mes.pcn.api.base.*;
import cn.estsh.i3plus.ext.mes.pcn.api.busi.IPackageExtService;
import cn.estsh.i3plus.ext.mes.pcn.api.busi.IProduceSnExtService;
import cn.estsh.i3plus.ext.mes.pcn.api.busi.IProductEncodeCfgExtService;
import cn.estsh.i3plus.ext.mes.pcn.api.busi.ISxNumberRuleCheckAttributeService;
import cn.estsh.i3plus.ext.mes.pcn.api.busi.ep.IEpRfidDispatchService;
import cn.estsh.i3plus.ext.mes.pcn.apiservice.serviceimpl.busi.station.ep.EpSnLineOffModuleService;
import cn.estsh.i3plus.ext.mes.pcn.pojo.bean.*;
import cn.estsh.i3plus.ext.mes.pcn.pojo.model.WorkCenterExtModel;
import cn.estsh.i3plus.ext.mes.pcn.pojo.model.WorkOrderExtModel;
import cn.estsh.i3plus.ext.mes.pcn.pojo.model.ep.EpRfidDispatchModel;
import cn.estsh.i3plus.ext.mes.pcn.pojo.repository.MesPackageExtRepository;
import cn.estsh.i3plus.ext.mes.pcn.pojo.repository.MesProductDataRfidRecordRepository;
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.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.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.enumutil.CommonEnumUtil;
import cn.estsh.i3plus.pojo.base.enumutil.MesPcnEnumUtil;
import cn.estsh.i3plus.pojo.mes.bean.MesPackageDetail;
import cn.estsh.i3plus.pojo.mes.bean.MesShift;
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.MesPackageDetailRepository;
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.*;

/**
 * @Description : 工步业务-EP打包下线扫描包装条码工步
 * @Reference :
 * @Author : wangjie
 * @CreateDate : 2019-07-11
 * @Modify:
 **/
@Slf4j
@Service("epSnLineOffScanPackNoStepService")
public class EpSnLineOffScanPackNoStepService extends BaseStepService {

    @Autowired
    private EpSnLineOffModuleService snLineOffModuleService;

    @Autowired
    private IWorkCenterExtService workCenterExtService;

    @Autowired
    private IShippingDispatchService shippingDispatchService;

    @Autowired
    private IProduceSnExtService produceSnExtService;

    @Autowired
    private IPartExtService partExtService;

    @Autowired
    private INumberRuleExtService numberRuleExtService;

    @Autowired
    private IProductEncodeCfgExtService productEncodeCfgExtService;

    @Autowired
    private ISxNumberRuleCheckAttributeService numberRuleCheckAttributeService;

    @Autowired
    private IPackageExtService packageExtService;

    @Autowired
    private IFsmCommonService fsmCommonService;

    @Autowired
    private ISxWorkOrderExtService workOrderExtService;

    @Autowired
    private MesPackageExtRepository packageExtRepository;

    @Autowired
    private MesPackageDetailRepository packageDetailRepository;

    @Autowired
    private MesProductDataRfidRecordRepository productDataRfidRecordRepository;

    @Autowired
    private IEpRfidDispatchService rfidDispatchService;

    @Autowired
    private IShiftExtService shiftExtService;

    @Autowired
    private IShiftProdCenterRecordService shiftProdCenterRecordService;

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

    @Override
    public StepResult guide(StationRequestBean reqBean) {
        StationResultBean resultBean = new StationResultBean();
        String guide = LocaleUtil.transferLanguage(reqBean.getUserInfo(), "请扫描包装条码");
        this.sendMessage(reqBean, resultBean, guide, MesPcnEnumUtil.STATION_BUSI_TYPE.GUIDE, MesPcnEnumUtil.STATION_DATA_TYPE.TEXT);
        return super.guide(reqBean);
    }

    @Override
    public StepResult init(StationRequestBean reqBean) {
        //清除工步内容
        StationResultBean resultBean = new StationResultBean();
        resultBean.setBusiType(MesPcnEnumUtil.STATION_BUSI_TYPE.STEP_CONTENT.getValue());
        this.sendMessage(reqBean, resultBean);
        return super.init(reqBean);
    }

    @Override
    public StepResult execute(StationRequestBean reqBean) {
        log.info("EpSnLineOffScanPackNoStepService[execute] 参数：{}", reqBean);

        StationResultBean resultBean = new StationResultBean();
        String err;

        if (StringUtils.isEmpty(reqBean.getOrganizeCode())) {
            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);
        }

        if (StringUtils.isEmpty(reqBean.getScanInfo())) {
            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);
        }

        if (StringUtils.isEmpty(reqBean.getSerialNumber())) {
            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 curWorkOrderNo = (String) snLineOffModuleService.doHandleCurWorkOrderNo(reqBean, 1, null);
        if (StringUtils.isEmpty(curWorkOrderNo)) {
            err = LocaleUtil.transferLanguage(reqBean.getUserInfo(), "当前执行工单已经失效,请重新选择工单");
            this.sendMessage(reqBean, resultBean, err, MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT);
            foundExThrowNoShowMsg();
        }
        WorkOrderExtModel orderModel = (WorkOrderExtModel) reqBean.getDataMap().get(MesPcnExtConstWords.WORK_ORDER);
        if (null == orderModel) {
            orderModel = getWorkOrderExtModel(reqBean, curWorkOrderNo);
        }
        if (null == orderModel) {
            err = String.format(LocaleUtil.transferLanguage(reqBean.getUserInfo(), "生产工单号[%s]无效,请重新选择工单"), curWorkOrderNo);
            sendMessage(reqBean, resultBean, err, MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT);
            foundExThrowNoShowMsg();
        }
        if (!curWorkOrderNo.equals(orderModel.getOrderNo())) {
            err = String.format(LocaleUtil.transferLanguage(reqBean.getUserInfo(), "当前执行工单[%s]与缓存工单号[%s]不一致,请重新选择工单"), curWorkOrderNo, orderModel.getOrderNo());
            this.sendMessage(reqBean, resultBean, err, MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT);
            foundExThrowNoShowMsg();
        }

        MesProduceSnExt produceSnExt = produceSnExtService.getProduceSnExtBySn(reqBean.getOrganizeCode(), reqBean.getSerialNumber());
        Boolean flag = (null != produceSnExt && CommonEnumUtil.IS_VAILD.VAILD.getValue() == produceSnExt.getIsValid() && produceSnExt.getLastWorkOrderNo().equals(curWorkOrderNo));
        if (!flag) {
            err = String.format(LocaleUtil.transferLanguage(reqBean.getUserInfo(), "条码[%s]未绑定工单[%s]"), reqBean.getSerialNumber(), curWorkOrderNo);
            this.sendMessage(reqBean, resultBean, err, MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT);

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

            //跳过整个工序
            reqBean.setClientInfo(shippingDispatchService.getActorClientInfo(reqBean));
            reqBean.setInterfaceType(MesPcnExtConstWords.SHIPPING);
            reqBean.setBusiType(MesPcnConstWords.WS_CMD_DO_SCAN);
            reqBean.setForceJumpProcess(true);
            shippingDispatchService.doSendScanQueueNextExec(reqBean);

            foundExThrowNoShowMsg();
        }

        MesWorkCenterExt workCenterExt = workCenterExtService.getWorkCenterExtByWorkCenterCode(reqBean.getOrganizeCode(), reqBean.getWorkCenterCode());
        if (null == workCenterExt) {
            err = String.format(LocaleUtil.transferLanguage(reqBean.getUserInfo(), "生产线代码[%s]无效"), reqBean.getWorkCenterCode());
            this.sendMessage(reqBean, resultBean, err, MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT);
            foundExThrowNoShowMsg();
        }
        if (StringUtils.isEmpty(workCenterExt.getShiftCode()) || StringUtils.isEmpty(workCenterExt.getWorkTime())) {
            err = String.format(LocaleUtil.transferLanguage(reqBean.getUserInfo(), "生产线代码[%s]未启动班次"), reqBean.getWorkCenterCode());
            this.sendMessage(reqBean, resultBean, err, MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT);
            foundExThrowNoShowMsg();
        }
        MesShift shiftDb = shiftExtService.getShiftByShiftCodeAndCenterCode(reqBean.getOrganizeCode(), reqBean.getWorkCenterCode(), workCenterExt.getShiftCode());
        if (null == shiftDb) {
            err = String.format(LocaleUtil.transferLanguage(reqBean.getUserInfo(), "生产线[%s]未关联班次代码[%s]"), reqBean.getWorkCenterCode(), workCenterExt.getShiftCode());
            this.sendMessage(reqBean,  resultBean, err, MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT);
            foundExThrowNoShowMsg();
        }
        String workTime = shiftProdCenterRecordService.getWorkTime(shiftDb.getStartTime(), shiftDb.getEndTime());
        if (StringUtils.isEmpty(workTime) || !workTime.equals(workCenterExt.getWorkTime())) {
            err = String.format(LocaleUtil.transferLanguage(reqBean.getUserInfo(), "生产线[%s]需要重新启动班次"), reqBean.getWorkCenterCode());
            this.sendMessage(reqBean,  resultBean, err, MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT);
            foundExThrowNoShowMsg();
        }

        Map<String, String> wcpcMap = fsmCommonService.getCachedWorkCellParam(reqBean);
        Boolean isDataCollectCenter = !CollectionUtils.isEmpty(wcpcMap) && wcpcMap.containsKey(MesPcnExtConstWords.CENTER_IS_DATA_COLLECT) &&
                !StringUtils.isEmpty(wcpcMap.get(MesPcnExtConstWords.CENTER_IS_DATA_COLLECT)) && wcpcMap.get(MesPcnExtConstWords.CENTER_IS_DATA_COLLECT).equals(CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValueStr());
        Boolean isRfidCellFlag = !CollectionUtils.isEmpty(wcpcMap) && wcpcMap.containsKey(MesPcnExtConstWords.IS_RFID_CELL) &&
                !StringUtils.isEmpty(wcpcMap.get(MesPcnExtConstWords.IS_RFID_CELL)) && wcpcMap.get(MesPcnExtConstWords.IS_RFID_CELL).equals(CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValueStr());
        Boolean isByPart = !CollectionUtils.isEmpty(wcpcMap) && wcpcMap.containsKey(MesPcnExtConstWords.CENTER_PD_CHECK_IS_BY_PART) &&
                !StringUtils.isEmpty(wcpcMap.get(MesPcnExtConstWords.CENTER_PD_CHECK_IS_BY_PART)) && wcpcMap.get(MesPcnExtConstWords.CENTER_PD_CHECK_IS_BY_PART).equals(CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValueStr());
        reqBean.getDataMap().put(MesPcnExtConstWords.CENTER_IS_DATA_COLLECT, isDataCollectCenter);
        reqBean.getDataMap().put(MesPcnExtConstWords.IS_RFID_CELL, isRfidCellFlag);
        reqBean.getDataMap().put(MesPcnExtConstWords.CENTER_PD_CHECK_IS_BY_PART, isByPart);
        String ip = (!CollectionUtils.isEmpty(wcpcMap) && wcpcMap.containsKey(MesPcnExtConstWords.RFID_HOST) &&
                !StringUtils.isEmpty(wcpcMap.get(MesPcnExtConstWords.RFID_HOST))) ? wcpcMap.get(MesPcnExtConstWords.RFID_HOST) : null;
        Integer port = (!CollectionUtils.isEmpty(wcpcMap) && wcpcMap.containsKey(MesPcnExtConstWords.RFID_PORT) &&
                !StringUtils.isEmpty(wcpcMap.get(MesPcnExtConstWords.RFID_PORT))) ? Integer.valueOf(wcpcMap.get(MesPcnExtConstWords.RFID_PORT)) : null;
        Integer mem = (!CollectionUtils.isEmpty(wcpcMap) && wcpcMap.containsKey(MesPcnExtConstWords.RFID_MEM) &&
                !StringUtils.isEmpty(wcpcMap.get(MesPcnExtConstWords.RFID_MEM))) ? Integer.valueOf(wcpcMap.get(MesPcnExtConstWords.RFID_MEM)) : null;
        Byte len = (!CollectionUtils.isEmpty(wcpcMap) && wcpcMap.containsKey(MesPcnExtConstWords.RFID_DATA_LEN) &&
                !StringUtils.isEmpty(wcpcMap.get(MesPcnExtConstWords.RFID_DATA_LEN))) ? Byte.valueOf(wcpcMap.get(MesPcnExtConstWords.RFID_DATA_LEN)) : null;
        Long time = (!CollectionUtils.isEmpty(wcpcMap) && wcpcMap.containsKey(MesPcnExtConstWords.RFID_READ_SLEEP_TIME) &&
                !StringUtils.isEmpty(wcpcMap.get(MesPcnExtConstWords.RFID_READ_SLEEP_TIME))) ? Long.parseLong(wcpcMap.get(MesPcnExtConstWords.RFID_READ_SLEEP_TIME)) : 100L;
        if (isRfidCellFlag && (StringUtils.isEmpty(ip) || StringUtils.isEmpty(port) || StringUtils.isEmpty(len))) {
            err = String.format(LocaleUtil.transferLanguage(reqBean.getUserInfo(), "生产线[%s]工位[%s]未配置RFID设备参数:ip[%s]port[%s]len[%s]"),
                    reqBean.getWorkCenterCode(), reqBean.getWorkCellCode(), ip, port, len);
            this.sendMessage(reqBean, resultBean, err, MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT);
            foundExThrowNoShowMsg();
        }

        MesPackageDetail packageDetail;
        if (MesPcnExtEnumUtil.WORK_ORDER_TYPE.REWORK_ORDER.getValue() == orderModel.getWorkOrderType()) {
            packageDetail = packageExtService.getPackageDetailBySn(reqBean.getOrganizeCode(), reqBean.getSerialNumber());
            if (null == packageDetail) {
                err = String.format(LocaleUtil.transferLanguage(reqBean.getUserInfo(), "返工工单[%s]产品条码[%s]对应的包装明细数据不存在,操作失败"), curWorkOrderNo, reqBean.getSerialNumber());
                this.sendMessage(reqBean, resultBean, err, MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT);
                foundExThrowNoShowMsg();
            }
            if (!packageDetail.getPackageNo().equals(reqBean.getScanInfo())) {
                err = String.format(LocaleUtil.transferLanguage(reqBean.getUserInfo(), "返工工单[%s]产品条码[%s]已关联的包装条码[%s]与扫描的包装条码[%s]不一致,操作失败"),
                        curWorkOrderNo, reqBean.getSerialNumber(), packageDetail.getPackageNo(), reqBean.getScanInfo());
                this.sendMessage(reqBean, resultBean, err, MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT);
                return StepResult.getNonComplete(err);
            }

            doHandleSnColonRfidNo(reqBean, resultBean, isRfidCellFlag, isDataCollectCenter, curWorkOrderNo, orderModel.getWorkCenterCode(), produceSnExt, ip, port, mem, time, len);

            WorkCenterExtModel centerModel = new WorkCenterExtModel();
            BeanUtils.copyProperties(workCenterExt, centerModel, MesPcnExtConstWords.ID);
            reqBean.getDataMap().put(MesPcnExtConstWords.WORK_CENTER, centerModel);

            reqBean.setPackageNo(reqBean.getScanInfo());

            return StepResult.getSuccessComplete();
        }

        MesPartExt partDb = partExtService.getPartExt(reqBean.getOrganizeCode(), produceSnExt.getPartNo());
        if (null == partDb) {
            err = String.format(LocaleUtil.transferLanguage(reqBean.getUserInfo(), "工单号[%s]关联的物料[%s]无效"), curWorkOrderNo, produceSnExt.getPartNo());
            this.sendMessage(reqBean, resultBean, err, MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT);
            foundExThrowNoShowMsg();
        }
        String ruleCode;
        try {
            ruleCode = productEncodeCfgExtService.getRuleCodeByMatchType(
                    reqBean.getOrganizeCode(), MesPcnExtEnumUtil.ENCODE_CODE_TYPE.PACK_SN.getValue(), partDb, reqBean.getWorkCenterCode());
        } catch (Exception e) {
            err = String.format(LocaleUtil.transferLanguage(reqBean.getUserInfo(), "工单号[%s]关联的物料[%s]:[%s]"),
                    curWorkOrderNo, produceSnExt.getPartNo(), e.getMessage());
            this.sendMessage(reqBean, resultBean, err, MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT);
            return StepResult.getNonComplete(err);
        }

        MesNumberRuleExt numberRuleDb = numberRuleExtService.getNumberRuleExtByRuleCode(reqBean.getOrganizeCode(), ruleCode);
        if (null == numberRuleDb || StringUtils.isEmpty(numberRuleDb.getNumberRule()) || StringUtils.isEmpty(numberRuleDb.getRuleLengthSpilt()) || StringUtils.isEmpty(numberRuleDb.getMethodName())) {
            err = String.format(LocaleUtil.transferLanguage(reqBean.getUserInfo(), "工单号[%s]关联的物料[%s]配置的编码规则代码[%s]无效"),
                    curWorkOrderNo, produceSnExt.getPartNo(), ruleCode);
            this.sendMessage(reqBean, resultBean, err, MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT);
            return StepResult.getNonComplete(err);
        }

        Map<String, Object> map = new HashMap<>();
        map.put(MesPcnExtConstWords.SERIAL_NUMBER, reqBean.getScanInfo());
        map.put(MesPcnExtConstWords.NUMBER_RULE_EXT, numberRuleDb);
        map.put(MesPcnExtConstWords.PART_EXT, partDb);
        Map<String,Object> resultMap = numberRuleCheckAttributeService.doCheckNumberRule(map);
        if (!(Boolean) resultMap.get(MesPcnExtConstWords.RESULT)) {
            err = String.format(LocaleUtil.transferLanguage(reqBean.getUserInfo(), "包装条码[%s]与工单号[%s]关联的物料[%s]配置的编码规则不匹配,操作失败"),
                    reqBean.getScanInfo(), curWorkOrderNo, produceSnExt.getPartNo());
            this.sendMessage(reqBean, resultBean, err, MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT);
            return StepResult.getNonComplete(err);
        }

        List<String> trolleyPartNoList =
                (!CollectionUtils.isEmpty(wcpcMap) && wcpcMap.containsKey(MesPcnExtConstWords.TROLLEY_PARTS) &&
                        !StringUtils.isEmpty(wcpcMap.get(MesPcnExtConstWords.TROLLEY_PARTS)))
                        ? Arrays.asList(wcpcMap.get(MesPcnExtConstWords.TROLLEY_PARTS).split(MesPcnExtConstWords.COMMA)) : null;

        MesPackageExt packageExt = packageExtService.getPackageByPackNo(reqBean.getOrganizeCode(), reqBean.getScanInfo());
        if (null != packageExt) {
            if (CollectionUtils.isEmpty(trolleyPartNoList) || !trolleyPartNoList.contains(produceSnExt.getPartNo())) {
                err = String.format(LocaleUtil.transferLanguage(reqBean.getUserInfo(), "包装条码[%s]已经被关联工单[%s],操作失败"),
                        reqBean.getScanInfo(), packageExt.getWorkOrderNo());
                this.sendMessage(reqBean, resultBean, err, MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT);
                return StepResult.getNonComplete(err);
            }
            if (!packageExt.getLastWorkOrderNo().equals(packageExt.getWorkOrderNo())) {
                err = String.format(LocaleUtil.transferLanguage(reqBean.getUserInfo(), "包装条码[%s]已关联返工工单[%s],操作失败"),
                        reqBean.getScanInfo(), packageExt.getLastWorkOrderNo());
                this.sendMessage(reqBean, resultBean, err, MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT);
                return StepResult.getNonComplete(err);
            }
            if (!packageExt.getWorkOrderNo().equals(curWorkOrderNo)) {
                err = String.format(LocaleUtil.transferLanguage(reqBean.getUserInfo(), "包装条码[%s]已关联生产工单[%s],操作失败"),
                        reqBean.getScanInfo(), packageExt.getWorkOrderNo());
                this.sendMessage(reqBean, resultBean, err, MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT);
                return StepResult.getNonComplete(err);
            }
            if (MathOperation.compareTo(packageExt.getQty(), packageExt.getPackSpecQty()) >= 0) {
                err = String.format(LocaleUtil.transferLanguage(reqBean.getUserInfo(), "包装条码[%s]关联的产品条码数量[%s]已达标台车物料[%s]的标包,操作失败"),
                        reqBean.getScanInfo(), packageExt.getQty(), produceSnExt.getPartNo());
                this.sendMessage(reqBean, resultBean, err, MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT);
                return StepResult.getNonComplete(err);
            }

            packageExt.setQty(MathOperation.add(packageExt.getQty(), new Double(1)));
            if (MathOperation.compareTo(packageExt.getQty(), packageExt.getPackSpecQty()) == 0) {
                packageExt.setIsSealed(MesPcnEnumUtil.PACKAGE_IS_SEALED.SEALED.getValue());
            }
            ConvertBean.serviceModelUpdate(packageExt, reqBean.getUserInfo());
            packageExt.setSystemSyncStatus(MesPcnExtEnumUtil.IF_SYNC_STATUS.NO_SYNC.getValue());
        } else {
            packageExt = new MesPackageExt();
            packageExt.setPackageNo(reqBean.getScanInfo());
            packageExt.setPartNo(produceSnExt.getPartNo());
            packageExt.setPartNameRdd(produceSnExt.getPartNameRdd());
            packageExt.setQty(new Double(1));
            if (CollectionUtils.isEmpty(trolleyPartNoList) || !trolleyPartNoList.contains(produceSnExt.getPartNo())) {
                packageExt.setPackSpecQty(new Double(1));
                packageExt.setIsSealed(MesPcnEnumUtil.PACKAGE_IS_SEALED.SEALED.getValue());
            } else {
                Double qty2 = (StringUtils.isEmpty(partDb.getQty2()) || MathOperation.compareTo(partDb.getQty2(), new Double(1)) <= 0) ? new Double(1) : partDb.getQty2();
                if (CollectionUtils.isEmpty(trolleyPartNoList) || !trolleyPartNoList.contains(produceSnExt.getPartNo())) {
                    packageExt.setPackSpecQty(qty2);
                } else {
                    Double packSpecQty;
                    try {
                        packSpecQty = StringUtils.isEmpty(resultMap.get(MesPcnExtConstWords.N)) ? qty2 :
                                ((StringUtils.isEmpty(partDb.getQty2()) || MathOperation.compareTo(partDb.getQty2(), new Double(1)) <= 0) ? new Double((Integer)resultMap.get(MesPcnExtConstWords.N)) :
                                        (MathOperation.compareTo(new Double((Integer)resultMap.get(MesPcnExtConstWords.N)), qty2) <= 0 ? new Double((Integer)resultMap.get(MesPcnExtConstWords.N)) : qty2));
                    } catch (Exception e) {
                        packSpecQty = qty2;
                    }
                    packageExt.setPackSpecQty(packSpecQty);
                }

                packageExt.setIsSealed(MesPcnEnumUtil.PACKAGE_IS_SEALED.UNSEALED.getValue());
            }
            packageExt.setUnit(partDb.getUnit());
            packageExt.setPrintStatus(MesPcnEnumUtil.PACKAGE_PRINT_STATUS.PRINTED.getValue());
            packageExt.setPackLevel(MesPcnEnumUtil.PACKAGE_PACKLEVEL.FIRST.getValue());
            packageExt.setWorkOrderNo(curWorkOrderNo);
            packageExt.setLastWorkOrderNo(curWorkOrderNo);
            packageExt.setWorkCenterCode(reqBean.getWorkCenterCode());
            packageExt.setWorkCellCode(reqBean.getWorkCellCode());
            packageExt.setOrganizeCode(reqBean.getOrganizeCode());
            ConvertBean.serviceModelInitialize(packageExt, reqBean.getUserInfo());
            packageExt.setSystemSyncStatus(MesPcnExtEnumUtil.IF_SYNC_STATUS.NO_SYNC.getValue());
        }

        doHandleSnColonRfidNo(reqBean, resultBean, isRfidCellFlag, isDataCollectCenter, curWorkOrderNo, orderModel.getWorkCenterCode(), produceSnExt, ip, port, mem, time, len);

        new ConvertBeanExt(packageExt).convertBean(packageExt);
        if (StringUtils.isEmpty(packageExt.getId())) {
            packageExtRepository.insert(packageExt);
        } else {
            packageExtRepository.save(packageExt);
        }

        packageDetail = new MesPackageDetail();
        packageDetail.setPackageNo(reqBean.getScanInfo());
        packageDetail.setSerialNumber(reqBean.getSerialNumber());
        packageDetail.setPartNo(produceSnExt.getPartNo());
        packageDetail.setPartNameRdd(produceSnExt.getPartNameRdd());
        packageDetail.setOrganizeCode(reqBean.getOrganizeCode());
        packageDetail.setSystemSyncStatus(MesPcnExtEnumUtil.IF_SYNC_STATUS.NO_SYNC.getValue());
        ConvertBean.serviceModelInitialize(packageDetail, reqBean.getUserInfo());
        packageDetailRepository.insert(packageDetail);

        WorkCenterExtModel centerModel = new WorkCenterExtModel();
        BeanUtils.copyProperties(workCenterExt, centerModel, MesPcnExtConstWords.ID);
        reqBean.getDataMap().put(MesPcnExtConstWords.WORK_CENTER, centerModel);

        reqBean.setPackageNo(reqBean.getScanInfo());

        return StepResult.getSuccessComplete();
    }

    private WorkOrderExtModel getWorkOrderExtModel(StationRequestBean reqBean, String workOrderNo) {
        WorkOrderExtModel orderModel = null;
        MesWorkOrderExt workOrderExt = workOrderExtService.getWorkOrderExtByOrderNo(reqBean.getOrganizeCode(), workOrderNo);
        if (null != workOrderExt) {
            orderModel = new WorkOrderExtModel();
            BeanUtils.copyProperties(workOrderExt, orderModel, MesPcnExtConstWords.ID);
            reqBean.getDataMap().put(MesPcnExtConstWords.WORK_ORDER, orderModel);
        }
        return orderModel;
    }

    private void doHandleSnColonRfidNo(StationRequestBean reqBean, StationResultBean resultBean,
                                       Boolean isRfidCellFlag, Boolean isDataCollectCenter, String workOrderNo, String orderCenter, MesProduceSnExt produceSnExt,
                                       String ip, Integer port, Integer mem, Long time, Byte len) {
        if (!isDataCollectCenter || !isRfidCellFlag) {
           return;
        }
        String err;

        String rfidNo = "";
        try {
            EpRfidDispatchModel model = new EpRfidDispatchModel(reqBean.getWorkCenterCode(), reqBean.getWorkCellCode(), ip, port, mem, len, time);
            rfidNo = rfidDispatchService.doRfidDispatch(model);
        } catch (Exception e) {
            err = String.format(LocaleUtil.transferLanguage(reqBean.getUserInfo(), "产品条码[%s]获取RFID编号失败,请重新扫描包装条码尝试获取,失败原因:%s"),
                    reqBean.getSerialNumber(), e.getMessage());
            this.sendMessage(reqBean, resultBean, err, MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT);
            foundExThrowNoShowMsg();
        }

        if (StringUtils.isEmpty(rfidNo)) {
            err = String.format(LocaleUtil.transferLanguage(reqBean.getUserInfo(), "产品条码[%s]未获取到RFID编号,请重新扫描包装条码尝试获取"),
                    reqBean.getSerialNumber());
            this.sendMessage(reqBean, resultBean, err, MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT);
            foundExThrowNoShowMsg();
        }

        err = String.format(LocaleUtil.transferLanguage(reqBean.getUserInfo(), "产品条码[%s]获取到RFID编号[%s]"), reqBean.getSerialNumber(), rfidNo);
        this.sendMessage(reqBean, resultBean, err, MesPcnEnumUtil.STATION_BUSI_TYPE.RUNNING_INFO, MesPcnEnumUtil.STATION_DATA_TYPE.TEXT);

        String rfidNoStr = "";
        try {
            //十六进制转字符串
            rfidNoStr = hexStr2Str(rfidNo);
        } catch (Exception e) {
            err = String.format(LocaleUtil.transferLanguage(reqBean.getUserInfo(), "产品条码[%s]获取到RFID编号[%s],字符串转换出现错误,请重新扫描包装条码尝试获取"),
                    reqBean.getSerialNumber(), rfidNo);
            this.sendMessage(reqBean, resultBean, err, MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT);
            foundExThrowNoShowMsg();
        }

        if (StringUtils.isEmpty(rfidNoStr)) {
            err = String.format(LocaleUtil.transferLanguage(reqBean.getUserInfo(), "产品条码[%s]获取到RFID编号[%s],字符串转换获取为NULL,请重新扫描包装条码尝试获取"),
                    reqBean.getSerialNumber(), rfidNo);
            this.sendMessage(reqBean, resultBean, err, MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT);
            foundExThrowNoShowMsg();
        } else {
            err = String.format(LocaleUtil.transferLanguage(reqBean.getUserInfo(), "产品条码[%s]获取到RFID编号[%s],转换字符串为[%s]"), reqBean.getSerialNumber(), rfidNo, rfidNoStr);
            this.sendMessage(reqBean, resultBean, err, MesPcnEnumUtil.STATION_BUSI_TYPE.RUNNING_INFO, MesPcnEnumUtil.STATION_DATA_TYPE.TEXT);
        }

        String snColonRfidNo = (String)snLineOffModuleService.doHandleSnColonRfidNo(reqBean, 1, null);
        if (!StringUtils.isEmpty(snColonRfidNo) && snColonRfidNo.contains(rfidNoStr) && !snColonRfidNo.contains(reqBean.getSerialNumber())) {
            err = String.format(LocaleUtil.transferLanguage(reqBean.getUserInfo(), "产品条码[%s]获取到的RFID编号(字符串)[%s]与上个产品条码[%s]的RFID编号(字符串)一致,请重新扫描包装条码尝试获取"),
                    reqBean.getSerialNumber(), rfidNoStr, snColonRfidNo.split(MesPcnExtConstWords.COLON)[0]);
            this.sendMessage(reqBean, resultBean, err, MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT);
            foundExThrowNoShowMsg();
        }

        if (!(Boolean)snLineOffModuleService.doHandleSnColonRfidNo(reqBean, 2, new StringJoiner(MesPcnExtConstWords.COLON).add(reqBean.getSerialNumber()).add(rfidNoStr).toString())) {
            err = String.format(LocaleUtil.transferLanguage(reqBean.getUserInfo(), "产品条码[%s]获取到的RFID编号(字符串)[%s]缓存失败,请重新扫描包装条码尝试缓存"),
                    reqBean.getSerialNumber(), rfidNoStr);
            this.sendMessage(reqBean, resultBean, err, MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT);
            foundExThrowNoShowMsg();
        }

        MesProductDataRfidRecord rfidRecord = new MesProductDataRfidRecord();
        rfidRecord.setWorkOrderNo(workOrderNo);
        rfidRecord.setWorkCenterCode(orderCenter);
        rfidRecord.setSerialNumber(produceSnExt.getSerialNumber());
        rfidRecord.setPartNo(produceSnExt.getPartNo());
        rfidRecord.setPartNameRdd(produceSnExt.getPartNameRdd());
        rfidRecord.setRfidNo(rfidNoStr);
        rfidRecord.setOrganizeCode(reqBean.getOrganizeCode());
        ConvertBean.serviceModelInitialize(rfidRecord, reqBean.getUserInfo());
        productDataRfidRecordRepository.insert(rfidRecord);
    }

    public static String hexStr2Str(String hexStr) {
        String str = "0123456789ABCDEF";
        char[] hexs = hexStr.toCharArray();
        byte[] bytes = new byte[hexStr.length() / 2];
        int n;
        for (int i = 0; i < bytes.length; i++) {
            n = str.indexOf(hexs[2 * i]) * 16;
            n += str.indexOf(hexs[2 * i + 1]);
            bytes[i] = (byte) (n & 0xff);
        }
        return new String(bytes);
    }

//    public static void main(String[] args) {
//        System.out.println(hexStr2Str("30313230323230313234313534393030"));

//        byte[] rfidNoArr = ReaderUtil.sendCommand(new RequestPacketModel().buildListTagIdCommand((byte) 0x03, "1", "1"), "192.168.31.100", 1969);
//        System.out.println(ReaderUtil.bytes2HexString(rfidNoArr));
//
//        try {
//            Thread.sleep(100);
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        }
//
//        byte[] bytes = ReaderUtil.getTagsId(rfidNoArr);
//        Byte[] tags = new Byte[bytes.length];
//        for (int i = 0; i<bytes.length; i++) {
//            tags[i] = bytes[i];
//        }
//
//        byte[] valueArr = ReaderUtil.sendCommand(new RequestPacketModel().buildReadTagCommand(tags, (byte) 0x03, "1", "1"), "192.168.31.100", 1969);
//        System.out.println(ReaderUtil.bytes2HexString(valueArr));
//    }

            ////EPC
            ////receive message[18]: F0 10 EE 01 06 E2 00 00 17 40 0D 01 52 18 10 5D 3B B2
            ////E2 00 00 17 40 0D 01 52 18 10 5D 3B    //  27 E1
            ////receive message[6]: F0 04 EC 27 E1 18

            ////USER
            ////receive message[18]: F0 10 EE 01 06 E2 00 00 17 40 0D 01 52 18 10 5D 3B B2
            ////E2 00 00 17 40 0D 01 52 18 10 5D 3B    //  0120
            ////receive message[6]: F0 04 EC 01 20 FF


            ////EPC
            ////receive message[8]: F0 06 EE 01 01 CB 9F B0
            ////CB9F    //  4604
            ////receive message[6]: F0 04 EC 46 04 D6

            ////USER
            ////receive message[8]: F0 06 EE 01 01 CB 9F B0
            ////CB9F    //  0001
            ////receive message[6]: F0 04 EC 00 01 1F


            ////EPC
            ////receive message[18]: F0 10 EE 01 06 E2 00 00 17 40 0D 01 33 28 30 02 A7 90
            ////E2 00 00 17 40 0D 01 33 28 30 02 A7    //  A9E8
            ////receive message[6]: F0 04 EC A9 E8 8F

            ////USER
            ////receive message[18]: F0 10 EE 01 06 E2 00 00 17 40 0D 01 33 28 30 02 A7 90
            ////E2 00 00 17 40 0D 01 33 28 30 02 A7    //  0120
            ////receive message[6]: F0 04 EC 01 20 FF

}

