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

import cn.estsh.i3plus.ext.mes.pcn.api.base.ISxWorkOrderExtService;
import cn.estsh.i3plus.ext.mes.pcn.api.busi.IProduceSnExtService;
import cn.estsh.i3plus.ext.mes.pcn.api.busi.ep.IEpWorkOrderExtBindSnService;
import cn.estsh.i3plus.ext.mes.pcn.apiservice.dao.IPackageExtDao;
import cn.estsh.i3plus.ext.mes.pcn.apiservice.dao.IProduceSnRepairDao;
import cn.estsh.i3plus.ext.mes.pcn.pojo.bean.MesProduceSnExt;
import cn.estsh.i3plus.ext.mes.pcn.pojo.bean.MesWorkOrderExt;
import cn.estsh.i3plus.ext.mes.pcn.pojo.bean.MesWorkOrderExtBindSn;
import cn.estsh.i3plus.ext.mes.pcn.pojo.model.ProduceSnExtModel;
import cn.estsh.i3plus.ext.mes.pcn.pojo.model.SnAndPackageNoCorrelationModel;
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.api.iservice.busi.IShippingDispatchService;
import cn.estsh.i3plus.mes.pcn.serviceimpl.base.BaseModuleService;
import cn.estsh.i3plus.mes.pcn.util.LocaleUtil;
import cn.estsh.i3plus.mes.pcn.util.PojoAttrUtil;
import cn.estsh.i3plus.platform.common.exception.ImppExceptionEnum;
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.MesStateMachineStatus;
import cn.estsh.i3plus.pojo.mes.model.AttrBean;
import cn.estsh.i3plus.pojo.mes.model.StationRequestBean;
import cn.estsh.i3plus.pojo.mes.model.StationResultBean;
import cn.estsh.impp.framework.boot.exception.ImppExceptionBuilder;
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.*;
import java.util.stream.Collectors;

/**
 * @Description : 展示组件：EP打包下线报工
 * @Reference :
 * @Author :wangjie
 * @CreateDate : 2020-06-26 11:18 上午
 * @Modify:
 **/
@Slf4j
@Service("epSnLineOffModuleService")
public class EpSnLineOffModuleService extends BaseModuleService {

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

    @Autowired
    private ISxWorkOrderExtService workOrderExtService;

    @Autowired
    private IProduceSnExtService produceSnExtService;

    @Autowired
    private IProduceSnRepairDao produceSnRepairDao;

    @Autowired
    private IPackageExtDao packageExtDao;

    @Autowired
    private IEpWorkOrderExtBindSnService workOrderExtBindSnService;

    @Autowired
    private IShippingDispatchService shippingDispatchService;

    private static final String EP_SN_LINE_OFF_DATA = "EP_SN_LINE_OFF_DATA";

    private static final String CUR_WORK_ORDER_NO = "CUR_WORK_ORDER_NO";
    private static final String CMD_WORK_ORDER = "CMD_WORK_ORDER";
    private static final String SN_COLON_RFID_NO = "SN_COLON_RFID_NO";

    @Override
    public void init(StationRequestBean reqBean) {
        StationResultBean resultBean = new StationResultBean();

        resultBean.setBusiType(MesPcnEnumUtil.STATION_BUSI_TYPE.MODULE_CONTENT.getValue());
        resultBean.setDataType(MesPcnEnumUtil.STATION_DATA_TYPE.CUSTOM.getValue());
        resultBean.setCustomPageName(MesPcnExtConstWords.EP_SN_LINE_OFF_MODULE);
        resultBean.setDataAttrList(packDataAttrList(reqBean));
        resultBean.setSpecialDisplayData(getStepColIndent(reqBean));

        String curWorkOrderNo = (String)doHandleCurWorkOrderNo(reqBean, 1, null);
        if (!StringUtils.isEmpty(curWorkOrderNo)) {
            MesWorkOrderExt workOrderExt = workOrderExtService.getWorkOrderExtByOrderNo(reqBean.getOrganizeCode(), curWorkOrderNo);
            if (null != workOrderExt) {
                resultBean.setResultMap(packResultMap(workOrderExt));
                resultBean.setResultList(packResultList(reqBean, workOrderExt));
            }
        }
        this.sendMessage(reqBean, resultBean);
    }

    private List<ProduceSnExtModel> packResultList(StationRequestBean reqBean, MesWorkOrderExt workOrderExt) {
        List<ProduceSnExtModel> modelList = null;
        if (MesPcnExtEnumUtil.WORK_ORDER_TYPE.REWORK_ORDER.getValue() != workOrderExt.getWorkOrderType()) {
            List<MesProduceSnExt> produceSnExtList = produceSnExtService.getProduceSnExtListByOrderNo(reqBean.getOrganizeCode(), workOrderExt.getOrderNo());
            List<SnAndPackageNoCorrelationModel> snAndPackageNoModelList = packageExtDao.getSnAndPackCorrelationListByOrderNo(reqBean.getOrganizeCode(), workOrderExt.getOrderNo());
            Optional<SnAndPackageNoCorrelationModel> errorDataOp = CollectionUtils.isEmpty(snAndPackageNoModelList) ? null :
                    snAndPackageNoModelList.stream().filter(o -> (null != o && StringUtils.isEmpty(o.getSerialNumber()))).findFirst();
            if (null != errorDataOp && errorDataOp.isPresent()) {
                String err = String.format(LocaleUtil.transferLanguage(reqBean.getUserInfo(), "生产工单[%s]下的包装条码[%s]没有对应包装明细数据"), workOrderExt.getOrderNo(), errorDataOp.get().getPackageNo());
                this.sendMessage(reqBean,  null, err, MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT);
                throw ImppExceptionBuilder.newInstance()
                        .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                        .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                        .setErrorDetail(err)
                        .build();
            }
            Map<String, List<SnAndPackageNoCorrelationModel>> snAndPackageNoMap = CollectionUtils.isEmpty(snAndPackageNoModelList) ? null :
                    snAndPackageNoModelList.stream().filter(o -> null != o).collect(Collectors.groupingBy(SnAndPackageNoCorrelationModel::getSerialNumber));
            if (!CollectionUtils.isEmpty(produceSnExtList)) {
                for (MesProduceSnExt produceSnExt : produceSnExtList) {
                    if (null == produceSnExt) {
                        continue;
                    }
                    if (CollectionUtils.isEmpty(modelList)) {
                        modelList = new ArrayList<>();
                    }
                    ProduceSnExtModel model = new ProduceSnExtModel();
                    BeanUtils.copyProperties(produceSnExt, model, MesPcnExtConstWords.ID);
                    model.setSnStatusName(MesPcnExtEnumUtil.PRODUCE_SN_STATUS.valueOfDescription(produceSnExt.getSnStatus()));
                    model.setPackageNo((!CollectionUtils.isEmpty(snAndPackageNoMap) && snAndPackageNoMap.containsKey(produceSnExt.getSerialNumber()))
                            ? snAndPackageNoMap.get(produceSnExt.getSerialNumber()).get(0).getPackageNo() : null);
                    modelList.add(model);
                }
            }
        } else {
            ProduceSnExtModel param = new ProduceSnExtModel(reqBean.getOrganizeCode(), workOrderExt.getOrderNo());
            modelList = produceSnRepairDao.queryProduceSnRepairList(param);
            if (!CollectionUtils.isEmpty(modelList)) {
                for (ProduceSnExtModel model : modelList) {
                    if (null == model) {
                        continue;
                    }
                    model.setSnStatusName(MesPcnExtEnumUtil.PRODUCE_SN_STATUS.valueOfDescription(model.getSnStatus()));
                }
            }
        }

        List<ProduceSnExtModel> resultList = null;
        if (!CollectionUtils.isEmpty(modelList)) {
            List<ProduceSnExtModel> resultList1 = modelList.stream().filter(o -> (null != o && !StringUtils.isEmpty(o.getOutWorkCenterTime()))).collect(Collectors.toList());
            List<ProduceSnExtModel> resultList2 = modelList.stream().filter(o -> (null != o && StringUtils.isEmpty(o.getOutWorkCenterTime()))).collect(Collectors.toList());
            resultList1 = CollectionUtils.isEmpty(resultList1) ? null :
                    resultList1.stream().sorted(Comparator.comparing(ProduceSnExtModel::getOutWorkCenterTime).reversed()).collect(Collectors.toList());
            resultList2 = CollectionUtils.isEmpty(resultList2) ? null :
                    resultList2.stream().sorted(Comparator.comparing(ProduceSnExtModel::getSerialNumber)).collect(Collectors.toList());
            if (!CollectionUtils.isEmpty(resultList1) || !CollectionUtils.isEmpty(resultList2)) {
                resultList = new ArrayList<>();
                if (!CollectionUtils.isEmpty(resultList1)) {
                    resultList.addAll(resultList1);
                }
                if (!CollectionUtils.isEmpty(resultList2)) {
                    resultList.addAll(resultList2);
                }
            }
        }
        return resultList;
    }

    private Map<String, Object> packResultMap(MesWorkOrderExt workOrderExt) {
        MesWorkOrderExtBindSn workOrderExtBindSn = workOrderExtBindSnService.getWorkOrderExtBindSnByOrderNo(workOrderExt.getOrganizeCode(), workOrderExt.getOrderNo());
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put(MesPcnExtConstWords.CUR_WORK_ORDER_NO, workOrderExt.getOrderNo());
        resultMap.put(MesPcnExtConstWords.WORK_ORDER_TYPE_NAME, MesPcnExtEnumUtil.WORK_ORDER_TYPE.valueOfDescription(workOrderExt.getWorkOrderType()));
        resultMap.put(MesPcnExtConstWords.PART_NO, workOrderExt.getPartNo());
        resultMap.put(MesPcnExtConstWords.PART_NAME, workOrderExt.getPartNameRdd());
        resultMap.put(MesPcnExtConstWords.QTY, workOrderExt.getQty());
        resultMap.put(MesPcnExtConstWords.COMPLETE_QTY, workOrderExt.getCompleteQty());
        resultMap.put(MesPcnExtConstWords.MISSING_QTY, workOrderExt.getMissingQty());
        resultMap.put(MesPcnExtConstWords.BIND_QTY, null != workOrderExtBindSn ? workOrderExtBindSn.getBindQty() : new Double(0));
        return resultMap;
    }

    private List<AttrBean> packDataAttrList(StationRequestBean reqBean) {
        List<AttrBean> attrBeanList = new ArrayList<>();
        PojoAttrUtil.loadPojoAttrs(attrBeanList, MesPcnExtConstWords.SERIAL_NUMBER, LocaleUtil.transferLanguage(reqBean.getUserInfo(), "产品条码"));
        PojoAttrUtil.loadPojoAttrs(attrBeanList, MesPcnExtConstWords.SN_STATUS_NAME, LocaleUtil.transferLanguage(reqBean.getUserInfo(), "条码状态"));
        PojoAttrUtil.loadPojoAttrs(attrBeanList, MesPcnExtConstWords.PACKAGENO, LocaleUtil.transferLanguage(reqBean.getUserInfo(), "包装条码"));
        PojoAttrUtil.loadPojoAttrs(attrBeanList, MesPcnExtConstWords.OUT_WC_TIME, LocaleUtil.transferLanguage(reqBean.getUserInfo(), "下线时间"));
        return attrBeanList;
    }


    @Override
    public boolean doFunction(StationRequestBean reqBean) {
        Boolean result = false;
        String err;
        Map<String, Object> dataMap = reqBean.getDataMap();
        String command = (String) dataMap.get(MesPcnExtConstWords.COMMAND);
        Object value = dataMap.get(MesPcnExtConstWords.VALUE);
        if (StringUtils.isEmpty(command)) {
            err = LocaleUtil.transferLanguage(reqBean.getUserInfo(), "后端未获取到业务功能指令");
            this.sendMessage(reqBean,  null, err, MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT);
            return result;
        }

        switch (command) {
            case CMD_WORK_ORDER :
                if (StringUtils.isEmpty(value)) {
                    err = LocaleUtil.transferLanguage(reqBean.getUserInfo(), "请选择工单");
                    this.sendMessage(reqBean,  null, err, MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT);
                    return result;
                }
                String curWorkOrderNo = (String)doHandleCurWorkOrderNo(reqBean, 1, null);
                if (!StringUtils.isEmpty(curWorkOrderNo) && curWorkOrderNo.equals(value.toString())) {
                    return result;
                }
                if (StringUtils.isEmpty(doHandleSelectWorkOrderNo(reqBean, 1, null))) {
                    doHandleSelectWorkOrderNo(reqBean, 2, value.toString());
                    result = true;
                }
                break;
            default:
                break;
        }

        if (!result) {
            err = LocaleUtil.transferLanguage(reqBean.getUserInfo(), "操作太频繁");
            this.sendMessage(reqBean,  null, err, MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT);
        } else {
            //跳过工序
            reqBean.setClientInfo(shippingDispatchService.getActorClientInfo(reqBean));
            reqBean.setInterfaceType(MesPcnConstWords.SHIPPING);
            reqBean.setBusiType(MesPcnConstWords.WS_CMD_DO_SCAN);
            reqBean.setForceJumpProcess(true);
            shippingDispatchService.doSendScanQueueNextExec(reqBean);
        }
        return result;
    }

    @Override
    public boolean execute(StationRequestBean reqBean) {
        return true;
    }

    @Override
    public boolean execStateModule(StationRequestBean reqBean, List<MesStateMachineStatus> states, Map<String, String> wcpcMap) {
        init(reqBean);
        return true;
    }

    private String getDataKey(StationRequestBean reqBean) {
        return new StringJoiner(MesPcnExtConstWords.COLON)
                .add(reqBean.getOrganizeCode()).add(EP_SN_LINE_OFF_DATA).add(reqBean.getWorkCenterCode()).toString();
    }

    public Object doHandleCurWorkOrderNo(StationRequestBean reqBean, Integer flag, String curWorkOrderNo) {
        switch (flag) {
            case 1:
                return redisMesPcn.getHash(getDataKey(reqBean), CUR_WORK_ORDER_NO);
            case 2:
                return redisMesPcn.putHash(getDataKey(reqBean), CUR_WORK_ORDER_NO, curWorkOrderNo, MesPcnEnumUtil.EXPIRE_TIME.NEVER.getValue());
            case 3:
                redisMesPcn.deleteHash(getDataKey(reqBean), CUR_WORK_ORDER_NO);
                return true;
            default:
                return null;
        }
    }

    public synchronized Object doHandleSelectWorkOrderNo(StationRequestBean reqBean, Integer flag, String selectWorkOrderNo) {
        switch (flag) {
            case 1:
                return redisMesPcn.getHash(getDataKey(reqBean), CMD_WORK_ORDER);
            case 2:
                return redisMesPcn.putHash(getDataKey(reqBean), CMD_WORK_ORDER, selectWorkOrderNo, MesPcnEnumUtil.EXPIRE_TIME.NEVER.getValue());
            case 3:
                redisMesPcn.deleteHash(getDataKey(reqBean), CMD_WORK_ORDER);
                return true;
            default:
                return null;
        }
    }

    public Object doHandleSnColonRfidNo(StationRequestBean reqBean, Integer flag, String snColonRfidNo) {
        switch (flag) {
            case 1:
                return redisMesPcn.getHash(getDataKey(reqBean), SN_COLON_RFID_NO);
            case 2:
                return redisMesPcn.putHash(getDataKey(reqBean), SN_COLON_RFID_NO, snColonRfidNo, MesPcnEnumUtil.EXPIRE_TIME.NEVER.getValue());
            case 3:
                redisMesPcn.deleteHash(getDataKey(reqBean), SN_COLON_RFID_NO);
                return true;
            default:
                return null;
        }
    }



}
