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

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.pojo.bean.MesPackageExt;
import cn.estsh.i3plus.ext.mes.pcn.pojo.bean.MesProduceSnExt;
import cn.estsh.i3plus.ext.mes.pcn.pojo.bean.MesProduceSnTravelExt;
import cn.estsh.i3plus.ext.mes.pcn.pojo.model.bu.InnerPackageRecordModel;
import cn.estsh.i3plus.ext.mes.pcn.pojo.repository.MesProduceSnTravelExtRepository;
import cn.estsh.i3plus.ext.mes.pcn.pojo.util.MesPcnExtConstWords;
import cn.estsh.i3plus.mes.pcn.actor.shipping.dispatch.IFsmCommonService;
import cn.estsh.i3plus.mes.pcn.serviceimpl.base.BaseStepService;
import cn.estsh.i3plus.mes.pcn.util.LocaleUtil;
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.MesProduceSn;
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.impp.framework.boot.util.ImppRedis;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Description : 工步业务-校验小包装条码生产顺序工步（跳号防错）
 * @Reference :
 * @Author : steven.peng
 * @CreateDate : 2019-07-11
 * @Modify:
 **/
@Slf4j
@Service("sxInnerPackagePreCheckProdSeqStepService")
public class SxInnerPackagePreCheckProdSeqStepService extends BaseStepService {

    @Autowired
    private IProduceSnExtService produceSnExtService;

    @Autowired
    private MesProduceSnTravelExtRepository produceSnTravelExtRepository;

    @Autowired
    private IFsmCommonService fsmCommonService;

    @Autowired
    private IPackageExtService packageExtService;

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

    @Override
    public StepResult init(StationRequestBean reqBean) {
        return super.init(reqBean);
    }

    @Override
    public StepResult execute(StationRequestBean reqBean) {
        log.info("sxInnerPackagePreCheckProdSeqStepService[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.getWorkOrderNo())) {
            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 innerPackageNo = (String)reqBean.getDataMap().get(MesPcnExtConstWords.INNER_PACKAGE_NO);

        List<MesPackageExt> mesPackageExts = packageExtService.getPackageListByWorkOrderNo(reqBean.getOrganizeCode(),reqBean.getWorkOrderNo());

        List<String> packageNoList = CollectionUtils.isEmpty(mesPackageExts) ? null :
                mesPackageExts.stream().filter(o -> null != o).map(MesPackageExt::getPackageNo).collect(Collectors.toList());
        packageNoList = CollectionUtils.isEmpty(packageNoList) ? null :
                packageNoList.stream().filter(o -> !StringUtils.isEmpty(o)).sorted(String::compareTo).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(packageNoList)) {
            err = String.format(LocaleUtil.transferLanguage(reqBean.getUserInfo(), "生产工单[%s]未找到对应的小包装条码"), reqBean.getWorkOrderNo());
            this.sendMessage(reqBean, resultBean, err, MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT);
            return StepResult.getNonComplete(err);
        }

        //  校验小包装条码对应的本体条码 查询出本体条码的信息
        MesProduceSnExt produceSnExt = produceSnExtService.getProduceSnExtBySn(reqBean.getOrganizeCode(), reqBean.getSerialNumber());
        if (produceSnExt == null) {
            err = String.format(LocaleUtil.transferLanguage(reqBean.getUserInfo(), "条码[%s]无效"), reqBean.getSerialNumber());
            sendMessage(reqBean, resultBean, err, MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT);
            return StepResult.getNonCompleteStop(err);
        }

        List<MesProduceSnExt> produceSnExtList = produceSnExtService.getProduceSnExtListByOrderNoAndSnType(reqBean.getOrganizeCode(), reqBean.getWorkOrderNo(),produceSnExt.getSnType());
        List<String> serialNumberList = CollectionUtils.isEmpty(produceSnExtList) ? null :
                produceSnExtList.stream().filter(o -> null != o).map(MesProduceSn::getSerialNumber).collect(Collectors.toList());
        serialNumberList = CollectionUtils.isEmpty(serialNumberList) ? null :
                serialNumberList.stream().filter(o -> !StringUtils.isEmpty(o)).sorted(String::compareTo).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(serialNumberList)) {
            err = String.format(LocaleUtil.transferLanguage(reqBean.getUserInfo(), "生产工单[%s]未关联条码"), reqBean.getWorkOrderNo());
            this.sendMessage(reqBean, resultBean, err, MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT);
            return StepResult.getNonComplete(err);
        }

        // 从redis里面取到小包装条码的记录
        String packageTravelNo = "";
        List<InnerPackageRecordModel> outerPackageRecordModelList = getLastRecord(reqBean,produceSnExt.getSnType());
        if (null == outerPackageRecordModelList || outerPackageRecordModelList.size() == 0) {
            // redis中无值 则去条码履历表中查询最新一条
            DdlPackBean packBean = DdlPackBean.getDdlPackBean(reqBean.getOrganizeCode());
            // DdlPreparedPack.getStringEqualPack(reqBean.getProcessCode(), MesPcnExtConstWords.PROCESS_CODE, packBean);
            // DdlPreparedPack.getStringEqualPack(reqBean.getWorkCellCode(), MesPcnExtConstWords.WORK_CELL_CODE, packBean);
            DdlPreparedPack.getStringEqualPack(reqBean.getWorkOrderNo(), MesPcnExtConstWords.WORK_ORDER_NO, packBean);
            DdlPreparedPack.getNumEqualPack(produceSnExt.getSnType(), MesPcnExtConstWords.SN_TYPE, packBean);
            DdlPreparedPack.getOrderByPack(new Object[]{CommonEnumUtil.ASC_OR_DESC.DESC.getValue()}, new String[]{MesPcnExtConstWords.CREATE_DATE_TIME}, packBean);
            MesProduceSnTravelExt produceSnTravelExt = produceSnTravelExtRepository.getByProperty(packBean);
            if(null != produceSnTravelExt){
                packageTravelNo = produceSnTravelExt.getSerialNumber();
            }
        } else {
            List<String> list =  outerPackageRecordModelList.stream().sorted(Comparator.comparing(InnerPackageRecordModel::getCreateTime).reversed())
                    .filter(o -> (null != o && !StringUtils.isEmpty(o.getSerialNumber()))).map(InnerPackageRecordModel::getSerialNumber).collect(Collectors.toList());
            if(null == list || list.size() == 0){

            }else{
                packageTravelNo = list.get(0);
            }
        }
        // 通过本体条码来进行跳号防错
/*      DdlPackBean packBean = DdlPackBean.getDdlPackBean(reqBean.getOrganizeCode());
        DdlPreparedPack.getStringEqualPack(reqBean.getProcessCode(), MesPcnExtConstWords.PROCESS_CODE, packBean);
        DdlPreparedPack.getStringEqualPack(reqBean.getWorkCellCode(), MesPcnExtConstWords.WORK_CELL_CODE, packBean);
        DdlPreparedPack.getStringEqualPack(reqBean.getWorkOrderNo(), MesPcnExtConstWords.WORK_ORDER_NO, packBean);
        DdlPreparedPack.getNumEqualPack(produceSnExt.getSnType(), MesPcnExtConstWords.SN_TYPE, packBean);
        DdlPreparedPack.getOrderByPack(new Object[]{CommonEnumUtil.ASC_OR_DESC.DESC.getValue()}, new String[]{MesPcnExtConstWords.CREATE_DATE_TIME}, packBean);
        MesProduceSnTravelExt produceSnTravelExt = produceSnTravelExtRepository.getByProperty(packBean);*/
        //if (null != produceSnTravelExt) {
        // 校验本体条码生产顺序
            Integer indexOld = serialNumberList.indexOf(packageTravelNo);
            if (indexOld.compareTo(-1) == 0) {
                err = String.format(LocaleUtil.transferLanguage(reqBean.getUserInfo(), "上次扫描的产品条码[%s]未关联工单[%s]"), packageTravelNo, reqBean.getWorkOrderNo());
                this.sendMessage(reqBean, resultBean, err, MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT);
                return StepResult.getNonComplete(err);
            }
            Integer indexNew = serialNumberList.indexOf(reqBean.getSerialNumber());
            if (indexNew.compareTo(-1) == 0) {
                err = String.format(LocaleUtil.transferLanguage(reqBean.getUserInfo(), "本次扫描的产品条码[%s]未关联工单[%s]"), reqBean.getSerialNumber(), reqBean.getWorkOrderNo());
                this.sendMessage(reqBean, resultBean, err, MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT);
                return StepResult.getNonComplete(err);
            }

            int checkSnSeqMaxNum = 90;
            Map<String, String> wcpcMap  = fsmCommonService.getCachedWorkCellParam(reqBean);
            if (!CollectionUtils.isEmpty(wcpcMap) && wcpcMap.containsKey("CHECK_SN_SEQ_MAX_NUM") && !StringUtils.isEmpty(wcpcMap.get("CHECK_SN_SEQ_MAX_NUM"))) {
                checkSnSeqMaxNum = Integer.parseInt(wcpcMap.get("CHECK_SN_SEQ_MAX_NUM"));
            }

//            if (Math.abs(indexNew - indexOld) >= checkSnSeqMaxNum) {
//                err = String.format(LocaleUtil.transferLanguage(reqBean.getUserInfo(), "本次扫描的产品条码[%s]与上次扫描的产品条码[%s]间隔区间超过[%s],需验证跳号码"),
//                        reqBean.getSerialNumber(), packageTravelNo, checkSnSeqMaxNum);
//                this.sendMessage(reqBean, resultBean, err, MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT);
//
//                reqBean.getDataMap().put("LAST_SN", packageTravelNo);
//                reqBean.getDataMap().put(MesPcnExtConstWords.WORK_ORDER_NO, reqBean.getWorkOrderNo());
//                StepResult stepResult = StepResult.getSuccessComplete();
//                stepResult.setNextTriggerEvent("CHECK_INNER_SEQ");
//                return stepResult;
//            }
       // }
        return StepResult.getSuccessComplete();

    }
    private MesPackageExt getMesPackageExtModel(StationRequestBean reqBean) {
        MesPackageExt pack = packageExtService.getPackageByPackNo(reqBean.getOrganizeCode(), reqBean.getScanInfo());
        return pack;
    }

    private String getLastSelectOrderKey(StationRequestBean reqBean) {
        return getCacheKey(reqBean, MesPcnExtConstWords.INNER_PACKAGE);
    }

    private List<InnerPackageRecordModel> getLastRecord(StationRequestBean reqBean, Integer snType) {
        List<InnerPackageRecordModel> outerPackageRecordModelList = (List<InnerPackageRecordModel>) redisMesPcn.getObject(getLastSelectOrderKey(reqBean));
        if(null == outerPackageRecordModelList || outerPackageRecordModelList.size() == 0){
            return outerPackageRecordModelList;
        }else {
            List<InnerPackageRecordModel> newList = outerPackageRecordModelList.stream().filter(o -> o.getWorkOrderNo().equals(reqBean.getWorkOrderNo()) && o.getOrganizeCode().equals(reqBean.getOrganizeCode()) &&
                    snType.equals(o.getSnType())).collect(Collectors.toList());
            return newList;
        }
    }

}
