package com.njcn.device.pq.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.njcn.common.config.GeneralInfo;
import com.njcn.common.pojo.exception.BusinessException;
import com.njcn.device.pq.api.AlarmClient;
import com.njcn.device.pq.api.GeneralDeviceInfoClient;
import com.njcn.device.biz.enums.DeviceResponseEnum;
import com.njcn.device.pq.enums.LineBaseEnum;
import com.njcn.device.pq.mapper.LineIntegrityDataMapper;
import com.njcn.device.pq.mapper.RStatIntegrityDMapper;
import com.njcn.device.pq.pojo.dto.GeneralDeviceDTO;
import com.njcn.device.pq.pojo.dto.PublicDTO;
import com.njcn.device.pq.pojo.param.DeviceInfoParam;
import com.njcn.device.pq.pojo.param.LineIntegrityDataParam;
import com.njcn.device.pq.pojo.param.OnlineRateParam;
import com.njcn.device.pq.pojo.po.LineDataIntegrity;
import com.njcn.device.pq.pojo.vo.AlarmStrategyVO;
import com.njcn.device.pq.pojo.vo.LineIntegrityDataVO;
import com.njcn.device.pq.pojo.vo.RStatIntegrityVO;
import com.njcn.device.pq.service.LineIntegrityDataService;
import com.njcn.device.pq.utils.DataStatisticsUtil;
import com.njcn.harmonic.pojo.vo.IntegrityIconVO;
import com.njcn.system.pojo.enums.StatisticsEnum;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.influxdb.dto.QueryResult;
import org.influxdb.impl.InfluxDBResultMapper;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.Collator;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 监测点数据完整性
 *
 * @author yzh
 * @date 2022/9/14
 */

@Slf4j
@Service
@RequiredArgsConstructor
public class LineIntegrityDataServiceImpl extends ServiceImpl<LineIntegrityDataMapper, LineIntegrityDataVO> implements LineIntegrityDataService {

    private final LineIntegrityDataMapper lineIntegrityDataMapper;

    private final AlarmClient alarmClient;

    private final GeneralDeviceService generalDeviceService;

    private final RStatIntegrityDMapper rStatIntegrityDMapper;

    private final GeneralInfo generalInfo;

    private final GeneralDeviceInfoClient generalDeviceInfoClient;

    /**
     * 监测点数据完整性
     *
     * @param lineIntegrityDataParam 实体参数
     */
    @Override
    public List<LineIntegrityDataVO> getIntegrityDataOfLine(LineIntegrityDataParam lineIntegrityDataParam) {

        // 获取所有数据
        List<GeneralDeviceDTO> generalDeviceDTOList = generalDeviceService.getDeviceInfo(lineIntegrityDataParam, Stream.of(0).collect(Collectors.toList()), Stream.of(1).collect(Collectors.toList()));

        // 判断所有数据集合状态
        if (CollectionUtil.isNotEmpty(generalDeviceDTOList)) {

            // 创建集合返回数据
            List<LineIntegrityDataVO> pro = new ArrayList<>();

            // 获取告警策略列表
            List<AlarmStrategyVO> alarmStrategyVos = alarmClient.getAlarmStrategyData().getData();
            // 判断告警策略数据状态
            if (CollectionUtil.isEmpty(alarmStrategyVos)) {
                throw new BusinessException(DeviceResponseEnum.QUERY_ALARMSTRATEGY_DATA_EMPTY);
            }
            List<AlarmStrategyVO> alarmAlgoDescribe = lineIntegrityDataMapper.getAlarmAlgoDescribe(alarmStrategyVos);
            Map<Integer, Integer> mapAlarm = alarmAlgoDescribe.stream().collect(Collectors.toMap(AlarmStrategyVO::getAlgoDescribe, AlarmStrategyVO::getIntegrityValue));

            Map<String, Integer> mapA = alarmStrategyVos.stream().collect(Collectors.toMap(AlarmStrategyVO::getId, AlarmStrategyVO::getIntegrityValue));


            // 遍历集合
            for (GeneralDeviceDTO generalDeviceDTO : generalDeviceDTOList) {

                // 判断监测点索引集合状态
                if (CollectionUtils.isEmpty(generalDeviceDTO.getLineIndexes())) {
                    continue;
                }

                // 创建实体类
                LineIntegrityDataVO lineIntegrityDataVO = new LineIntegrityDataVO();

                // 通过监测点索引查询监测点信息
                List<LineIntegrityDataVO> lineList = lineIntegrityDataMapper.getDetailedParametersForLine(generalDeviceDTO.getLineIndexes(), lineIntegrityDataParam.getLineGrade());
                List<String> lineIds = lineList.stream().map(LineIntegrityDataVO::getId).distinct().collect(Collectors.toList());

                // 通过供电站索引查询供电站信息
                List<LineIntegrityDataVO> subList = lineIntegrityDataMapper.getSubList(lineIds);
                List<String> gdIds = subList.stream().map(LineIntegrityDataVO::getPid).distinct().collect(Collectors.toList());

                // 通过供电公司索引查询供电公司信息
                List<LineIntegrityDataVO> gdList = lineIntegrityDataMapper.getGdList(gdIds);

                // 通过供电公司索引查询省会
                List<LineIntegrityDataVO> proList = lineIntegrityDataMapper.getProvinceList(gdIds);

                // 查询监测点数据完整性
                List<LineDataIntegrity> percentageOfCompleteDatas = rStatIntegrityDMapper.getLineIntegrityRate(generalDeviceDTO.getLineIndexes(),lineIntegrityDataParam.getSearchBeginTime(), lineIntegrityDataParam.getSearchEndTime());

                for (LineIntegrityDataVO lineDataIntegrity : lineList) {
                    boolean flag = false;
                    for (LineDataIntegrity lineData : percentageOfCompleteDatas) {
                        if (lineDataIntegrity.getId().equals(lineData.getLineId())) {
                            flag = true;
                            Double temValue = lineData.getIntegrityData();
                            lineDataIntegrity.setIntegrityData(DataStatisticsUtil.dataLimits(temValue));
                            //根据等级判断是否越限
                            if (StrUtil.isNotBlank(lineDataIntegrity.getLineGrade())) {
                                if (mapA.containsKey(lineDataIntegrity.getLineGrade())) {
                                    if (temValue > mapA.get(lineDataIntegrity.getLineGrade())) {
                                        lineDataIntegrity.setValueOver(1);
                                    } else {
                                        lineDataIntegrity.setValueOver(0);
                                    }
                                } else {
                                    throw new BusinessException(DeviceResponseEnum.LINE_GRADE_LESS);
                                }
                            } else {
                                //默认没有设置等级的监测点标志为1  0.不合格 1.合格
                                lineDataIntegrity.setValueOver(1);
                            }
                            break;
                        }
                    }
                    if (!flag) {
                        //表示未匹配到数据完整性
                        lineDataIntegrity.setIntegrityData(3.14159);
                        lineDataIntegrity.setValueOver(0);
                    }
                }

                //处理变电站
                dealChildrenData(subList, lineList, true);
                //处理供电公司
                dealChildrenData(gdList, subList, false);

                //double areaDataIntegrity = DataStatisticsUtil.getAreaDataIntegrity(percentageOfCompleteDatas);

                if (lineIntegrityDataParam.getStatisticalType().getCode().equalsIgnoreCase(StatisticsEnum.POWER_NETWORK.getCode())) {
                    lineIntegrityDataVO.setChildren(gdList);
                } else {
                    //还需要额外处理省会
                    dealChildrenData(proList, gdList, false);
                    lineIntegrityDataVO.setChildren(proList);
                }

                // 数据封装
                Double temValue = lineList.stream().filter(item->item.getIntegrityData()!=3.14159).mapToDouble(LineIntegrityDataVO::getIntegrityData).average().orElse(3.14159);
                LineIntegrityDataVO temp = lineList.stream().filter(t -> t.getAlgoDescribe() != null).min(Comparator.comparing(LineIntegrityDataVO::getAlgoDescribe)).orElse(new LineIntegrityDataVO());
                lineIntegrityDataVO.setAlgoDescribe(temp.getAlgoDescribe());
                lineIntegrityDataVO.setId(generalDeviceDTO.getIndex());
                lineIntegrityDataVO.setName(generalDeviceDTO.getName());
                lineIntegrityDataVO.setLevel(0);
                lineIntegrityDataVO.setIntegrityData(DataStatisticsUtil.dataLimits(temValue));
                pro.add(lineIntegrityDataVO);

            }

            getAreaIntegrityData(mapAlarm,pro);
            return pro;
        } else {
            return new ArrayList<>();
        }
    }

    @Override
    public List<IntegrityIconVO> getIntegrityIcon(DeviceInfoParam.CompareBusinessParam integrityIconParam) {
        integrityIconParam.setServerName(generalInfo.getMicroServiceName());
        List<GeneralDeviceDTO> generalDeviceDTOList = generalDeviceInfoClient.getPracticalRunDeviceInfo(integrityIconParam).getData();
        List<IntegrityIconVO> out = new ArrayList<>();
        if (!CollectionUtils.isEmpty(generalDeviceDTOList)) {
            for (GeneralDeviceDTO generalDeviceDTO : generalDeviceDTOList) {
                IntegrityIconVO outParam = new IntegrityIconVO();
                List<String> lineIndexes = generalDeviceDTO.getLineIndexes();
                if (CollectionUtils.isEmpty(lineIndexes)) {
                    continue;
                }
                outParam.setType(generalDeviceDTO.getName()+"\n("+generalDeviceDTO.getLineIndexes().size()+")");
                //根据监测点查询数据完整性
                List<PublicDTO> integrityData = getCondition(lineIndexes, integrityIconParam.getSearchBeginTime(), integrityIconParam.getSearchEndTime());
                outParam.setSingle(NumberUtil.round(integrityData.stream().mapToDouble(PublicDTO::getData).average().orElse(3.14159),2).doubleValue());
                //如果存在需要比较的时间，再获取对应数据
                if (StrUtil.isNotBlank(integrityIconParam.getPeriodBeginTime()) && StrUtil.isNotBlank(integrityIconParam.getPeriodEndTime())) {
                    List<PublicDTO> compareData = getCondition(lineIndexes, integrityIconParam.getPeriodBeginTime(), integrityIconParam.getPeriodEndTime());
                    outParam.setRatio(NumberUtil.round(compareData.stream().mapToDouble(PublicDTO::getData).average().orElse(3.14159),2).doubleValue());
                }
                out.add(outParam);
            }
        }
        out.sort(new Comparator<IntegrityIconVO>() {
            @Override
            public int compare(IntegrityIconVO o1, IntegrityIconVO o2) {
                Comparator<Object> com = Collator.getInstance(Locale.CHINA);
                return com.compare(o1.getType(), o2.getType());
            }
        });
        return out;
    }


    private List<PublicDTO> getCondition(List<String> lineList, String startTime, String endTime) {
        List<PublicDTO> integrityList = new ArrayList<>();
        OnlineRateParam param = new OnlineRateParam();
        param.setIds(lineList);
        param.setStartTime(DateUtil.beginOfDay(DateUtil.parse(startTime)).toString());
        param.setEndTime(DateUtil.endOfDay(DateUtil.parse(endTime)).toString());
        List<RStatIntegrityVO> data = rStatIntegrityDMapper.getOnIntegrityByIds(param);
        if (!CollectionUtils.isEmpty(data)) {
            data.forEach(po -> {
                PublicDTO publicDTO = new PublicDTO();
                //数据完整性 保留四位小数
                Double integrity = po.getIntegrityRate() == null ? 3.14159 : BigDecimal.valueOf(Double.parseDouble(po.getIntegrityRate().toString())).setScale(2, RoundingMode.HALF_UP).doubleValue();
                publicDTO.setId(po.getLineIndex());
                publicDTO.setData((integrity > 100.00) ? 100.00 : integrity);
                integrityList.add(publicDTO);
            });
        }
        return integrityList;
    }

    public void getAreaIntegrityData(Map<Integer, Integer> mapAlarm,List<LineIntegrityDataVO> proList) {
        for (LineIntegrityDataVO proItem : proList) {
            List<LineIntegrityDataVO> gds = proItem.getChildren();
            if (CollectionUtil.isNotEmpty(gds)) {
                for (LineIntegrityDataVO gdItem : gds) {
                    List<LineIntegrityDataVO> subs = gdItem.getChildren();
                    if (CollectionUtil.isNotEmpty(subs)) {
                        for (LineIntegrityDataVO subItem : subs) {
                            if (Objects.nonNull(subItem.getAlgoDescribe())) {
                                if (mapAlarm.containsKey(subItem.getAlgoDescribe())) {
                                    if (subItem.getIntegrityData() != 3.14159 && subItem.getIntegrityData() < mapAlarm.get(subItem.getAlgoDescribe())) {
                                        subItem.setValueOver(1);
                                    } else {
                                        subItem.setValueOver(0);
                                    }
                                }
                            }
                        }
                    }
                    if (Objects.nonNull(gdItem.getAlgoDescribe())) {
                        if (mapAlarm.containsKey(gdItem.getAlgoDescribe())) {
                            if (gdItem.getIntegrityData() != 3.14159 && gdItem.getIntegrityData() < mapAlarm.get(gdItem.getAlgoDescribe())) {
                                gdItem.setValueOver(1);
                            } else {
                                gdItem.setValueOver(0);
                            }
                        }
                    }
                }
            }
            if (Objects.nonNull(proItem.getAlgoDescribe())) {
                if (mapAlarm.containsKey(proItem.getAlgoDescribe()))
                    if (proItem.getIntegrityData() != 3.14159 && proItem.getIntegrityData() < mapAlarm.get(proItem.getAlgoDescribe())){
                        proItem.setValueOver(1);
                    } else {
                        proItem.setValueOver(0);
                    }
            }
        }
    }

    /**
     * 处理变电站
     *
     * @param targetData   父集合
     * @param childrenData 子集合
     * @param isLine       处理策略
     */
    private void dealChildrenData(List<LineIntegrityDataVO> targetData, List<LineIntegrityDataVO> childrenData, boolean isLine) {
        // 创建一个map集合，用于封装对象
        Map<String, List<LineIntegrityDataVO>> groupLine;
        if (isLine) {
            // 通过stream流分组
            groupLine = childrenData.stream().collect(Collectors.groupingBy(lineAdministrationTree -> {
                // 获取父id字符串，通过 逗号 分割 成一个数组
                String[] pid = lineAdministrationTree.getPids().split(",");
                // 判断集合索引为3的元素
                return pid[LineBaseEnum.SUB_LEVEL.getCode()];
            }));
        } else {
            groupLine = childrenData.stream().collect(Collectors.groupingBy(LineIntegrityDataVO::getPid));
        }
        targetData = targetData.stream().peek(lineAdministrationTree -> {
            Set<String> pids = groupLine.keySet();
            for (String pid : pids) {
                if (lineAdministrationTree.getId().equals(pid)) {
                    List<LineIntegrityDataVO> lineIntegrityDataVOList = groupLine.get(pid);
                    lineAdministrationTree.setChildren(lineIntegrityDataVOList);
                    //父级完整性匹配
                    Double temValue = lineIntegrityDataVOList.stream().filter(item->item.getIntegrityData() != 3.14159).mapToDouble(LineIntegrityDataVO::getIntegrityData).average().orElse(3.14159);
                    lineAdministrationTree.setIntegrityData(DataStatisticsUtil.dataLimits(temValue));
                    LineIntegrityDataVO temp = lineIntegrityDataVOList.stream().filter(t -> t.getAlgoDescribe() != null).min(Comparator.comparing(LineIntegrityDataVO::getAlgoDescribe)).orElse(new LineIntegrityDataVO());
                    lineAdministrationTree.setAlgoDescribe(temp.getAlgoDescribe());
                }
            }
        }).collect(Collectors.toList());
    }

}
