package cn.estsh.i3plus.ext.mes.pcn.apiservice.serviceimpl.equiplog;

import cn.estsh.i3plus.ext.mes.pcn.api.busi.IMesEquipmentLogExtService;
import cn.estsh.i3plus.ext.mes.pcn.apiservice.dao.IMesEquipmentLogDao;
import cn.estsh.i3plus.ext.mes.pcn.pojo.context.MesCellEquipContext;
import cn.estsh.i3plus.ext.mes.pcn.pojo.context.MesEquipLogDispatchContext;
import cn.estsh.i3plus.ext.mes.pcn.pojo.context.MesEquipVariableCfgCollectContext;
import cn.estsh.i3plus.ext.mes.pcn.pojo.context.MesEquipVariableCollectContext;
import cn.estsh.i3plus.pojo.mes.bean.MesEquipmentRecord;
import cn.estsh.i3plus.pojo.mes.bean.MesEquipmentVariable;
import cn.estsh.i3plus.pojo.mes.bean.MesEquipmentVariableCfg;
import cn.estsh.i3plus.pojo.mes.util.MesExtEnumUtil;
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.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

@Slf4j
@Service
public class MesEquipmentLogExtService implements IMesEquipmentLogExtService {

    @Autowired
    private IMesEquipmentLogDao equipmentLogDao;

    @Override
    public void updateEquipmentLogList(String organizeCode, Integer equipId, Map<Long, String> equipmentLogIdMap) {
        if (StringUtils.isEmpty(organizeCode) || StringUtils.isEmpty(equipId) || CollectionUtils.isEmpty(equipmentLogIdMap)) return;
        equipmentLogDao.updateEquipVariableStatus(organizeCode, equipId, equipmentLogIdMap, MesExtEnumUtil.EQUIP_VARIABLE_NEED_NEW_VALUE.FALSE.getEquipVariableStatus());
    }

    @Override
    public Boolean checkEquipQuality(Integer quality) {
        return MesExtEnumUtil.EQUIP_LOG_QUALITY.checkQuality(quality);
    }

    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public MesEquipLogDispatchContext getEquipLogDispatchContext(MesCellEquipContext cellEquipContext, List<MesEquipmentVariable> equipmentVariableList, List<MesEquipmentVariableCfg> equipmentVariableCfgList) {

        MesEquipLogDispatchContext equipLogDispatchContext = new MesEquipLogDispatchContext(cellEquipContext.getOrganizeCode());

        if (CollectionUtils.isEmpty(equipmentVariableList) || CollectionUtils.isEmpty(equipmentVariableCfgList)) return equipLogDispatchContext;

        List<MesEquipVariableCollectContext> equipVariableCollectContextList = equipmentLogDao.queryMesEquipmentLog(equipmentVariableList, cellEquipContext.getOrganizeCode(), cellEquipContext.getEquipId(), MesExtEnumUtil.EQUIP_VARIABLE_TYPE.PRODUCTION.getValue());

        // 标记当前设备通信是否正常
        Optional<MesEquipVariableCollectContext> optional = CollectionUtils.isEmpty(equipVariableCollectContextList) ? null : equipVariableCollectContextList.stream().filter(o -> (null != o && !StringUtils.isEmpty(o.getQuality()) && !checkEquipQuality(o.getQuality()))).findFirst();
        cellEquipContext.setQuality((null != optional && optional.isPresent()) ? optional.get().getQuality() : MesExtEnumUtil.EQUIP_LOG_QUALITY.defaultQuality());

        // 封装数据变量接口逻辑、数据变量、设备LOG信息的嵌套对象集合
        List<MesEquipVariableCfgCollectContext> collectContextList = generateEquipVariableCfgCollectLogContextList(equipLogDispatchContext, cellEquipContext, equipVariableCollectContextList, equipmentVariableCfgList);

        return equipLogDispatchContext.equipVariableCfgCollectContextList(collectContextList);

    }

    private List<MesEquipVariableCfgCollectContext> generateEquipVariableCfgCollectLogContextList(MesEquipLogDispatchContext equipLogDispatchContext, MesCellEquipContext cellEquipContext,
                                                                                                  List<MesEquipVariableCollectContext> equipVariableCollectContextList, List<MesEquipmentVariableCfg> equipmentVariableCfgList) {

        List<MesEquipVariableCfgCollectContext> equipVariableCfgCollectContextList = null;

        Map<String, List<MesEquipVariableCollectContext>> categoryLevelTwoMap = equipVariableCollectContextList.stream().filter(o -> null != o).collect(Collectors.groupingBy(MesEquipVariableCollectContext::getCategoryLevelTwo));

        for (MesEquipmentVariableCfg equipmentVariableCfg : equipmentVariableCfgList) {

            if (null == equipmentVariableCfg) continue;

            MesEquipVariableCfgCollectContext equipVariableCfgCollectContext = new MesEquipVariableCfgCollectContext();
            BeanUtils.copyProperties(equipmentVariableCfg, equipVariableCfgCollectContext);

            if (StringUtils.isEmpty(equipmentVariableCfg.getNeedNewValue())) equipVariableCfgCollectContext.setNeedNewValue(MesExtEnumUtil.EQUIP_VARIABLE_NEED_NEW_VALUE.FALSE.getValue());
            if (MesExtEnumUtil.EQUIP_VARIABLE_NEED_NEW_VALUE.TRUE.getValue() == equipVariableCfgCollectContext.getNeedNewValue()) equipLogDispatchContext.needNewValue();

            // 内部方法: 根据常变值重写查询出来的设备变量值,赋值设备变量ID集合
            equipVariableCfgCollectContext.equipVariableCollectContextList(categoryLevelTwoMap.get(equipmentVariableCfg.getCategoryLevelTwo()));

            // 已经采集到任何数据情况下isCollectValue标记为true
            if (equipLogDispatchContext.getIsCollectValue() || equipVariableCfgCollectContext.getIsCollectValue()) equipLogDispatchContext.isCollectValue();

            if (CollectionUtils.isEmpty(equipVariableCfgCollectContextList)) equipVariableCfgCollectContextList = new ArrayList<>();

            equipVariableCfgCollectContextList.add(equipVariableCfgCollectContext);

            // 标记需要修改的设备数据变量ID 【在主方法体中修改常变值配置对应的设备ID分表的采集数据的状态为1】
            if (equipVariableCfgCollectContext.getIsCollectValue() && checkEquipQuality(cellEquipContext.getQuality()) && !StringUtils.isEmpty(equipmentVariableCfg.getNeedNewValue()) &&
                    equipmentVariableCfg.getNeedNewValue().compareTo(MesExtEnumUtil.EQUIP_VARIABLE_NEED_NEW_VALUE.TRUE.getValue()) == 0) equipLogDispatchContext.resetEquipmentLogIdMap(equipVariableCfgCollectContext.getEquipmentLogIdMap());
        }

        return equipVariableCfgCollectContextList;

    }

    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public List<MesEquipVariableCollectContext> getEquipmentLogCollectList(String organizeCode, Integer equipId, Integer needNewValue, Integer variableType) {
        if (StringUtils.isEmpty(organizeCode) || StringUtils.isEmpty(equipId) || StringUtils.isEmpty(variableType)) return null;
        List<MesEquipVariableCollectContext> equipVariableCollectContextList = equipmentLogDao.queryMesEquipmentLog(organizeCode, equipId, variableType);
        return filterEquipVariableCollectContextList(equipVariableCollectContextList, needNewValue);
    }

    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public List<MesEquipVariableCollectContext> getEquipmentLogCollectList(String organizeCode, Integer equipId, Integer needNewValue, Integer variableType, List<Long> equipVariableIdList) {
        if (StringUtils.isEmpty(organizeCode) || StringUtils.isEmpty(equipId) || CollectionUtils.isEmpty(equipVariableIdList) || StringUtils.isEmpty(variableType)) return null;
        List<MesEquipVariableCollectContext> equipVariableCollectContextList = equipmentLogDao.queryMesEquipmentLog(organizeCode, equipId, variableType, equipVariableIdList);
        return filterEquipVariableCollectContextList(equipVariableCollectContextList, needNewValue);
    }

    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public List<MesEquipVariableCollectContext> getEquipmentLogCollectListThenFilter(String organizeCode, Integer equipId, Integer needNewValue, Integer variableType, List<Long> equipVariableIdList) {
        if (StringUtils.isEmpty(organizeCode) || StringUtils.isEmpty(equipId) || CollectionUtils.isEmpty(equipVariableIdList) || StringUtils.isEmpty(variableType)) return null;
        List<MesEquipVariableCollectContext> equipVariableCollectContextList = equipmentLogDao.queryMesEquipmentLog(organizeCode, equipId, variableType);
        equipVariableCollectContextList = CollectionUtils.isEmpty(equipVariableCollectContextList) ? null :
                equipVariableCollectContextList.stream().filter(o -> (null != o && !StringUtils.isEmpty(o.getEquipVariableId()) && equipVariableIdList.contains(o.getEquipVariableId()))).collect(Collectors.toList());
        return filterEquipVariableCollectContextList(equipVariableCollectContextList, needNewValue);
    }

    private List<MesEquipVariableCollectContext> filterEquipVariableCollectContextList(List<MesEquipVariableCollectContext> equipVariableCollectContextList, Integer needNewValue) {

        if (CollectionUtils.isEmpty(equipVariableCollectContextList)) return equipVariableCollectContextList;

        equipVariableCollectContextList = equipVariableCollectContextList.stream().filter(o -> (null != o && matchQualityAndNeedNewValue(o, needNewValue))).collect(Collectors.toList());

        return equipVariableCollectContextList;

    }

    private Boolean matchQualityAndNeedNewValue(MesEquipVariableCollectContext equipVariableCollectContext, Integer needNewValue) {

        if (StringUtils.isEmpty(equipVariableCollectContext.getEquipVariableValue())) return false;

        if (!checkEquipQuality(equipVariableCollectContext.getQuality())) return false;

        if (StringUtils.isEmpty(needNewValue) || needNewValue.compareTo(MesExtEnumUtil.EQUIP_VARIABLE_NEED_NEW_VALUE.FALSE.getValue()) == 0) return true;

        if (!StringUtils.isEmpty(equipVariableCollectContext.getEquipVariableStatus()) && equipVariableCollectContext.getEquipVariableStatus().compareTo(MesExtEnumUtil.EQUIP_VARIABLE_NEED_NEW_VALUE.TRUE.getEquipVariableStatus()) == 0) return true;

        return false;

    }

    @Override
    public void insertBatchEquipmentLogDetail(String organizeCode, Integer equipId, String userInfo, MesEquipmentRecord mesEquipmentRecord, List<MesEquipVariableCollectContext> equipmentLogList) {
        equipmentLogDao.insertBatchEquipmentLogDetail(organizeCode, equipId, userInfo, mesEquipmentRecord, equipmentLogList);
    }

}
