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

import cn.estsh.i3plus.ext.mes.pcn.api.busi.IProduceSnTravelExtService;
import cn.estsh.i3plus.ext.mes.pcn.pojo.bean.*;
import cn.estsh.i3plus.ext.mes.pcn.pojo.model.ep.EpSnBindOrderWorkOrderModel;
import cn.estsh.i3plus.ext.mes.pcn.pojo.repository.*;
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.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.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.MesPackageDetail;
import cn.estsh.i3plus.pojo.mes.bean.MesProdBindRecord;
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.i3plus.pojo.mes.repository.MesProdBindRecordRepository;
import cn.estsh.impp.framework.boot.util.ImppRedis;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @PROJECT_NAME: i3plus-mes-panasonic
 * @DESCRIPTION:EP条码关联工单-绑定OR解绑工步
 * @USER: xinwang.yi
 * @DATE: 2022-01-03 11:25
 */
@Slf4j
@Service("epSnBindOrderSnBindOrUnBindStepService")
public class EpSnBindOrderSnBindOrUnBindStepService extends BaseStepService {
    @Resource(name = MesPcnExtConstWords.REDIS_RES_PCN)
    private ImppRedis redisMesPcn;

    @Autowired
    private MesProduceSnExtRepository produceSnExtRepository;

    @Autowired
    private IProduceSnTravelExtService produceSnTravelExtService;

    @Autowired
    private MesWorkOrderExtBindSnRepository workOrderExtBindSnRepository;

    @Autowired
    private MesProdBindRecordRepository prodBindRecordRepository;

    @Autowired
    private MesWorkOrderExtBindSnRecordRepository workOrderExtBindSnRecordRepository;

    @Autowired
    private MesPackageExtRepository packageExtRepository;

    @Autowired
    private MesPackageDetailRepository packageDetailRepository;

    @Autowired
    private MesProduceSnTravelExtRepository produceSnTravelExtRepository;

    @Override
    public StepResult execute(StationRequestBean reqBean) {

        log.info("epSnBindOrderSnBindOrUnBindStepService[execute] 参数：{}", reqBean);
        StationResultBean resultBean = new StationResultBean();
        String curProdTypeInt = (String) doHandleCurProdType(reqBean, 1, null);

        Integer curProdType = Integer.valueOf(curProdTypeInt);

        List<MesProduceSnExt> produceSnExtList = (List<MesProduceSnExt>) doHandleProduceSnList(reqBean, 1, null);

        EpSnBindOrderWorkOrderModel curWorkOrderNo = (EpSnBindOrderWorkOrderModel) doHandleCurWorkOrder(reqBean, 1, null);

        String workOrderNo = null;
        //单个产品条码
        String serialNumber = null;
        //动作类型
        Integer actionType = MesPcnEnumUtil.MES_ACTION_TYPE.BIND.getValue();

        if(CollectionUtils.isEmpty(produceSnExtList)){
            String err = String.format(LocaleUtil.transferLanguage(reqBean.getUserInfo(), "缓存中的条码数据丢失,请重新扫描"), reqBean.getScanInfo());
            this.sendMessage(reqBean, resultBean, err, MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT);
            return StepResult.getSuccessComplete(err);
        }

        Iterator<MesProduceSnExt> mesProduceSnExtIterator = produceSnExtList.stream().iterator();
        //判断 curProdType 如果是 10或者20
        if(curProdType == MesPcnExtEnumUtil.EP_SN_BIND_ORDER_PROD_TYPE.SINGLE_BIND.getValue() || curProdType == MesPcnExtEnumUtil.EP_SN_BIND_ORDER_PROD_TYPE.BATCH_BIND.getValue()) {
            while (mesProduceSnExtIterator.hasNext()) {
                MesProduceSnExt produceSnExt = mesProduceSnExtIterator.next();
                ConvertBean.serviceModelInitialize(produceSnExt,reqBean.getUserInfo());
                produceSnExt.setOrganizeCode(reqBean.getOrganizeCode());
                new ConvertBeanExt(produceSnExt).convertBean(produceSnExt);
                produceSnExtRepository.save(produceSnExt);
                produceSnTravelExtService.insertProduceSnTravelExt(produceSnExt);
            }
        //curProdType 如果是 30或者40
        }else if(curProdType == MesPcnExtEnumUtil.EP_SN_BIND_ORDER_PROD_TYPE.SINGLE_UNBIND.getValue() || curProdType == MesPcnExtEnumUtil.EP_SN_BIND_ORDER_PROD_TYPE.BATCH_UNBIND.getValue()){

            List<String> serialNumberList = produceSnExtList.stream().map(MesProduceSnExt::getSerialNumber).collect(Collectors.toList());

            DdlPackBean packBean = DdlPackBean.getDdlPackBean(reqBean.getOrganizeCode());
            DdlPreparedPack.getInPackList(serialNumberList, MesPcnExtConstWords.SERIAL_NUMBER, packBean);
            List<MesPackageDetail> packageDetailListDb = packageDetailRepository.findByHqlWhere(packBean);

            if(!CollectionUtils.isEmpty(packageDetailListDb)){
                packageDetailListDb.stream().forEach(mesPackageExt -> {
                    ConvertBean.serviceModelUpdate(mesPackageExt, reqBean.getUserInfo());
                    mesPackageExt.setIsValid(CommonEnumUtil.IS_VAILD.INVAILD.getValue());
                });
                packageDetailRepository.saveAll(packageDetailListDb);

                List<String> packageNoList = packageDetailListDb.stream().map(MesPackageDetail::getPackageNo).collect(Collectors.toList());
                packBean = DdlPackBean.getDdlPackBean(reqBean.getOrganizeCode());
                DdlPreparedPack.getInPackList( packageNoList, MesPcnExtConstWords.PACKAGENO, packBean);
                List<MesPackageExt> packageExtListDb = packageExtRepository.findByHqlWhere(packBean);

                if(!CollectionUtils.isEmpty(packageExtListDb)){
                    packageExtListDb.stream().forEach(mesPackageExt -> {
                        mesPackageExt.setIsValid(CommonEnumUtil.IS_VAILD.INVAILD.getValue());
                        ConvertBean.serviceModelUpdate(mesPackageExt, reqBean.getUserInfo());
                        new ConvertBeanExt(mesPackageExt).convertBean(mesPackageExt);
                    });
                    packageExtRepository.saveAll(packageExtListDb);
                }
            }

            while (mesProduceSnExtIterator.hasNext()) {
                MesProduceSnExt produceSnExt = mesProduceSnExtIterator.next();
                produceSnExt.setIsValid(CommonEnumUtil.IS_VAILD.INVAILD.getValue());
                ConvertBean.serviceModelUpdate(produceSnExt, reqBean.getUserInfo());
                new ConvertBeanExt(produceSnExt).convertBean(produceSnExt);
                produceSnExtRepository.save(produceSnExt);
            }

            packBean = DdlPackBean.getDdlPackBean(reqBean.getOrganizeCode());
            DdlPreparedPack.getInPackList(serialNumberList, MesPcnExtConstWords.SERIAL_NUMBER, packBean);
            List<MesProduceSnTravelExt> produceSnTravelExts = produceSnTravelExtRepository.findByHqlWhere(packBean);

            if(!org.apache.commons.collections.CollectionUtils.isEmpty(produceSnTravelExts)){
                produceSnTravelExts.stream().forEach(mesProduceSnTravelExt -> {
                    mesProduceSnTravelExt.setIsValid(CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue());
                    ConvertBean.serviceModelUpdate(mesProduceSnTravelExt, reqBean.getUserInfo());
                    new ConvertBeanExt(mesProduceSnTravelExt).convertBean(mesProduceSnTravelExt);
                });
                produceSnTravelExtRepository.saveAll(produceSnTravelExts);
            }
        }

//        doHandleProduceSnList(reqBean, 3, null);

        DdlPackBean packBean = DdlPackBean.getDdlPackBean(reqBean.getOrganizeCode());
        DdlPreparedPack.getStringEqualPack(curWorkOrderNo.getWorkOrderNo(), MesPcnExtConstWords.WORK_ORDER_NO, packBean);
        MesWorkOrderExtBindSn workOrderExtBindSn = workOrderExtBindSnRepository.getByProperty(packBean);

        if(workOrderExtBindSn == null){
            workOrderExtBindSn = new MesWorkOrderExtBindSn();
            BeanUtils.copyProperties(curWorkOrderNo,workOrderExtBindSn, MesPcnExtConstWords.ID);
            workOrderExtBindSn.setBindQty(new Double(produceSnExtList.size()));
            workOrderExtBindSn.setTotalBindQty(workOrderExtBindSn.getBindQty());
            workOrderExtBindSn.setTotalUnbindQty(new Double(0));
            workOrderExtBindSn.setTotalBindTimes(1);
            workOrderExtBindSn.setTotalUnbindTimes(0);
            workOrderExtBindSn.setOrganizeCode(reqBean.getOrganizeCode());
            workOrderExtBindSn.setSystemSyncStatus(MesPcnExtEnumUtil.IF_SYNC_STATUS.NO_SYNC.getValue());
            ConvertBean.serviceModelInitialize(workOrderExtBindSn ,reqBean.getUserInfo());
            workOrderExtBindSnRepository.insert(workOrderExtBindSn);
        }else{
            if(curProdType == MesPcnExtEnumUtil.EP_SN_BIND_ORDER_PROD_TYPE.SINGLE_BIND.getValue() || curProdType == MesPcnExtEnumUtil.EP_SN_BIND_ORDER_PROD_TYPE.BATCH_BIND.getValue()){
                workOrderExtBindSn.setBindQty(MathOperation.add(workOrderExtBindSn.getBindQty(), new Double(produceSnExtList.size())));
                workOrderExtBindSn.setTotalBindQty(MathOperation.add(workOrderExtBindSn.getTotalBindQty(), new Double(produceSnExtList.size())));
                workOrderExtBindSn.setTotalBindTimes(workOrderExtBindSn.getTotalBindTimes() + 1);
                workOrderExtBindSn.setSystemSyncStatus(MesPcnExtEnumUtil.IF_SYNC_STATUS.NO_SYNC.getValue());
                ConvertBean.serviceModelUpdate(workOrderExtBindSn, reqBean.getUserInfo());
                workOrderExtBindSnRepository.save(workOrderExtBindSn);

            }else if(curProdType == MesPcnExtEnumUtil.EP_SN_BIND_ORDER_PROD_TYPE.SINGLE_UNBIND.getValue() || curProdType == MesPcnExtEnumUtil.EP_SN_BIND_ORDER_PROD_TYPE.BATCH_UNBIND.getValue()){
                workOrderExtBindSn.setBindQty(MathOperation.sub(workOrderExtBindSn.getBindQty(), new Double(produceSnExtList.size())));
                workOrderExtBindSn.setTotalUnbindQty(MathOperation.add(workOrderExtBindSn.getTotalUnbindQty(), new Double(produceSnExtList.size())));
                workOrderExtBindSn.setTotalUnbindTimes(workOrderExtBindSn.getTotalUnbindTimes() + 1);
                workOrderExtBindSn.setSystemSyncStatus(MesPcnExtEnumUtil.IF_SYNC_STATUS.NO_SYNC.getValue());
                ConvertBean.serviceModelUpdate(workOrderExtBindSn, reqBean.getUserInfo());
                workOrderExtBindSnRepository.save(workOrderExtBindSn);
            }
        }
        //生产工单条码绑定记录
        MesWorkOrderExtBindSnRecord workOrderExtBindSnRecord = new MesWorkOrderExtBindSnRecord();
        BeanUtils.copyProperties(curWorkOrderNo, workOrderExtBindSnRecord, MesPcnExtConstWords.ID);
        workOrderExtBindSnRecord.setProdType(curProdType);
        workOrderExtBindSnRecord.setSerialNumber(produceSnExtList.get(0).getSerialNumber());
        if(produceSnExtList.size() > 1){
            workOrderExtBindSnRecord.setSerialNumberEnd(produceSnExtList.get(produceSnExtList.size()-1).getSerialNumber());
        }
        workOrderExtBindSnRecord.setOperateQty(new Double(produceSnExtList .size()));
        ConvertBean.serviceModelInitialize(workOrderExtBindSnRecord,reqBean.getUserInfo());
        workOrderExtBindSnRecord.setOrganizeCode(reqBean.getOrganizeCode());
        workOrderExtBindSnRecord.setSystemSyncStatus(MesPcnExtEnumUtil.IF_SYNC_STATUS.NO_SYNC.getValue());
        workOrderExtBindSnRecordRepository.save(workOrderExtBindSnRecord);

        if(curProdType == MesPcnExtEnumUtil.EP_SN_BIND_ORDER_PROD_TYPE.SINGLE_UNBIND.getValue() || curProdType == MesPcnExtEnumUtil.EP_SN_BIND_ORDER_PROD_TYPE.BATCH_UNBIND.getValue()){
            if(curProdType == MesPcnExtEnumUtil.EP_SN_BIND_ORDER_PROD_TYPE.SINGLE_UNBIND.getValue()){
                workOrderNo = curWorkOrderNo.getWorkOrderNo();
                serialNumber = produceSnExtList.get(0).getSerialNumber();
                //查询操作过的条码记录
                packBean = DdlPackBean.getDdlPackBean(reqBean.getOrganizeCode());
                DdlPreparedPack.getStringEqualPack(workOrderNo, MesPcnExtConstWords.WORK_ORDER_NO, packBean);
                DdlPreparedPack.getStringEqualPack(serialNumber, MesPcnExtConstWords.SERIAL_NUMBER, packBean);
                DdlPreparedPack.getNumEqualPack(actionType, MesPcnExtConstWords.ACTION_TYPE, packBean);
                MesProdBindRecord prodBindRecord = prodBindRecordRepository.getByProperty(packBean);
                if(prodBindRecord != null){
                    prodBindRecord.setActionType(MesPcnEnumUtil.MES_ACTION_TYPE.UNTYING.getValue());
                    ConvertBean.serviceModelUpdate(prodBindRecord, reqBean.getUserInfo());
                    prodBindRecordRepository.save(prodBindRecord);
                }

            }else{
                //查询已绑定过的记录
                String snWithoutSeqNo = produceSnExtList.get(0).getSnWithoutSeqNo();
                List<String> serialNumberList = produceSnExtList.stream().map(MesProduceSnExt::getSerialNumber).collect(Collectors.toList());
                String leftSn = snWithoutSeqNo.substring(0, snWithoutSeqNo.indexOf(MesPcnExtConstWords.SEQNO));
                packBean = DdlPackBean.getDdlPackBean(reqBean.getOrganizeCode());
                DdlPreparedPack.getStringEqualPack(workOrderNo, MesPcnExtConstWords.WORK_ORDER_NO, packBean);
                DdlPreparedPack.getStringRightLikerPack(leftSn, MesPcnExtConstWords.SERIAL_NUMBER, packBean);
                DdlPreparedPack.getNumEqualPack(actionType, MesPcnExtConstWords.ACTION_TYPE, packBean);
                List<MesProdBindRecord> prodBindRecord = prodBindRecordRepository.findByHqlWhere(packBean);

                List<MesProdBindRecord> prodBindRecordsMeta = prodBindRecord.stream().filter(mesProdBindRecord -> serialNumberList.contains(mesProdBindRecord.getSerialNumber())).collect(Collectors.toList());
                Iterator<MesProdBindRecord> iterator = prodBindRecordsMeta.stream().iterator();
                List<MesProdBindRecord> prodBindRecords = new ArrayList<>();
                while (iterator.hasNext()){
                    MesProdBindRecord next = iterator.next();
                    next.setActionType(MesPcnEnumUtil.MES_ACTION_TYPE.UNTYING.getValue());
                    prodBindRecords.add(next);
                }
                if(CollectionUtils.isEmpty(prodBindRecords)){
                    prodBindRecordRepository.saveAll(prodBindRecords);
                }
            }
        }
        return StepResult.getSuccessComplete();
    }

    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 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;
        }
    }
}
