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

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.njcn.common.pojo.enums.common.DataStateEnum;
import com.njcn.common.pojo.param.StatisticsBizBaseParam;
import com.njcn.device.biz.enums.RunFlagEnum;
import com.njcn.device.biz.pojo.dto.DeptGetChildrenMoreDTO;
import com.njcn.device.biz.pojo.dto.LineDevGetDTO;
import com.njcn.device.biz.pojo.param.DeptGetLineParam;
import com.njcn.device.common.mapper.onlinerate.OnLineRateMapper;
import com.njcn.device.common.service.GeneralDeviceService;
import com.njcn.device.device.service.IDeviceService;
import com.njcn.device.line.mapper.LineDetailMapper;
import com.njcn.device.line.service.DeptLineService;
import com.njcn.device.line.service.LineService;
import com.njcn.device.pq.mapper.RStatOnlinerateDMapper;
import com.njcn.device.pq.pojo.dto.GeneralDeviceDTO;
import com.njcn.device.pq.pojo.param.GridDiagramParam;
import com.njcn.device.pq.pojo.param.LineBaseQueryParam;
import com.njcn.device.pq.pojo.param.OnlineRateParam;
import com.njcn.device.pq.pojo.param.dataClean.MonitorBaseParam;
import com.njcn.device.pq.pojo.po.*;
import com.njcn.device.pq.pojo.vo.GridDiagramProVO;
import com.njcn.device.pq.pojo.vo.GridDiagramVO;
import com.njcn.device.pq.pojo.vo.LoadTypeVO;
import com.njcn.device.pq.pojo.vo.RStatOnlineRateVO;
import com.njcn.device.pq.service.*;
import com.njcn.device.rstatintegrity.mapper.RStatIntegrityDMapper;
import com.njcn.system.api.DicDataFeignClient;
import com.njcn.system.enums.DicDataEnum;
import com.njcn.system.enums.DicDataTypeEnum;
import com.njcn.system.pojo.po.DictData;
import com.njcn.user.api.DeptFeignClient;
import com.njcn.user.pojo.po.Dept;

import java.time.ZoneId;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Service;


/**
 * @author wr
 * @description
 * @date 2024/4/16 13:57
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class GridDiagramServiceImpl implements GridDiagramService {

    private final CommTerminalService commTerminalService;
    private final DeptFeignClient deptFeignClient;
    private final DicDataFeignClient dicDataFeignClient;
    private final RStatOnlinerateDMapper onLineRateDMapper;
    private final RStatIntegrityDMapper integrityDMapper;
    private final IDeviceService deviceService;
    private final GeneralDeviceService generalDeviceService;
    private final LineService lineService;
    private final DeptLineService deptLineService;
    private final LineDetailMapper lineDetailMapper;
    private final OnLineRateMapper onLineRateMapper;

    @Override
    public GridDiagramVO getGridDiagramMonitor(GridDiagramParam param) {
        //获取电压等级
        List<DictData> dictDataList = dicDataFeignClient.getDicDataByTypeCode(DicDataTypeEnum.DEV_VOLTAGE_STAND.getCode()).getData();
        List<DictData> v = dicDataFeignClient.getDicDataByTypeCode(DicDataTypeEnum.PANORAMIC_VOLTAGE.getCode()).getData();
        List<String> voltageIds;
        //获取电压等级550 220 110 35
        if (CollUtil.isNotEmpty(v)) {
            List<String> vName = v.stream().map(DictData::getName).collect(Collectors.toList());
            voltageIds = dictDataList.stream().filter(item -> vName.contains(item.getName())).sorted(Comparator.comparing(DictData::getSort).reversed()).map(DictData::getId).collect(Collectors.toList());
        } else {
            voltageIds = dictDataList.stream().filter(item -> Objects.equals(DicDataEnum.DY_500KV.getCode(), item.getCode()) || Objects.equals(DicDataEnum.DY_220KV.getCode(), item.getCode()) || Objects.equals(DicDataEnum.DY_110KV.getCode(), item.getCode()) || Objects.equals(DicDataEnum.DY_35KV.getCode(), item.getCode())).sorted(Comparator.comparing(DictData::getSort).reversed()).map(DictData::getId).collect(Collectors.toList());
        }


        GridDiagramVO gridDiagramVO = new GridDiagramVO();
        List<GridDiagramVO.LineStatistics> info = new ArrayList<>();
        List<GridDiagramVO.LineStatistics> gwInfo = new ArrayList<>();

        //获取部门数据关系
        List<Dept> data = deptFeignClient.getDirectSonSelf(param.getOrgId()).getData();
        DeptGetLineParam deptGetLineParam = new DeptGetLineParam();
        deptGetLineParam.setDeptId(param.getOrgId());
        deptGetLineParam.setLineRunFlag(0);
        List<DeptGetChildrenMoreDTO> deptGetChildrenMoreDTOS = commTerminalService.deptGetLine(deptGetLineParam);
        //监测点id集合
        List<String> lineIdsAll = deptGetChildrenMoreDTOS.stream().flatMap(x -> x.getLineBaseList().stream().map(LineDevGetDTO::getPointId)).distinct().collect(Collectors.toList());
        //终端id集合
        List<String> devIdsAll = deptGetChildrenMoreDTOS.stream().flatMap(x -> x.getLineBaseList().stream().map(LineDevGetDTO::getDevId)).distinct().collect(Collectors.toList());
        List<RStatOnlinerateD> onlineRateByDevIds = new ArrayList<>();
        List<RStatIntegrityD> onIntegrityByIds = new ArrayList<>();
        if (CollUtil.isNotEmpty(lineIdsAll)) {
            //监测点完整性
            onIntegrityByIds.addAll(integrityDMapper.selectList(new QueryWrapper<RStatIntegrityD>().select("sum(real_time) as realTime,sum(due_time) as dueTime,line_index as lineIndex").in(CollUtil.isNotEmpty(lineIdsAll), "line_index", lineIdsAll).ge(StrUtil.isNotBlank(param.getSearchBeginTime()), "time_id", DateUtil.beginOfDay(DateUtil.parse(param.getSearchBeginTime()))).le(StrUtil.isNotBlank(param.getSearchEndTime()), "time_id", DateUtil.endOfDay(DateUtil.parse(param.getSearchEndTime()))).groupBy("line_index")));
            //终端在线率
            onlineRateByDevIds.addAll(onLineRateDMapper.selectList(new QueryWrapper<RStatOnlinerateD>().select("sum(online_min) as onlineMin,sum(offline_min) as offlineMin,dev_index as devIndex").in(CollUtil.isNotEmpty(devIdsAll), "dev_index", devIdsAll).ge(StrUtil.isNotBlank(param.getSearchBeginTime()), "time_id", DateUtil.beginOfDay(DateUtil.parse(param.getSearchBeginTime()))).le(StrUtil.isNotBlank(param.getSearchEndTime()), "time_id", DateUtil.endOfDay(DateUtil.parse(param.getSearchEndTime()))).groupBy("dev_index")));
        }

        Map<String, DeptGetChildrenMoreDTO> deptLineMap = deptGetChildrenMoreDTOS.stream().collect(Collectors.toMap(DeptGetChildrenMoreDTO::getUnitId, Function.identity()));
        GridDiagramVO.LineStatistics lineStatistics;
        GridDiagramVO.LineStatistics gwLineStatistics;
        for (Dept datum : data) {
            if (deptLineMap.containsKey(datum.getId())) {
                lineStatistics = new GridDiagramVO.LineStatistics();
                lineStatistics.setOrgId(datum.getId());
                lineStatistics.setOrgName(datum.getName());
                gwLineStatistics = new GridDiagramVO.LineStatistics();
                gwLineStatistics.setOrgId(datum.getId());
                gwLineStatistics.setOrgName(datum.getName());
                List<LineDevGetDTO> lineBaseList = deptLineMap.get(datum.getId()).getLineBaseList();
                List<GridDiagramVO.LineStatisticsData> statisticsData = new ArrayList<>();
                List<GridDiagramVO.LineStatisticsData> gwStatisticsData = new ArrayList<>();
                getLineStatisticsData(statisticsData, gwStatisticsData, lineBaseList, voltageIds, onlineRateByDevIds, onIntegrityByIds);
                lineStatistics.setData(statisticsData);
                gwLineStatistics.setData(gwStatisticsData);

                info.add(lineStatistics);
                gwInfo.add(gwLineStatistics);
            }
        }
        gridDiagramVO.setInfo(info);
        gridDiagramVO.setGwInfo(gwInfo);
        return gridDiagramVO;
    }

    /**
     * @param statisticsData     全部监测点数据
     * @param gwStatisticsData   国网监测点数据
     * @param lineBaseList       监测点信息
     * @param voltageIds         电压等级
     * @param onlineRateByDevIds 在线率
     * @param onIntegrityByIds   完整率
     * @Description: 在线率，完整率赋值
     * @Author: wr
     * @Date: 2024/4/18 15:38
     */
    private void getLineStatisticsData(List<GridDiagramVO.LineStatisticsData> statisticsData, List<GridDiagramVO.LineStatisticsData> gwStatisticsData, List<LineDevGetDTO> lineBaseList, List<String> voltageIds, List<RStatOnlinerateD> onlineRateByDevIds, List<RStatIntegrityD> onIntegrityByIds) {
        voltageIds.forEach((key) -> {
            statisticsDataList(statisticsData, lineBaseList, key, onlineRateByDevIds, onIntegrityByIds);
            gwStatisticsDataList(gwStatisticsData, lineBaseList, key, onlineRateByDevIds, onIntegrityByIds);
        });
        statisticsDataOtherList(statisticsData, lineBaseList, onlineRateByDevIds, onIntegrityByIds);
        gwStatisticsDataOtherList(gwStatisticsData, lineBaseList, onlineRateByDevIds, onIntegrityByIds);
    }

    /**
     * @param statisticsData
     * @param lineBaseList
     * @param value
     * @param onlineRateByDevIds
     * @param onIntegrityByIds
     * @Description: 全部监测点数据赋值
     * @Author: wr
     * @Date: 2024/4/18 15:40
     */
    private void statisticsDataList(List<GridDiagramVO.LineStatisticsData> statisticsData, List<LineDevGetDTO> lineBaseList, String value, List<RStatOnlinerateD> onlineRateByDevIds, List<RStatIntegrityD> onIntegrityByIds) {
        //监测点集合
        List<String> lineIds = lineBaseList.stream().filter(x -> value.equals(x.getVoltageLevel())).map(LineDevGetDTO::getPointId).distinct().collect(Collectors.toList());
        List<String> onLineNumIds = lineBaseList.stream().filter(x -> value.equals(x.getVoltageLevel()) && 1 == x.getComFlag()).map(LineDevGetDTO::getPointId).distinct().collect(Collectors.toList());
        //终端id集合
        List<String> devIds = lineBaseList.stream().filter(x -> value.equals(x.getVoltageLevel())).map(LineDevGetDTO::getDevId).distinct().collect(Collectors.toList());

        gridDiagramAdd(statisticsData, onlineRateByDevIds, value, onIntegrityByIds, devIds, lineIds, onLineNumIds);

    }

    private void statisticsDataOtherList(List<GridDiagramVO.LineStatisticsData> statisticsData, List<LineDevGetDTO> lineBaseList, List<RStatOnlinerateD> onlineRateByDevIds, List<RStatIntegrityD> onIntegrityByIds) {
        //终端id集合
        List<String> devIdsAll = lineBaseList.stream().map(LineDevGetDTO::getDevId).distinct().collect(Collectors.toList());
        //监测点集合
        List<String> lineIdsAll = lineBaseList.stream().map(LineDevGetDTO::getPointId).distinct().collect(Collectors.toList());
        List<String> onLineNumAll = lineBaseList.stream().filter(x -> 1 == x.getComFlag()).map(LineDevGetDTO::getPointId).distinct().collect(Collectors.toList());

        gridDiagramAdd(statisticsData, onlineRateByDevIds, null, onIntegrityByIds, devIdsAll, lineIdsAll, onLineNumAll);
    }

    private void gridDiagramAdd(List<GridDiagramVO.LineStatisticsData> statisticsData, List<RStatOnlinerateD> onlineRateByDevIds, String value, List<RStatIntegrityD> onIntegrityByIds, List<String> devIdsAll, List<String> lineIdsAll, List<String> onLineNumAll) {
        GridDiagramVO.LineStatisticsData lineStatisticsData = new GridDiagramVO.LineStatisticsData();
        lineStatisticsData.setColumnName(value);
        lineStatisticsData.setNum(lineIdsAll.size());
        lineStatisticsData.setNumList(lineIdsAll);
        lineStatisticsData.setOnLineNum(onLineNumAll.size());
        lineStatisticsData.setOnLineNumList(onLineNumAll);
        onLineAndIntegrity(lineIdsAll, onIntegrityByIds, devIdsAll, onlineRateByDevIds, lineStatisticsData);
        statisticsData.add(lineStatisticsData);
    }


    private void gwStatisticsDataList(List<GridDiagramVO.LineStatisticsData> statisticsData, List<LineDevGetDTO> lineBaseList, String value, List<RStatOnlinerateD> onlineRateByDevIds, List<RStatIntegrityD> onIntegrityByIds) {
        //监测点集合
        List<String> lineIds = lineBaseList.stream().filter(x -> value.equals(x.getVoltageLevel())).filter(x -> 1 == x.getIsUpToGrid()).map(LineDevGetDTO::getPointId).distinct().collect(Collectors.toList());
        List<String> onLineNumIds = lineBaseList.stream().filter(x -> value.equals(x.getVoltageLevel()) && 1 == x.getComFlag())
                .filter(x -> 1 == x.getIsUpToGrid())
                .map(LineDevGetDTO::getPointId).distinct().collect(Collectors.toList());
        //终端id集合
        List<String> devIds = lineBaseList.stream().filter(x -> value.equals(x.getVoltageLevel())).filter(x -> 1 == x.getIsUpToGrid()).map(LineDevGetDTO::getDevId).distinct().collect(Collectors.toList());

        gridDiagramAdd(statisticsData, onlineRateByDevIds, value, onIntegrityByIds, devIds, lineIds, onLineNumIds);
    }

    private void gwStatisticsDataOtherList(List<GridDiagramVO.LineStatisticsData> statisticsData, List<LineDevGetDTO> lineBaseList, List<RStatOnlinerateD> onlineRateByDevIds, List<RStatIntegrityD> onIntegrityByIds) {
        //终端id集合
        List<String> devIdsAll = lineBaseList.stream().filter(x -> 1 == x.getIsUpToGrid()).map(LineDevGetDTO::getDevId).distinct().collect(Collectors.toList());
        //监测点集合
        List<String> lineIdsAll = lineBaseList.stream().filter(x -> 1 == x.getIsUpToGrid()).map(LineDevGetDTO::getPointId).distinct().collect(Collectors.toList());
        List<String> onLineNumAll = lineBaseList.stream().filter(x -> 1 == x.getComFlag() && 1 == x.getIsUpToGrid()).map(LineDevGetDTO::getPointId).distinct().collect(Collectors.toList());

        gridDiagramAdd(statisticsData, onlineRateByDevIds, null, onIntegrityByIds, devIdsAll, lineIdsAll, onLineNumAll);
    }

    private void onLineAndIntegrity(List<String> lineIds, List<RStatIntegrityD> onIntegrityByIds, List<String> devIds, List<RStatOnlinerateD> onlineRateByDevIds, GridDiagramVO.LineStatisticsData lineStatisticsData) {
        //监测完整率
        List<RStatIntegrityD> integrityDS = onIntegrityByIds.stream().filter(x -> lineIds.contains(x.getLineIndex())).collect(Collectors.toList());
        if (CollUtil.isNotEmpty(integrityDS)) {
            double realTime = integrityDS.stream().mapToDouble(RStatIntegrityD::getRealTime).sum();
            double dueTime = integrityDS.stream().mapToDouble(RStatIntegrityD::getDueTime).sum();
            lineStatisticsData.setIntegrityRate(Math.min(NumberUtil.round(realTime * 100 / dueTime, 2).floatValue(), 100));
        } else {
            lineStatisticsData.setIntegrityRate(0.0f);
        }
        //终端在线率
        List<RStatOnlinerateD> onlineRateDS = onlineRateByDevIds.stream().filter(x -> devIds.contains(x.getDevIndex())).collect(Collectors.toList());
        if (CollUtil.isNotEmpty(onlineRateDS)) {
            double onlineTime = onlineRateDS.stream().mapToDouble(RStatOnlinerateD::getOnlineMin).sum();
            double offlineTime = onlineRateDS.stream().mapToDouble(RStatOnlinerateD::getOfflineMin).sum();
            lineStatisticsData.setOnLineRate(Math.min(NumberUtil.round(onlineTime * 100.0 / (onlineTime + offlineTime), 2).floatValue(), 100));
        } else {
            lineStatisticsData.setOnLineRate(0.0f);
        }
    }


    @Override
    public GridDiagramVO getGridDiagramDev(GridDiagramParam param) {
        //获取电压等级
        List<DictData> dictDataList = dicDataFeignClient.getDicDataByTypeCode(DicDataTypeEnum.DEV_VOLTAGE_STAND.getCode()).getData();
        List<DictData> v = dicDataFeignClient.getDicDataByTypeCode(DicDataTypeEnum.PANORAMIC_VOLTAGE.getCode()).getData();
        List<String> voltageIds;
        //获取电压等级550 220 110 35
        if (CollUtil.isNotEmpty(v)) {
            List<String> vName = v.stream().map(DictData::getName).collect(Collectors.toList());
            voltageIds = dictDataList.stream().filter(item -> vName.contains(item.getName())).sorted(Comparator.comparing(DictData::getSort).reversed()).map(DictData::getId).collect(Collectors.toList());
        } else {
            voltageIds = dictDataList.stream().filter(item -> Objects.equals(DicDataEnum.DY_500KV.getCode(), item.getCode()) || Objects.equals(DicDataEnum.DY_220KV.getCode(), item.getCode()) || Objects.equals(DicDataEnum.DY_110KV.getCode(), item.getCode()) || Objects.equals(DicDataEnum.DY_35KV.getCode(), item.getCode())).sorted(Comparator.comparing(DictData::getSort).reversed()).map(DictData::getId).collect(Collectors.toList());

        }

        GridDiagramVO gridDiagramVO = new GridDiagramVO();
        List<GridDiagramVO.LineStatistics> info = new ArrayList<>();
        List<GridDiagramVO.LineStatistics> gwInfo = new ArrayList<>();

        //获取部门数据关系
        List<Dept> data = deptFeignClient.getDirectSonSelf(param.getOrgId()).getData();
        DeptGetLineParam deptGetLineParam = new DeptGetLineParam();
        deptGetLineParam.setDeptId(param.getOrgId());
        List<DeptGetChildrenMoreDTO> deptGetChildrenMoreDTOS = commTerminalService.deptGetLine(deptGetLineParam);


        Map<String, DeptGetChildrenMoreDTO> deptLineMap = deptGetChildrenMoreDTOS.stream().collect(Collectors.toMap(DeptGetChildrenMoreDTO::getUnitId, Function.identity()));
        GridDiagramVO.LineStatistics lineStatistics;
        GridDiagramVO.LineStatistics gwLineStatistics;
        for (Dept datum : data) {
            if (deptLineMap.containsKey(datum.getId())) {
                lineStatistics = new GridDiagramVO.LineStatistics();
                lineStatistics.setOrgId(datum.getId());
                lineStatistics.setOrgName(datum.getName());
                gwLineStatistics = new GridDiagramVO.LineStatistics();
                gwLineStatistics.setOrgId(datum.getId());
                gwLineStatistics.setOrgName(datum.getName());
                List<LineDevGetDTO> lineBaseList = deptLineMap.get(datum.getId()).getLineBaseList();
                List<GridDiagramVO.StatisticsData> statisticsData = new ArrayList<>();
                List<GridDiagramVO.StatisticsData> gwStatisticsData = new ArrayList<>();
                getDevStatisticsData(statisticsData, gwStatisticsData, lineBaseList, voltageIds);
                lineStatistics.setData(statisticsData);
                gwLineStatistics.setData(gwStatisticsData);

                info.add(lineStatistics);
                gwInfo.add(gwLineStatistics);
            }
        }
        gridDiagramVO.setInfo(info);
        gridDiagramVO.setGwInfo(gwInfo);
        return gridDiagramVO;
    }

    @Override
    public Map<String, Long> getGridDiagramDevTendency(GridDiagramParam param, Integer type) {
        List<Integer> runFlag = new ArrayList<>();
        if (3 != type) {
            runFlag.add(0);
        }
        List<GeneralDeviceDTO> generalDeviceDTOList = generalDeviceService.getDeviceInfo(param.getDeviceInfoParam(), runFlag, Stream.of(1).collect(Collectors.toList()));
        Map<String, Long> map = new LinkedHashMap<>();
        DateField dateField;
        DateTime parse;
        if (1 == param.getType()) {
            dateField = DateField.YEAR;
            parse = DateUtil.offset(DateUtil.parse(param.getSearchBeginTime()), DateField.YEAR, -5);
        } else {
            dateField = DateField.MONTH;
            parse = DateUtil.parse(param.getSearchBeginTime());
        }
        //根据步进单位获取起始日期时间和结束日期时间的时间区间集合
        List<DateTime> dateTimes = DateUtil.rangeToList(parse, DateUtil.parse(param.getSearchEndTime()), dateField);
        List<Date> times;
        //终端分布趋势
        if (4 == type) {
            List<String> devIDs = generalDeviceDTOList.stream().flatMap(x -> x.getDeviceIndexes().stream()).distinct().collect(Collectors.toList());
            List<Device> list = deviceService.list(new LambdaQueryWrapper<Device>().select(Device::getLoginTime).in(CollUtil.isNotEmpty(devIDs), Device::getId, devIDs).eq(Device::getRunFlag, 0));
            times = list.stream().map(x -> Date.from(x.getLoginTime().atStartOfDay(ZoneId.systemDefault()).toInstant())).collect(Collectors.toList());
        } else {
            List<String> ids;
            //监测点分布趋势
            if (type == 3) {
                ids = generalDeviceDTOList.stream().flatMap(x -> x.getSubIndexes().stream()).distinct().collect(Collectors.toList());
            } else {
                ids = generalDeviceDTOList.stream().flatMap(x -> x.getLineIndexes().stream()).distinct().collect(Collectors.toList());
            }
            List<Line> list = lineService.list(new LambdaQueryWrapper<Line>().in(CollUtil.isNotEmpty(ids), Line::getId, ids).eq(Line::getState, DataStateEnum.ENABLE.getCode()).eq(Line::getLevel, type));
            times = list.stream().map(x -> Date.from(x.getCreateTime().atZone(ZoneId.systemDefault()).toInstant())).collect(Collectors.toList());
        }
        long num = 0;
        for (int i = 0; i < dateTimes.size(); i++) {
            if (i == 0) {
                if (1 == param.getType()) {
                    long count = times.stream().filter(x -> DateUtil.isIn(x, DateUtil.beginOfYear(DateUtil.parse("1970-01-01 00:00:00")), DateUtil.endOfYear(dateTimes.get(0)))).count();
                    num = num + count;
                    map.put(dateTimes.get(0).toString().substring(0, 4), num);
                } else {
                    long count = times.stream().filter(x -> DateUtil.isIn(x, DateUtil.beginOfYear(DateUtil.parse("1970-01-01 00:00:00")), DateUtil.endOfMonth(dateTimes.get(0)))).count();
                    num = num + count;
                    map.put(dateTimes.get(0).toString().substring(0, 7), num);
                }
            } else {
                int finalI = i;
                if (1 == param.getType()) {
                    long count = times.stream().filter(x -> DateUtil.isIn(x, DateUtil.beginOfYear(dateTimes.get(finalI)), DateUtil.endOfYear(dateTimes.get(finalI)))).count();
                    num = num + count;
                    map.put(dateTimes.get(finalI).toString().substring(0, 4), num);
                } else {
                    long count = times.stream().filter(x -> DateUtil.isIn(x, DateUtil.beginOfMonth(dateTimes.get(finalI)), DateUtil.endOfMonth(dateTimes.get(finalI)))).count();
                    num = num + count;
                    map.put(dateTimes.get(finalI).toString().substring(0, 7), num);
                }
            }
        }
        return map;
    }

    @Override
    public List<GridDiagramVO.DeviceData> getGridDiagramDevData(GridDiagramParam param) {
        // 获取所有数据
        List<GeneralDeviceDTO> generalDeviceDTOList = generalDeviceService.getDeviceInfo(param.getDeviceInfoParam(), Stream.of(0).collect(Collectors.toList()), Stream.of(1).collect(Collectors.toList()));
        List<String> devIDs = generalDeviceDTOList.stream().flatMap(x -> x.getDeviceIndexes().stream()).distinct().collect(Collectors.toList());
        List<RStatOnlinerateD> onlinerateDS = onLineRateDMapper.selectList(new QueryWrapper<RStatOnlinerateD>()
                .select("sum(online_min) as onlineMin,sum(offline_min) as offlineMin,dev_index as devIndex")
                .in(CollUtil.isNotEmpty(devIDs), "dev_index", devIDs)
                .ge(StrUtil.isNotBlank(param.getSearchBeginTime()), "time_id", DateUtil.beginOfDay(DateUtil.parse(param.getSearchBeginTime())))
                .le(StrUtil.isNotBlank(param.getSearchEndTime()), "time_id", DateUtil.endOfDay(DateUtil.parse(param.getSearchEndTime())))
                .groupBy("dev_index"));
        List<String> devIds = generalDeviceDTOList.stream().flatMap(x -> x.getDeviceIndexes().stream()).distinct().collect(Collectors.toList());
        List<Device> list = deviceService.list(new LambdaQueryWrapper<Device>()
                .select(Device::getId, Device::getRunFlag, Device::getComFlag)
                .in(CollUtil.isNotEmpty(devIds), Device::getId, devIds)
        );
        List<GridDiagramVO.DeviceData> info = new ArrayList<>();
        GridDiagramVO.DeviceData data;
        for (GeneralDeviceDTO generalDeviceDTO : generalDeviceDTOList) {
            data = new GridDiagramVO.DeviceData();
            data.setOrgId(generalDeviceDTO.getIndex());
            data.setOrgName(generalDeviceDTO.getName());
            List<Device> collect = list.stream().filter(x -> generalDeviceDTO.getDeviceIndexes().contains(x.getId())).collect(Collectors.toList());
            List<Device> runDevice = collect.stream().filter(x -> 0 == x.getRunFlag()).collect(Collectors.toList());
            data.setDevCount(Long.valueOf(runDevice.size()));
            data.setDevOnCount(runDevice.stream().filter(x -> 1 == x.getComFlag()).count());
            List<RStatOnlinerateD> onlineRateDS = onlinerateDS.stream().filter(x -> generalDeviceDTO.getDeviceIndexes().contains(x.getDevIndex())).collect(Collectors.toList());
            if (CollUtil.isNotEmpty(onlineRateDS)) {
                double onlineTime = onlineRateDS.stream().mapToDouble(RStatOnlinerateD::getOnlineMin).sum();
                double offlineTime = onlineRateDS.stream().mapToDouble(RStatOnlinerateD::getOfflineMin).sum();
                data.setOnlineEvaluate(Math.min(NumberUtil.round(onlineTime * 100.0 / (onlineTime + offlineTime), 2).doubleValue(), 100));
            } else {
                data.setOnlineEvaluate(0.0);
            }
            info.add(data);
        }
        return info;
    }

    @Override
    public List<GridDiagramVO.DevData> getGridDiagramDevDataList(GridDiagramParam param) {
        List<GridDiagramVO.DevData> info = new ArrayList<>();
        List<GeneralDeviceDTO> generalDeviceDTOList = generalDeviceService.getDeviceInfoAsDept(param.getDeviceInfoParam(), Arrays.asList(0), Stream.of(1).collect(Collectors.toList()));
        List<String> devIds = generalDeviceDTOList.stream().flatMap(x -> x.getDeviceIndexes().stream()).collect(Collectors.toList());
        //终端信息
        List<Device> devList = new ArrayList<>();
        if (CollUtil.isNotEmpty(devIds)) {
            devList = deviceService.list(new LambdaQueryWrapper<Device>().in(CollUtil.isNotEmpty(devIds), Device::getId, devIds));
        }
        GridDiagramVO.DevData data;
        OnlineRateParam onlineRateParam = new OnlineRateParam();
        onlineRateParam.setStartTime(param.getSearchBeginTime());
        onlineRateParam.setEndTime(param.getSearchEndTime());
        for (GeneralDeviceDTO dto : generalDeviceDTOList) {
            List<String> list = new ArrayList<>();
            for (int i = 0; i < 3; i++) {
                int finalI = i;
                List<String> devices = devList.stream()
                        .filter(x -> dto.getDeviceIndexes().contains(x.getId()))
                        .filter(x -> finalI == x.getRunFlag())
                        .map(Device::getId).distinct().collect(Collectors.toList());
                list.add(String.valueOf(devices.size()));
                //当终端信息是0标识需要进行在线率查询，并进行赋值
                if (i == 0) {
                    if (CollUtil.isNotEmpty(devices)) {
                        onlineRateParam.setIds(devices);
                        list.add(String.valueOf(onLineRateDMapper.getTotalOnlineRates(onlineRateParam)));
                    } else {
                        list.add("0");
                    }
                }
            }
            data = new GridDiagramVO.DevData();
            data.setOrgId(dto.getIndex());
            data.setOrgName(dto.getName());
            data.setRunNum(Long.valueOf(list.get(0)));
            data.setOverhaulNum(Long.valueOf(list.get(2)));
            data.setRefundNum(Long.valueOf(list.get(3)));
            data.setOnLineRate(Float.valueOf(list.get(1)));
            info.add(data);
        }
        return info;
    }

    @Override
    public GridDiagramProVO getGridDiagramStatistics(StatisticsBizBaseParam param) {
        GridDiagramProVO vo = new GridDiagramProVO();
        // 获取包括当前部门的后代所有部门信息
        List<String> deptIds = deptFeignClient.getDepSonIdtByDeptId(param.getId()).getData();
        // 根据部门ids集合查询是否绑定监测点 部门和监测点关联关系中间表：pq_dept_line 可以一对多
        List<DeptLine> deptLines = deptLineService.selectDeptBindLines(deptIds);
        List<String> lineIds = deptLines.stream().map(DeptLine::getLineId).collect(Collectors.toList());
        List<LineDetail> lines = lineDetailMapper.getLineDetailByIds(lineIds);
        LineBaseQueryParam baseQueryParam = new LineBaseQueryParam();
        baseQueryParam.setStartTime(param.getStartTime());
        baseQueryParam.setEndTime(param.getEndTime());
        //开始组装总信息
        List<GridDiagramProVO.Details> data = new ArrayList<>();
        data.add(add(lines, baseQueryParam, null, 0));
        data.add(add(lines, baseQueryParam, null, 1));
        //开始组装国网信息
        List<GridDiagramProVO.Details> gwData = new ArrayList<>();
        gwData.add(add(lines, baseQueryParam, 1, 0));
        vo.setData(data);
        vo.setGwData(gwData);

        return vo;
    }

    private GridDiagramProVO.Details add(List<LineDetail> lines,
                                         LineBaseQueryParam baseQueryParam,
                                         Integer gwType,
                                         Integer powerFlag) {
        GridDiagramProVO.Details details = new GridDiagramProVO.Details();
        Stream<LineDetail> stream = lines.stream();
        Stream<LineDetail> stream2 = lines.stream();
        Stream<LineDetail> stream3 = lines.stream();
        if (gwType != null) {
            stream = stream.filter(x -> x.getMonitorFlag() == gwType);
            stream2 = stream2.filter(x -> x.getMonitorFlag() == gwType);
            stream3 = stream3.filter(x -> x.getMonitorFlag() == gwType);
        }
        if (powerFlag != null) {
            stream = stream.filter(x -> x.getPowerFlag() == powerFlag);
            stream2 = stream2.filter(x -> x.getPowerFlag() == powerFlag);
            stream3 = stream3.filter(x -> x.getPowerFlag() == powerFlag);
        }
        //总监测点
        List<String> ids = stream.map(LineDetail::getId).collect(Collectors.toList());
        //在线监测点
        List<String> onIds = stream2.filter(x -> x.getComFlag() == 1)
                .map(LineDetail::getId)
                .collect(Collectors.toList());
        details.setNum(ids.size());
        details.setNumList(ids);
        details.setOnLineNum(onIds.size());
        details.setOnLineNumList(onIds);
        baseQueryParam.setLineIds(ids);
        if (CollUtil.isNotEmpty(ids)) {
            details.setIntegrityRate(integrityDMapper.selectTotalIntegrityByLineIds(baseQueryParam));
        } else {
            details.setIntegrityRate(0.0f);
        }

        List<String> devIds = stream3.map(LineDetail::getMonitorName).collect(Collectors.toList());
        if (CollUtil.isNotEmpty(devIds)) {
            OnlineRateParam onlineRateParam = new OnlineRateParam();
            onlineRateParam.setIds(devIds);
            onlineRateParam.setStartTime(baseQueryParam.getStartTime());
            onlineRateParam.setEndTime(baseQueryParam.getEndTime());
            //获取所有终端在线率
            List<RStatOnlineRateVO> onlineRateByDev = onLineRateMapper.getOnlineRateByDevIds(onlineRateParam);
            if(CollUtil.isNotEmpty(onlineRateByDev)){
                details.setOnLineRate(onlineRateByDev.get(0).getOnlineRate().floatValue());
            }else{
                details.setOnLineRate(0.0f);
            }
        } else {
            details.setOnLineRate(0.0f);
        }
        return details;
    }

    @Override
    public List<String> getGridDiagramCityDev(GridDiagramParam param) {
        List<GeneralDeviceDTO> generalDeviceDTOList = generalDeviceService.getDeviceInfoAsDept(param.getDeviceInfoParam(), null, Stream.of(1).collect(Collectors.toList()));
        List<String> devIds = generalDeviceDTOList.stream().flatMap(x -> x.getDeviceIndexes().stream()).collect(Collectors.toList());
        //终端信息
        List<Device> devList = new ArrayList<>();
        if (CollUtil.isNotEmpty(devIds)) {
            devList = deviceService.list(new LambdaQueryWrapper<Device>().in(CollUtil.isNotEmpty(devIds), Device::getId, devIds));
        }
        OnlineRateParam onlineRateParam = new OnlineRateParam();
        onlineRateParam.setStartTime(param.getSearchBeginTime());
        onlineRateParam.setEndTime(param.getSearchEndTime());

        List<String> list = new ArrayList<>();
        for (int i = 0; i < 3; i++) {
            int finalI = i;
            List<String> devices = devList.stream().filter(x -> finalI == x.getRunFlag()).map(Device::getId).distinct().collect(Collectors.toList());
            list.add(String.valueOf(devices.size()));
            if (i == 0) {
                onlineRateParam.setIds(devices);
                list.add(String.valueOf(onLineRateDMapper.getTotalOnlineRates(onlineRateParam)));
            } else {
                list.add(String.valueOf(3.14159));
            }
        }

        return list;
    }

    @Override
    public List<RStatIntegrityD> getGridDiagramIntegrityD(StatisticsBizBaseParam param) {
        return integrityDMapper.selectList(new LambdaQueryWrapper<RStatIntegrityD>()
                .eq(RStatIntegrityD::getLineIndex, param.getId())
                .ge(StrUtil.isNotBlank(param.getStartTime()), RStatIntegrityD::getTimeId, DateUtil.beginOfDay(DateUtil.parse(param.getStartTime())))
                .le(StrUtil.isNotBlank(param.getEndTime()), RStatIntegrityD::getTimeId, DateUtil.endOfDay(DateUtil.parse(param.getEndTime())))
        );
    }

    @Override
    public List<RStatOnlinerateD> getGridDiagramOnLineRateD(StatisticsBizBaseParam param) {
        return onLineRateDMapper.selectList(new LambdaQueryWrapper<RStatOnlinerateD>()
                .eq(RStatOnlinerateD::getDevIndex, param.getId())
                .ge(StrUtil.isNotBlank(param.getStartTime()), RStatOnlinerateD::getTimeId, DateUtil.beginOfDay(DateUtil.parse(param.getStartTime())))
                .le(StrUtil.isNotBlank(param.getEndTime()), RStatOnlinerateD::getTimeId, DateUtil.endOfDay(DateUtil.parse(param.getEndTime())))
        );
    }

    @Override
    public List<LoadTypeVO> loadTypeVOList(@NotNull GridDiagramParam param) {
        List<LoadTypeVO> returnList = new ArrayList<>();
        MonitorBaseParam monitorBaseParam = new MonitorBaseParam();
        monitorBaseParam.setDeptId(param.getOrgId());
        monitorBaseParam.setLineRunFlag(RunFlagEnum.RUNNING.getStatus());
        List<String> list = commTerminalService.getRunMonitorByDept(monitorBaseParam);
        if(CollUtil.isNotEmpty(list)) {
            List<LineDetail> lineDetailList =lineDetailMapper.selectList(new LambdaQueryWrapper<LineDetail>().select(LineDetail::getLoadType, LineDetail::getId).in(LineDetail::getId, list));
            Map<String,List<String>> map = lineDetailList.stream().collect(Collectors.groupingBy(LineDetail::getLoadType,Collectors.mapping(LineDetail::getId, Collectors.toList())));
            map.forEach((k,v)->{
                LoadTypeVO loadTypeVO = new LoadTypeVO();
                loadTypeVO.setName(k);
                loadTypeVO.setCount(v.size());
                loadTypeVO.setLoadTypeList(v);
                returnList.add(loadTypeVO);
            });
        }
        return returnList;
    }


    private void getDevStatisticsData(List<GridDiagramVO.StatisticsData> statisticsData, List<GridDiagramVO.StatisticsData> gwStatisticsData, List<LineDevGetDTO> lineBaseList, List<String> voltageIds) {
        GridDiagramVO.StatisticsData data;
        for (String voltageId : voltageIds) {
            for (int i = 0; i < 2; i++) {
                data = new GridDiagramVO.StatisticsData();
                data.setColumnName(voltageId);
                int finalI = i;
                //todo 1国网信息
                long count = lineBaseList.stream().filter(x -> getIsUpToGrid(finalI, x, voltageId)).map(LineDevGetDTO::getDevId).distinct().count();
                data.setNumOne(count);
                data.setNumOneList(lineBaseList.stream().filter(x -> getIsUpToGrid(finalI, x, voltageId)).map(LineDevGetDTO::getPointId).distinct().collect(Collectors.toList()));
                long count1 = lineBaseList.stream().filter(x -> getIsUpToGrid(finalI, x, voltageId)).filter(x -> 1 == x.getComFlag()).map(LineDevGetDTO::getDevId).distinct().count();
                data.setNumTwo(count1);
                data.setNumTwoList(lineBaseList.stream().filter(x -> getIsUpToGrid(finalI, x, voltageId)).filter(x -> 1 == x.getComFlag()).map(LineDevGetDTO::getPointId).distinct().collect(Collectors.toList()));
                if (i == 0) {
                    statisticsData.add(data);
                } else {
                    gwStatisticsData.add(data);
                }
            }
        }
        //numOne 在线  numTwo 在线
        data = new GridDiagramVO.StatisticsData();
        data.setNumOne(lineBaseList.stream().map(LineDevGetDTO::getDevId).distinct().count());
        data.setNumOneList(lineBaseList.stream().map(LineDevGetDTO::getPointId).distinct().collect(Collectors.toList()));
        data.setNumTwo(lineBaseList.stream()
                .filter(x -> 1 == x.getComFlag()).map(LineDevGetDTO::getDevId).distinct().count());
        data.setNumTwoList(lineBaseList.stream()
                .filter(x -> 1 == x.getComFlag()).map(LineDevGetDTO::getPointId).distinct().collect(Collectors.toList()));
        statisticsData.add(data);
        data = new GridDiagramVO.StatisticsData();
        data.setNumOne(lineBaseList.stream()
                .filter(x -> 1 == x.getIsUpToGrid()).map(LineDevGetDTO::getDevId).distinct().count());
        data.setNumOneList(lineBaseList.stream()
                .filter(x -> 1 == x.getIsUpToGrid()).map(LineDevGetDTO::getPointId).distinct().collect(Collectors.toList()));
        data.setNumTwo(lineBaseList.stream()
                .filter(x -> 1 == x.getComFlag() && 1 == x.getIsUpToGrid()).map(LineDevGetDTO::getDevId).distinct().count());
        data.setNumTwoList(lineBaseList.stream()
                .filter(x -> 1 == x.getComFlag() && 1 == x.getIsUpToGrid()).map(LineDevGetDTO::getPointId).distinct().collect(Collectors.toList()));
        gwStatisticsData.add(data);

    }

    //在运-在线
    private Boolean getIsUpToGrid(Integer type, LineDevGetDTO lineDevGetDTO, String voltageId) {
        //0：全部 1：国网上送监测点
        if (type == 0) {
            return voltageId.equals(lineDevGetDTO.getVoltageLevel());
        } else {
            return voltageId.equals(lineDevGetDTO.getVoltageLevel()) && 1 == lineDevGetDTO.getIsUpToGrid();
        }
    }

}
