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

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.api.busi.IProduceSnTravelExtService;
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.MesProduceSnTravelExt;
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.ProduceSnExtModel;
import cn.estsh.i3plus.ext.mes.pcn.pojo.repository.MesWorkOrderExtRepository;
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.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.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.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 : 展示组件：净水器线-本体包装
 * @Reference :
 * @Author :wangjie
 * @CreateDate : 2020-06-26 11:18 上午
 * @Modify:
 **/
@Slf4j
@Service("sxOuterNoumenonPackageModuleService")
public class SxOuterNoumenonPackageModuleService extends BaseModuleService {

    @Autowired
    private ISxWorkOrderExtService workOrderExtService;

    @Autowired
    private IWorkCenterExtService workCenterExtService;

    @Autowired
    private IShiftExtService shiftExtService;

    @Autowired
    private IProduceSnExtService produceSnExtService;

    @Autowired
    private IProduceSnRepairDao produceSnRepairDao;

    @Autowired
    private IShiftProdCenterRecordService shiftProdCenterRecordService;

    @Autowired
    private MesWorkOrderExtRepository workOrderExtRepository;

    @Autowired
    private IProduceSnTravelExtService produceSnTravelExtService;

    @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_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,  resultBean, 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()) {
            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();
        }
        //MesWorkOrderExt workOrderExt = null;
        List<MesWorkOrderExt> workOrderExtList = getWorkOrderExtList(reqBean);

        List<MesProduceSnTravelExt> produceSnTravelExtList = null;
        if (!StringUtils.isEmpty(reqBean.getWorkOrderNo())) {
            if (!CollectionUtils.isEmpty(workOrderExtList)) {
                workOrderExt = new MesWorkOrderExt();
                BeanUtils.copyProperties(workOrderExtList.get(0), workOrderExt);
                if(workOrderExt.getWorkOrderType() == MesPcnExtEnumUtil.WORK_ORDER_TYPE.REWORK_ORDER.getValue()){
                    produceSnTravelExtList = produceSnTravelExtService.getProduceSnTravelExtListByLastOrderNo(
                            reqBean.getOrganizeCode(), reqBean.getWorkCenterCode(), reqBean.getWorkCellCode(), reqBean.getWorkOrderNo());
                }else{
                    produceSnTravelExtList = produceSnTravelExtService.getProduceSnTravelExtListByOrderNo(
                            reqBean.getOrganizeCode(), reqBean.getWorkCenterCode(), reqBean.getWorkCellCode(), reqBean.getWorkOrderNo());
                }

            }
        } else {
            if (!CollectionUtils.isEmpty(workOrderExtList)) {
                for (MesWorkOrderExt workOrder : workOrderExtList) {
                    if (null == workOrder) {
                        continue;
                    }
                    produceSnTravelExtList = produceSnTravelExtService.getProduceSnTravelExtListByOrderNo(
                            reqBean.getOrganizeCode(), reqBean.getWorkCenterCode(), reqBean.getWorkCellCode(), workOrder.getOrderNo());
                    if (CollectionUtils.isEmpty(produceSnTravelExtList) || produceSnTravelExtList.size() != workOrder.getQty().intValue()) {
                        workOrderExt = new MesWorkOrderExt();
                        BeanUtils.copyProperties(workOrder, workOrderExt);
                        break;
                    }
                }
            }
        }

        reqBean.setWorkOrderNo(workOrderExt.getOrderNo());
        resultBean.setResultMap(packResultMap(workOrderExt));
        resultBean.setResultList(packResultList(reqBean, workOrderExt,produceSnTravelExtList));
        this.sendMessage(reqBean, resultBean);
    }

    private List<ProduceSnExtModel> packResultList(StationRequestBean reqBean, MesWorkOrderExt workOrderExt,List<MesProduceSnTravelExt> produceSnTravelExtList ) {
        List<ProduceSnExtModel> modelList = null;
        Map<String, List<MesProduceSnTravelExt>> snTravelExtMap = CollectionUtils.isEmpty(produceSnTravelExtList) ? null :
                produceSnTravelExtList.stream().filter(o -> null != o).collect(Collectors.groupingBy(MesProduceSnTravelExt::getSerialNumber));

        List<MesProduceSnExt> produceSnExtList = produceSnExtService.getProduceSnExtListByOrderNo(reqBean.getOrganizeCode(), workOrderExt.getOrderNo());
        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.setCreateDatetime();
//                model.setStatus((!CollectionUtils.isEmpty(snTravelExtMap) && snTravelExtMap.containsKey(serialNumber))
//                        ? LocaleUtil.transferLanguage(userInfo, "已扫描") : null);
                model.setCreateDatetime((!CollectionUtils.isEmpty(snTravelExtMap) && snTravelExtMap.containsKey(produceSnExt.getSerialNumber()))
                        ? snTravelExtMap.get(produceSnExt.getSerialNumber()).get(0).getCreateDatetime() : null);
                model.setSnStatusName(MesPcnExtEnumUtil.PRODUCE_SN_STATUS.valueOfDescription(produceSnExt.getSnStatus()));
                modelList.add(model);
            }
        } else {
            if (MesPcnExtEnumUtil.WORK_ORDER_TYPE.REWORK_ORDER.getValue() == workOrderExt.getWorkOrderType()) {
                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.setCreateDatetime((!CollectionUtils.isEmpty(snTravelExtMap) && snTravelExtMap.containsKey(model.getSerialNumber()))
                                ? snTravelExtMap.get(model.getSerialNumber()).get(0).getCreateDatetime() : null);
                        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.getCreateDatetime()))).collect(Collectors.toList());
            List<ProduceSnExtModel> resultList2 = modelList.stream().filter(o -> (null != o && StringUtils.isEmpty(o.getCreateDatetime()))).collect(Collectors.toList());
            resultList1 = CollectionUtils.isEmpty(resultList1) ? null :
                    resultList1.stream().sorted(Comparator.comparing(ProduceSnExtModel::getCreateDatetime).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) {
        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());
        resultMap.put(MesPcnExtConstWords.COMPLETE_QTY, workOrderExt.getCompleteQty());
        resultMap.put(MesPcnExtConstWords.MISSING_QTY, workOrderExt.getMissingQty());
        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.OUT_WC_TIME, LocaleUtil.transferLanguage(reqBean.getUserInfo(), "下线时间"));
        PojoAttrUtil.loadPojoAttrs(attrBeanList, MesPcnExtConstWords.CREATE_DATE_TIME, LocaleUtil.transferLanguage(reqBean.getUserInfo(), "扫描时间"));

        return attrBeanList;
    }

    private List<MesWorkOrderExt> getWorkOrderExtList(StationRequestBean reqBean) {
        DdlPackBean packBean = DdlPackBean.getDdlPackBean(reqBean.getOrganizeCode());
        DdlPreparedPack.getStringEqualPack(reqBean.getWorkCenterCode(), MesPcnExtConstWords.WORK_CENTER_CODE, packBean);
        DdlPreparedPack.getStringEqualPack(reqBean.getAreaCode(), MesPcnExtConstWords.AREA_CODE, packBean);
        DdlPreparedPack.getNumEqualPack(MesPcnExtEnumUtil.WORK_ORDER_STATUS.OPEN.getValue(), MesPcnExtConstWords.WORK_ORDER_STATUS, packBean);
        DdlPreparedPack.getStringEqualPack(reqBean.getWorkOrderNo(), MesPcnExtConstWords.ORDER_NO, packBean);
        DdlPreparedPack.getOrderByPack(new Object[]{CommonEnumUtil.ASC_OR_DESC.ASC.getValue()}, new String[]{MesPcnExtConstWords.SEQ}, packBean);
        return workOrderExtRepository.findByHqlWhere(packBean);
    }

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

    public void putLastSelectOrder(StationRequestBean reqBean) {
        redisMesPcn.putObject(getLastSelectOrderKey(reqBean), reqBean.getWorkOrderNo(), MesPcnEnumUtil.EXPIRE_TIME.NEVER.getValue());
    }

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

}
