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

import cn.estsh.i3plus.ext.mes.pcn.api.busi.IProduceSnExtService;
import cn.estsh.i3plus.ext.mes.pcn.api.busi.IProduceSnRepairService;
import cn.estsh.i3plus.ext.mes.pcn.api.busi.IProduceSnTravelExtService;
import cn.estsh.i3plus.ext.mes.pcn.pojo.bean.MesProduceSnExt;
import cn.estsh.i3plus.ext.mes.pcn.pojo.bean.MesProduceSnRepair;
import cn.estsh.i3plus.ext.mes.pcn.pojo.bean.MesProduceSnTravelExt;
import cn.estsh.i3plus.ext.mes.pcn.pojo.bean.MesWorkOrderExt;
import cn.estsh.i3plus.ext.mes.pcn.pojo.model.BindKeyPartModuleModel;
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.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("sxBindKeyPartModuleService")
public class SxBindKeyPartModuleService extends BaseModuleService {

    @Autowired
    private MesWorkOrderExtRepository workOrderExtRepository;

    @Autowired
    private IProduceSnExtService produceSnExtService;

    @Autowired
    private IProduceSnRepairService produceSnRepairService;

    @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) {
        this.sendMessage(reqBean, null, "", MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.TEXT);
        doInit(reqBean);
    }

    private void doInit(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.BIND_KEY_PART_MODULE);
        resultBean.setDataAttrList(packDataAttrList(reqBean));
        resultBean.setSpecialDisplayData(getStepColIndent(reqBean));

        doPackLastSelectOrder(reqBean);
        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;
                    }
                }
            }
        }

        if (null == workOrderExt) {
            if (!StringUtils.isEmpty(reqBean.getWorkOrderNo())) {
                Map<String, Object> resultMap = new HashMap<>();
                resultMap.put(MesPcnExtConstWords.WORK_ORDER_NO, reqBean.getWorkOrderNo());
                resultBean.setResultMap(resultMap);
                this.sendMessage(reqBean, resultBean);

                if (MesPcnEnumUtil.ACTOR_RECEIVE_STRATEGY.WS_CMD_INIT_MODULE.getCode().equals(reqBean.getBusiType())) {
                    err = String.format(LocaleUtil.transferLanguage(reqBean.getUserInfo(), "工单[%s]不能在工位[%s]操作"), reqBean.getWorkOrderNo(), reqBean.getWorkCellCode());
                    this.sendMessage(reqBean, resultBean, err, MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, 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.getWorkOrderNo(), reqBean.getWorkCellCode())
                            .build();
                }

            } else {
                if (!CollectionUtils.isEmpty(resultBean.getResultMap())) {
                    resultBean.getResultMap().remove(MesPcnExtConstWords.WORK_ORDER_NO);
                }
                this.sendMessage(reqBean, resultBean);
                err = String.format(LocaleUtil.transferLanguage(reqBean.getUserInfo(), "生产线[%s]暂无启动工单"), reqBean.getWorkCenterCode());
                this.sendMessage(reqBean, resultBean, err, MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.TEXT);
                throw ImppExceptionBuilder.newInstance()
                        .setSystemID(CommonEnumUtil.SOFT_TYPE.MES_PCN.getCode())
                        .setErrorCode(ImppExceptionEnum.BUSINESS_EXCEPTION.getCode())
                        .setErrorDetail("生产线[%s]暂无启动工单", reqBean.getWorkCenterCode())
                        .build();
            }
        }

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

    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());
        return resultMap;
    }

    private List<BindKeyPartModuleModel> getResultList(StationRequestBean reqBean, Integer workOrderType, List<MesProduceSnTravelExt> produceSnTravelExtList) {
        List<BindKeyPartModuleModel> modelList = new ArrayList<>();
        Map<String, List<MesProduceSnTravelExt>> snTravelExtMap = CollectionUtils.isEmpty(produceSnTravelExtList) ? null :
                produceSnTravelExtList.stream().filter(o -> null != o).collect(Collectors.groupingBy(MesProduceSnTravelExt::getSerialNumber));
        if (MesPcnExtEnumUtil.WORK_ORDER_TYPE.REWORK_ORDER.getValue() != workOrderType) {
            List<MesProduceSnExt> produceSnExtList = produceSnExtService.getProduceSnExtListByOrderNo(reqBean.getOrganizeCode(), reqBean.getWorkOrderNo());
            if (!CollectionUtils.isEmpty(produceSnExtList)) {
                for (MesProduceSnExt produceSnExt : produceSnExtList) {
                    if (null == produceSnExt) {
                        continue;
                    }
                    packModelList(modelList, produceSnExt.getSerialNumber(), snTravelExtMap, reqBean.getUserInfo());
                }
            } 
        } else {
            List<MesProduceSnRepair> produceSnRepairList = produceSnRepairService.getProduceSnRepairListByOrderNo(reqBean.getOrganizeCode(), reqBean.getWorkOrderNo());
            if (!CollectionUtils.isEmpty(produceSnRepairList)) {
                for (MesProduceSnRepair produceSnRepair : produceSnRepairList) {
                    if (null == produceSnRepair) {
                        continue;
                    }
                    packModelList(modelList, produceSnRepair.getSerialNumber(), snTravelExtMap, reqBean.getUserInfo());
                }
            }
        }
        
        if (!CollectionUtils.isEmpty(modelList)) {
            List<BindKeyPartModuleModel> list1 = modelList.stream().filter(o -> (null != o && !StringUtils.isEmpty(o.getCreateDatetime()))).collect(Collectors.toList());
            if (!CollectionUtils.isEmpty(list1)) {
                list1 = list1.stream().sorted(Comparator.comparing(BindKeyPartModuleModel::getCreateDatetime).reversed()).collect(Collectors.toList());
            }
            List<BindKeyPartModuleModel> list2 = modelList.stream().filter(o -> (null != o && StringUtils.isEmpty(o.getCreateDatetime()))).collect(Collectors.toList());
            if (!CollectionUtils.isEmpty(list2)) {
                list2 = list2.stream().sorted(Comparator.comparing(BindKeyPartModuleModel::getSerialNumber)).collect(Collectors.toList());
            }
            modelList = new ArrayList<>();
            modelList.addAll(list1);
            modelList.addAll(list2);
        }

        return modelList;
    }

    private void packModelList(List<BindKeyPartModuleModel> modelList, String serialNumber, Map<String, List<MesProduceSnTravelExt>> snTravelExtMap, String userInfo) {
        BindKeyPartModuleModel model = new BindKeyPartModuleModel();
        model.setSerialNumber(serialNumber);
        model.setStatus((!CollectionUtils.isEmpty(snTravelExtMap) && snTravelExtMap.containsKey(serialNumber))
                ? LocaleUtil.transferLanguage(userInfo, "已扫描") : null);
        model.setCreateDatetime((!CollectionUtils.isEmpty(snTravelExtMap) && snTravelExtMap.containsKey(serialNumber))
                ? snTravelExtMap.get(serialNumber).get(0).getCreateDatetime() : null);
        modelList.add(model);
    }

    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.STATUS, 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 void doPackLastSelectOrder(StationRequestBean reqBean) {
        if (StringUtils.isEmpty(reqBean.getWorkOrderNo())) {
            String workOrderNo = getLastSelectOrder(reqBean);
            if (!StringUtils.isEmpty(workOrderNo)) {
                reqBean.setWorkOrderNo(workOrderNo);
                deleteLastSelectOrder(reqBean);
            }
        }
    }

    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) {
        doInit(reqBean);
        return true;
    }

}
