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

import cn.estsh.i3plus.ext.mes.pcn.pojo.bean.MesProduceSnExt;
import cn.estsh.i3plus.ext.mes.pcn.pojo.model.ep.EpSnBindOrderWorkOrderModel;
import cn.estsh.i3plus.ext.mes.pcn.pojo.repository.MesProduceSnExtRepository;
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.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.MesPcnEnumUtil;
import cn.estsh.i3plus.pojo.base.tool.DdlPreparedPack;
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.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @PROJECT_NAME: i3plus-mes-panasonic
 * @DESCRIPTION:通用工步1:EP条码关联工单-单个解绑条码校验工步
 * @USER: xinwang.yi
 * @DATE: 2022-01-03 12:36
 */
@Slf4j
@Service("epSnBindOrderSnUnBindCheckStepService")
public class EpSnBindOrderSnUnBindCheckStepService extends BaseStepService {

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

    @Autowired
    private MesProduceSnExtRepository produceSnExtRepository;

    @Override
    public StepResult guide(StationRequestBean reqBean) {
        StationResultBean resultBean = new StationResultBean();
        String curProdTypeInt = (String) doHandleCurProdType(reqBean, 1, null);
        Integer curProdType = Integer.valueOf(curProdTypeInt);
        if(curProdType == MesPcnExtEnumUtil.EP_SN_BIND_ORDER_PROD_TYPE.SINGLE_BIND.getValue()){
            String guide = LocaleUtil.transferLanguage(reqBean.getUserInfo(), "请扫描需要解绑的产品条码");
            this.sendMessage(reqBean, resultBean, guide, MesPcnEnumUtil.STATION_BUSI_TYPE.GUIDE, MesPcnEnumUtil.STATION_DATA_TYPE.TEXT);
        }else if(curProdType == MesPcnExtEnumUtil.EP_SN_BIND_ORDER_PROD_TYPE.BATCH_BIND.getValue()){
            List<MesProduceSnExt> produceSnExtList = (List<MesProduceSnExt>) doHandleProduceSnList(reqBean, 1 ,null);
            if(CollectionUtils.isEmpty(produceSnExtList)){
                String guide = LocaleUtil.transferLanguage(reqBean.getUserInfo(), "请扫描需要解绑的区间[首]产品条码");
                this.sendMessage(reqBean, resultBean, guide, MesPcnEnumUtil.STATION_BUSI_TYPE.GUIDE, MesPcnEnumUtil.STATION_DATA_TYPE.TEXT);
            }else{
                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 execute(StationRequestBean reqBean) {
        log.info("epSnBindOrderSnUnBindCheckStepService[execute] 参数：{}", reqBean);
        StationResultBean resultBean = new StationResultBean();

        String scanInfo = reqBean.getScanInfo();
        if(StringUtils.isEmpty(scanInfo)){
            doHandleProduceSnList(reqBean, 3, null);
            return StepResult.getNonComplete();
        }
        EpSnBindOrderWorkOrderModel curWorkOrderNo = (EpSnBindOrderWorkOrderModel) doHandleCurWorkOrder(reqBean, 1 ,null);
        DdlPackBean packBean = DdlPackBean.getDdlPackBean(reqBean.getOrganizeCode());
        DdlPreparedPack.getStringEqualPack(scanInfo, MesPcnExtConstWords.SERIAL_NUMBER, packBean);
        MesProduceSnExt produceSnExtDb = produceSnExtRepository.getByProperty(packBean);
        if(produceSnExtDb == null){
            String message = String.format(LocaleUtil.transferLanguage(reqBean.getUserInfo(), "产品条码[%s]在系统中不存在,请重新扫描"), scanInfo);
            this.sendMessage(reqBean, resultBean, message, MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT);
            doHandleProduceSnList(reqBean, 3, null);
            return StepResult.getNonComplete(message);
        }else{
            if(!(produceSnExtDb.getSnStatus() == MesPcnExtEnumUtil.PRODUCE_SN_STATUS.CREATE.getValue())){
                String message = String.format(LocaleUtil.transferLanguage(reqBean.getUserInfo(), "产品条码[%s]状态为[%s],不支持解绑,请重新扫描"), scanInfo, MesPcnExtEnumUtil.PRODUCE_SN_STATUS.valueOfDescription(produceSnExtDb.getSnStatus()));
                this.sendMessage(reqBean, resultBean, message, MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT);
                doHandleProduceSnList(reqBean, 3, null);
                return StepResult.getNonComplete(message);
            }

            if(!produceSnExtDb.getWorkOrderNo().equals(curWorkOrderNo.getWorkOrderNo())){
                String message = String.format(LocaleUtil.transferLanguage(reqBean.getUserInfo(), "产品条码[%s]未关联当前执行工单[%s],不支持解绑,请重新扫描"), scanInfo, curWorkOrderNo.getWorkOrderNo());
                this.sendMessage(reqBean, resultBean, message, MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT);
                doHandleProduceSnList(reqBean, 3, null);
                return StepResult.getNonComplete(message);
            }

            if(!produceSnExtDb.getLastWorkOrderNo().equals(produceSnExtDb.getWorkOrderNo())){
                String message = String.format(LocaleUtil.transferLanguage(reqBean.getUserInfo(), "产品条码[%s]已经关联返工工单[%s],不支持解绑,请重新扫描"), scanInfo, produceSnExtDb.getLastWorkOrderNo());
                this.sendMessage(reqBean, resultBean, message, MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT);
                doHandleProduceSnList(reqBean, 3, null);
                return StepResult.getNonComplete(message);
            }
        }

        List<MesProduceSnExt> produceSnExtList = (List<MesProduceSnExt>) doHandleProduceSnList(reqBean, 1, null);
        String curProdTypeString = (String) doHandleCurProdType(reqBean, 1, null);
        Integer curProdType = Integer.valueOf(curProdTypeString);
        if(CollectionUtils.isEmpty(produceSnExtList)){
            produceSnExtList = new ArrayList<>();
            produceSnExtList.add(produceSnExtDb);
            doHandleProduceSnList(reqBean, 2, produceSnExtList);

            if(curProdType == MesPcnExtEnumUtil.EP_SN_BIND_ORDER_PROD_TYPE.SINGLE_UNBIND.getValue()){
                String message = String.format(LocaleUtil.transferLanguage(reqBean.getUserInfo(), "产品条码[%s]解绑校验成功"), scanInfo);
                this.sendMessage(reqBean, resultBean, message, MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.TEXT);
                return StepResult.getSuccessComplete(message);
            }else if(curProdType == MesPcnExtEnumUtil.EP_SN_BIND_ORDER_PROD_TYPE.BATCH_UNBIND.getValue()){
                String message = String.format(LocaleUtil.transferLanguage(reqBean.getUserInfo(), "区间[首]产品条码[%s]解绑校验成功"), scanInfo);
                this.sendMessage(reqBean, resultBean, message, MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.TEXT);
                return StepResult.getNonComplete(message);
            }
        }

        if(produceSnExtList.get(0).getSerialNumber().equals(produceSnExtDb.getSerialNumber())){
            String message = String.format(LocaleUtil.transferLanguage(reqBean.getUserInfo(), "当前扫描区间[首]产品条码[%s]与区间[尾]产品条码[%s]一致,请重新扫描区间[首]产品条码"), produceSnExtList.get(0).getSerialNumber(), scanInfo );
            this.sendMessage(reqBean, resultBean, message, MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT);
            doHandleProduceSnList(reqBean, 3, produceSnExtList);
            return StepResult.getNonComplete(message);
        }

        String snWithoutSeqNo = produceSnExtList.get(0).getSnWithoutSeqNo();

        log.info("首条码匹配部分：{}",snWithoutSeqNo);
        log.info("尾条码匹配部分：{}",produceSnExtDb.getSnWithoutSeqNo());
        if(!snWithoutSeqNo.equals(produceSnExtDb.getSnWithoutSeqNo())){
            String message = String.format(LocaleUtil.transferLanguage(reqBean.getUserInfo(), "当前扫描区间[首]产品条码[%s]与区间[尾]产品条码[%s]除流水号以外部分不一致,请重新扫描区间[首]产品条码"), produceSnExtList.get(0).getSerialNumber(), scanInfo );
            this.sendMessage(reqBean, resultBean, message, MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT);
            doHandleProduceSnList(reqBean, 3, produceSnExtList);
            return StepResult.getNonComplete(message);
        }

        String[] seqNoFArray = produceSnExtList.get(0).getSeqNo().split(MesPcnExtConstWords.COMMA);
        String[] seqNoSArray = produceSnExtDb.getSeqNo().split(MesPcnExtConstWords.COMMA);
        String seqNoF = seqNoFArray[0];
        String seqNoS = seqNoSArray[0];
        String seqNoF2 = null;
        String seqNoS2 = null;
        if(seqNoFArray.length > 1){
            seqNoF2 = seqNoFArray[1];
            seqNoS2 = seqNoSArray[1];
        }

        if(Integer.valueOf(seqNoF).compareTo(Integer.valueOf(seqNoS)) >=0 ){
            String message = String.format(LocaleUtil.transferLanguage(reqBean.getUserInfo(), "当前扫描区间[首]产品条码[%s]的流水号[%s]不小于区间[尾]产品条码[%s]的流水号[%s],请重新扫描区间[首]产品条码"), produceSnExtList.get(0).getSerialNumber(), produceSnExtList.get(0).getSeqNo(), scanInfo, produceSnExtDb.getSeqNo());
            this.sendMessage(reqBean, resultBean, message, MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT);
            doHandleProduceSnList(reqBean, 3, produceSnExtList);
            return StepResult.getNonComplete(message);
        }

        if(!StringUtils.isEmpty(seqNoS2) && Integer.valueOf(seqNoF2 ).compareTo(Integer.valueOf(seqNoS2)) >= 0 ){
            doHandleProduceSnList(reqBean, 3, null);
            String err = String.format(LocaleUtil.transferLanguage(reqBean.getUserInfo(), "当前扫描区间[首]产品条码[%s]的二段流水号[%s]不小于区间[尾]产品条码[%s]的二段流水号[%s],请重新扫描区间[首]产品条码"),produceSnExtList.get(0).getSerialNumber(), seqNoF2, reqBean.getScanInfo(), seqNoS2);
            this.sendMessage(reqBean, resultBean, err, MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT);
            return StepResult.getNonComplete(err);
        }

        if(!StringUtils.isEmpty(seqNoF2)){
            if(Integer.valueOf(seqNoS).compareTo(Integer.valueOf(seqNoF)) != Integer.valueOf(seqNoS2).compareTo(Integer.valueOf(seqNoF2))){
                doHandleProduceSnList(reqBean, 3, null);
                String err = String.format(LocaleUtil.transferLanguage(reqBean.getUserInfo(), "前扫描区间[首-尾]产品条码的2段流水号[%s-%s]的区间数量和1段流水号区间数量不一致,请将产品条码调整好再进行绑定"),produceSnExtList.get(0).getSeqNo(), produceSnExtDb.getSeqNo());
                this.sendMessage(reqBean, resultBean, err, MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT);
                return StepResult.getNonComplete(err);
            }
        }

        List<String> serialNumberList = new LinkedList<>();
        List<String> seqNoList = new ArrayList<>();
        List<String> seqNo2List = null;

        seqNoListCollect(seqNoList, seqNoF, seqNoS);
        if(!StringUtils.isEmpty(seqNoF2)){
            seqNo2List = new ArrayList<>();
            seqNoListCollect(seqNo2List, seqNoF2, seqNoS2);
        }

        Iterator<String> seqNoListIterator = seqNoList.stream().iterator();
        while (seqNoListIterator.hasNext()){
            String seqNo = seqNoListIterator.next();
            serialNumberList.add(snWithoutSeqNo.replaceFirst(MesPcnExtConstWords.SEQNO, seqNo));
        }

        if(!CollectionUtils.isEmpty(seqNo2List)){
            Boolean flag = false;
            for (int seqIndex = 0; seqIndex < seqNo2List.size();seqIndex++) {
                if(CollectionUtils.isEmpty(serialNumberList) && flag == false){
                    flag =true;
                }

                if(flag == true){
                    serialNumberList.add(snWithoutSeqNo.replaceFirst(MesPcnExtConstWords.SEQNO2, seqNo2List.get(seqIndex)));
                }else{
                    serialNumberList.set(seqIndex, serialNumberList.get(seqIndex).replaceFirst(MesPcnExtConstWords.SEQNO2, seqNo2List.get(seqIndex)));
                }
            }
        }

        String leftSn = snWithoutSeqNo.substring(0, snWithoutSeqNo.indexOf(MesPcnExtConstWords.SEQNO));
        packBean = DdlPackBean.getDdlPackBean(reqBean.getOrganizeCode());
        DdlPreparedPack.getStringRightLikerPack(leftSn, MesPcnExtConstWords.SERIAL_NUMBER, packBean);
        List<MesProduceSnExt> produceSnExtDbList = produceSnExtRepository.findByHqlWhere(packBean);

        List<MesProduceSnExt> produceSnExtDbNeedUnBindList = produceSnExtDbList.stream().filter(mesProduceSnExt -> serialNumberList.contains(mesProduceSnExt.getSerialNumber())).collect(Collectors.toList());
        if(!(produceSnExtDbNeedUnBindList.size() == serialNumberList.size())){
            String message = String.format(LocaleUtil.transferLanguage(reqBean.getUserInfo(), "当前扫描区间[首]产品条码[%s]与区间[尾]产品条码[%s]中有[%s]个产品条码未绑定生产工单,请重新扫描区间[首]产品条码"), produceSnExtList.get(0).getSerialNumber(), scanInfo, serialNumberList.size()-produceSnExtDbNeedUnBindList.size());
            this.sendMessage(reqBean, resultBean, message, MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT);
            doHandleProduceSnList(reqBean, 3, produceSnExtList);
            return StepResult.getNonComplete(message);
        }

        Iterator<MesProduceSnExt> mesProduceSnExtIterator = produceSnExtDbNeedUnBindList.stream().iterator();
        while (mesProduceSnExtIterator.hasNext()){
            MesProduceSnExt item = mesProduceSnExtIterator.next();
            if(!(item.getSnStatus() == MesPcnExtEnumUtil.PRODUCE_SN_STATUS.CREATE.getValue())){
                String message = String.format(LocaleUtil.transferLanguage(reqBean.getUserInfo(), "区间内的产品条码[%s]状态为[%s],不支持解绑,请重新扫描区间[首]产品条码"), item.getSerialNumber(), MesPcnExtEnumUtil.PRODUCE_SN_STATUS.valueOfDescription(item.getSnStatus()));
                this.sendMessage(reqBean, resultBean, message, MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT);
                doHandleProduceSnList(reqBean, 3, produceSnExtList);
                return StepResult.getNonComplete(message);
            }

            if(!item.getWorkOrderNo().equals(curWorkOrderNo.getWorkOrderNo())){
                String message = String.format(LocaleUtil.transferLanguage(reqBean.getUserInfo(), "区间内的产品条码[%s]未关联当前执行工单[%s],不支持解绑,请重新扫描区间[首]产品条码"), item.getSerialNumber(), item.getWorkOrderNo());
                this.sendMessage(reqBean, resultBean, message, MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT);
                doHandleProduceSnList(reqBean, 3, produceSnExtList);
                return StepResult.getNonComplete(message);
            }

            if(!item.getLastWorkOrderNo().equals(item.getWorkOrderNo())){
                String message = String.format(LocaleUtil.transferLanguage(reqBean.getUserInfo(), "区间内的产品条码[%s]已经关联返工工单[%s],不支持解绑,请重新扫描区间[首]产品条码"), item.getSerialNumber(), item.getLastWorkOrderNo());
                this.sendMessage(reqBean, resultBean, message, MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT);
                doHandleProduceSnList(reqBean, 3, produceSnExtList);
                return StepResult.getNonComplete(message);
            }
        }
        produceSnExtList.addAll(produceSnExtDbNeedUnBindList);
        doHandleProduceSnList(reqBean, 2, produceSnExtList);
        String message = String.format(LocaleUtil.transferLanguage(reqBean.getUserInfo(), "区间[尾]产品条码[%s]解绑校验成功"), scanInfo);
        this.sendMessage(reqBean, resultBean, message, MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.TEXT);
        return StepResult.getSuccessComplete(message);
    }

    private synchronized Object doHandleCurWorkOrder(StationRequestBean reqBean, Integer flag, EpSnBindOrderWorkOrderModel curWorkOrderNo) {
        switch (flag) {
            case 1:
                return redisMesPcn.getHash(getCacheKey(reqBean, MesPcnExtConstWords.PROD_DATA), MesPcnExtConstWords.CUR_WORK_ORDER);
            case 2:
                return redisMesPcn.putHash(getCacheKey(reqBean, MesPcnExtConstWords.PROD_DATA), MesPcnExtConstWords.CUR_WORK_ORDER, curWorkOrderNo, MesPcnEnumUtil.EXPIRE_TIME.NEVER.getValue());
            case 3:
                redisMesPcn.deleteHash(getCacheKey(reqBean, MesPcnExtConstWords.PROD_DATA), MesPcnExtConstWords.CUR_WORK_ORDER);
                return true;
            default:
                return null;
        }
    }

    public synchronized Object doHandleCurProdType(StationRequestBean reqBean, Integer flag, String curProdType) {
        switch (flag) {
            case 1:
                return redisMesPcn.getHash(getCacheKey(reqBean, MesPcnExtConstWords.PROD_DATA), MesPcnExtConstWords.CUR_PROD_TYPE);
            case 2:
                return redisMesPcn.putHash(getCacheKey(reqBean, MesPcnExtConstWords.PROD_DATA), MesPcnExtConstWords.CUR_PROD_TYPE, curProdType, MesPcnEnumUtil.EXPIRE_TIME.NEVER.getValue());
            case 3:
                redisMesPcn.deleteHash(getCacheKey(reqBean, MesPcnExtConstWords.PROD_DATA), MesPcnExtConstWords.CUR_PROD_TYPE);
                return true;
            default:
                return null;
        }
    }

    public synchronized Object doHandleProduceSnList(StationRequestBean reqBean, Integer flag, List<MesProduceSnExt> produceSnExtList) {
        switch (flag) {
            case 1:
                return redisMesPcn.getHash(getCacheKey(reqBean, MesPcnExtConstWords.PROD_DATA), MesPcnExtConstWords.SN_MODEL_LIST);
            case 2:
                return redisMesPcn.putHash(getCacheKey(reqBean, MesPcnExtConstWords.PROD_DATA), MesPcnExtConstWords.SN_MODEL_LIST, produceSnExtList, MesPcnEnumUtil.EXPIRE_TIME.NEVER.getValue());
            case 3:
                redisMesPcn.deleteHash(getCacheKey(reqBean, MesPcnExtConstWords.PROD_DATA), MesPcnExtConstWords.SN_MODEL_LIST);
                return true;
            default:
                return null;
        }
    }

    private void seqNoListCollect(List<String> seqNoList,String seqNoF, String seqNoS){
        for (int seq = Integer.valueOf(seqNoF)+1; seq <= Integer.valueOf(seqNoS); seq++){
            StringBuffer seqStrbuf = new StringBuffer();
            String seqStr = String.valueOf(seq);
            if(seqStr.length() < seqNoF.length()){
                while (seqStrbuf.length() < seqNoF.length()-seqStr.length()){
                    seqStrbuf.append("0");
                }
            }
            seqStrbuf.append(seqStr);
            seqNoList.add(seqStrbuf.toString());
        }
    }
}
