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

import cn.estsh.i3plus.ext.mes.pcn.api.base.IShiftExtService;
import cn.estsh.i3plus.ext.mes.pcn.api.base.IShiftProdCenterRecordService;
import cn.estsh.i3plus.ext.mes.pcn.api.base.ISxWorkOrderExtService;
import cn.estsh.i3plus.ext.mes.pcn.api.base.IWorkCenterExtService;
import cn.estsh.i3plus.ext.mes.pcn.api.busi.IProduceSnExtService;
import cn.estsh.i3plus.ext.mes.pcn.apiservice.dao.IPackageExtDao;
import cn.estsh.i3plus.ext.mes.pcn.pojo.bean.MesProduceSnExt;
import cn.estsh.i3plus.ext.mes.pcn.pojo.bean.MesWorkCenterExt;
import cn.estsh.i3plus.ext.mes.pcn.pojo.bean.MesWorkOrderExt;
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.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.pojo.base.enumutil.CommonEnumUtil;
import cn.estsh.i3plus.pojo.base.enumutil.MesPcnEnumUtil;
import cn.estsh.i3plus.pojo.mes.bean.MesShift;
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.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 : 展示组件：本体包装前置组件(生成包装条码)
 * @Reference :
 * @Author :wangjie
 * @CreateDate : 2020-06-26 11:18 上午
 * @Modify:
 **/
@Slf4j
@Service("sxNoumenonPackagePreModuleService")
public class SxNoumenonPackagePreModuleService extends BaseModuleService {

    @Autowired
    private ISxWorkOrderExtService workOrderExtService;

    @Autowired
    private IWorkCenterExtService workCenterExtService;

    @Autowired
    private IShiftExtService shiftExtService;

    @Autowired
    private IProduceSnExtService produceSnExtService;

    @Autowired
    private IPackageExtDao packageExtDao;

    @Autowired
    private IShiftProdCenterRecordService shiftProdCenterRecordService;

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

    private static final String LAST_SELECT_ORDER = "LAST_SELECT_ORDER";

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

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

        MesWorkCenterExt workCenterExt = workCenterExtService.getWorkCenterExtByWorkCenterCode(reqBean.getOrganizeCode(), reqBean.getWorkCenterCode());
        if (null == workCenterExt || (StringUtils.isEmpty(workCenterExt.getShiftCode()) || StringUtils.isEmpty(workCenterExt.getWorkTime()))) {
            this.sendMessage(reqBean, resultBean);
            err = String.format(LocaleUtil.transferLanguage(reqBean.getUserInfo(), "生产线[%s]未启动班次"), reqBean.getWorkCenterCode());
            this.sendMessage(reqBean,  resultBean, err, MesPcnEnumUtil.STATION_BUSI_TYPE.GUIDE, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT);
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
                    .setErrorDetail("生产线[%s]未启动班次", reqBean.getWorkCenterCode())
                    .build();
        }
        MesShift shiftDb = shiftExtService.getShiftByShiftCodeAndCenterCode(reqBean.getOrganizeCode(), reqBean.getWorkCenterCode(), workCenterExt.getShiftCode());
        if (null == shiftDb) {
            this.sendMessage(reqBean, resultBean);
            err = String.format(LocaleUtil.transferLanguage(reqBean.getUserInfo(), "生产线[%s]未关联班次代码[%s]"), reqBean.getWorkCenterCode(), workCenterExt.getShiftCode());
            this.sendMessage(reqBean,  resultBean, err, MesPcnEnumUtil.STATION_BUSI_TYPE.GUIDE, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT);
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.BUSINESS_EXCEPTION.getCode())
                    .setErrorDetail("生产线[%s]未关联班次代码[%s]", reqBean.getWorkCenterCode(), workCenterExt.getShiftCode())
                    .build();
        }
        String workTime = shiftProdCenterRecordService.getWorkTime(shiftDb.getStartTime(), shiftDb.getEndTime());
        if (StringUtils.isEmpty(workTime) || !workTime.equals(workCenterExt.getWorkTime())) {
            this.sendMessage(reqBean, resultBean);
            err = String.format(LocaleUtil.transferLanguage(reqBean.getUserInfo(), "生产线[%s]需要重新启动班次"), reqBean.getWorkCenterCode());
            this.sendMessage(reqBean,  resultBean, err, MesPcnEnumUtil.STATION_BUSI_TYPE.GUIDE, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT);
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.BUSINESS_EXCEPTION.getCode())
                    .setErrorDetail("生产线[%s]需要重新启动班次", reqBean.getWorkCenterCode())
                    .build();
        }

        Boolean result = doPackLastSelectOrder(reqBean);
        if (StringUtils.isEmpty(reqBean.getWorkOrderNo())) {
            this.sendMessage(reqBean, resultBean);
            err = LocaleUtil.transferLanguage(reqBean.getUserInfo(), "请选择工单");
            this.sendMessage(reqBean,  null, err, MesPcnEnumUtil.STATION_BUSI_TYPE.GUIDE, MesPcnEnumUtil.STATION_DATA_TYPE.TEXT);
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.BUSINESS_EXCEPTION.getCode())
                    .setErrorDetail("请选择工单")
                    .build();
        }
        MesWorkOrderExt workOrderExt = workOrderExtService.getWorkOrderExtByOrderNo(reqBean.getOrganizeCode(), reqBean.getWorkOrderNo());
        if (null == workOrderExt || MesPcnExtEnumUtil.WORK_ORDER_STATUS.OPEN.getValue() != workOrderExt.getWorkOrderStatus() ||
                MesPcnExtEnumUtil.WORK_ORDER_TYPE.REWORK_ORDER.getValue() == workOrderExt.getWorkOrderType()) {
            if (result) {
                Map<String, Object> resultMap = new HashMap<>();
                resultMap.put(MesPcnExtConstWords.WORK_ORDER_NO, reqBean.getWorkOrderNo());
                resultBean.setResultMap(resultMap);
                err = String.format(LocaleUtil.transferLanguage(reqBean.getUserInfo(), "工单[%s]不能在此工位操作"), reqBean.getWorkOrderNo());
                this.sendMessage(reqBean,  resultBean, err, MesPcnEnumUtil.STATION_BUSI_TYPE.GUIDE, MesPcnEnumUtil.STATION_DATA_TYPE.TEXT);
            }
            this.sendMessage(reqBean, resultBean);
            throw ImppExceptionBuilder.newInstance()
                    .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                    .setErrorCode(ImppExceptionEnum.BUSINESS_EXCEPTION.getCode())
                    .setErrorDetail("工单[%s]不能在此工位操作", reqBean.getWorkOrderNo())
                    .build();
        }

        reqBean.setWorkOrderNo(workOrderExt.getOrderNo());
        resultBean.setResultList(packResultList(reqBean, workOrderExt));
        resultBean.setResultMap(packResultMap(workOrderExt, resultBean.getResultList()));

        this.sendMessage(reqBean, resultBean);
    }

    private List<SnAndPackageNoCorrelationModel> packResultList(StationRequestBean reqBean, MesWorkOrderExt workOrderExt) {
        List<MesProduceSnExt> produceSnExtList = produceSnExtService.getProduceSnExtListByOrderNo(reqBean.getOrganizeCode(), workOrderExt.getOrderNo());
        List<SnAndPackageNoCorrelationModel> modelList = packageExtDao.getSnAndPackCorrelationListByOrderNo(reqBean.getOrganizeCode(), workOrderExt.getOrderNo());
        List<String> snlist = CollectionUtils.isEmpty(modelList) ? new ArrayList<>() :
                modelList.stream().filter(o -> null != o).map(SnAndPackageNoCorrelationModel::getSerialNumber).collect(Collectors.toList());
        List<MesProduceSnExt> unScanList = CollectionUtils.isEmpty(produceSnExtList) ? null :
                produceSnExtList.stream().filter(o -> (null != o && !snlist.contains(o.getSerialNumber()))).collect(Collectors.toList());
        unScanList = CollectionUtils.isEmpty(unScanList) ? null :
                unScanList.stream().sorted(Comparator.comparing(MesProduceSnExt::getSerialNumber)).collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(unScanList)) {
            for (MesProduceSnExt produceSnExt : unScanList) {
                if (null == produceSnExt) {
                    continue;
                }
                SnAndPackageNoCorrelationModel model = new SnAndPackageNoCorrelationModel();
                model.setSerialNumber(produceSnExt.getSerialNumber());
                model.setWorkOrderNo(produceSnExt.getWorkOrderNo());
                if (CollectionUtils.isEmpty(modelList)) {
                    modelList = new ArrayList<>();
                }
                modelList.add(model);
            }
        }

        return modelList;
    }

    private Map<String, Object> packResultMap(MesWorkOrderExt workOrderExt, List<SnAndPackageNoCorrelationModel> resultList) {
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put(MesPcnExtConstWords.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());
        List<String> packageNoList = CollectionUtils.isEmpty(resultList) ? null :
                resultList.stream().filter(o -> (null != o && !StringUtils.isEmpty(o.getPackageNo()))).map(SnAndPackageNoCorrelationModel::getPackageNo).collect(Collectors.toList());
        resultMap.put(MesPcnExtConstWords.COMPLETE_QTY, CollectionUtils.isEmpty(packageNoList) ? 0 : packageNoList.size());
        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.PACKAGENO, LocaleUtil.transferLanguage(reqBean.getUserInfo(), "包装条码"));
        PojoAttrUtil.loadPojoAttrs(attrBeanList, MesPcnExtConstWords.CREATE_DATE_TIME, LocaleUtil.transferLanguage(reqBean.getUserInfo(), "扫描时间"));
        return attrBeanList;
    }

    private Boolean doPackLastSelectOrder(StationRequestBean reqBean) {
        if (StringUtils.isEmpty(reqBean.getWorkOrderNo())) {
            String workOrderNo = getLastSelectOrder(reqBean);
            if (!StringUtils.isEmpty(workOrderNo)) {
                reqBean.setWorkOrderNo(workOrderNo);
                deleteLastSelectOrder(reqBean);
                return true;
            }
        }
        return false;
    }

    private String getLastSelectOrderKey(StationRequestBean reqBean) {
        return getCacheKey(reqBean, LAST_SELECT_ORDER);
    }

    private String getLastSelectOrder(StationRequestBean reqBean) {
        return (String) redisMesPcn.getObject(getLastSelectOrderKey(reqBean));
    }

    private void deleteLastSelectOrder(StationRequestBean reqBean) {
        redisMesPcn.deleteKey(getLastSelectOrderKey(reqBean));
    }

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

}
