package com.njcn.prepare.harmonic.service.influxdb.impl;

import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.njcn.common.utils.HarmonicTimesUtil;
import com.njcn.common.utils.PubUtils;
import com.njcn.device.biz.commApi.CommLineClient;
import com.njcn.device.biz.commApi.CommTerminalGeneralClient;
import com.njcn.device.biz.pojo.dto.LineDevGetDTO;
import com.njcn.device.biz.pojo.dto.PollutionLineInfoDTO;
import com.njcn.device.biz.pojo.po.Overlimit;
import com.njcn.event.api.EventDetailFeignClient;
import com.njcn.event.pojo.dto.EventCount;
import com.njcn.harmonic.pojo.vo.IntegrityVO;
import com.njcn.influx.constant.InfluxDbSqlConstant;
import com.njcn.influx.imapper.DataHarmRateVMapper;
import com.njcn.influx.imapper.DataVMapper;
import com.njcn.influx.pojo.constant.InfluxDBTableConstant;
import com.njcn.influx.pojo.po.DataHarmRateV;
import com.njcn.influx.pojo.po.DataV;
import com.njcn.influx.query.InfluxQueryWrapper;
import com.njcn.prepare.harmonic.mapper.mysql.EventMapper;
import com.njcn.prepare.harmonic.pojo.bo.excel.*;
import com.njcn.prepare.harmonic.service.influxdb.IPollutionCalc;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Field;
import java.time.Instant;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Service
@RequiredArgsConstructor
@Slf4j
public class PollutionCalcImpl implements IPollutionCalc {

    private final CommTerminalGeneralClient commTerminalGeneralClient;

    private final CommLineClient commLineClient;

    private final DataVMapper dataVMapper;

    private final DataHarmRateVMapper dataHarmRateVMapper;

    private final EventDetailFeignClient eventDetailFeignClient;

    private final EventMapper eventMapper;

    /**
     * 监测点污染值计算，谐波电压&谐波电流
     * 1、获取所有监测点；
     * 2、根据指标获取对应的污染值，目前仅做谐波电压；
     * 注：目前仅支持获取昨天的
     */
    @Override
    public void calcAllLineValue() {
//        LocalDate yesterday = LocalDate.now().minusDays(1);
//        String yesterdayDate = LocalDateTimeUtil.format(LocalDateTimeUtil.beginOfDay(LocalDateTimeUtil.of(yesterday)), DatePattern.NORM_DATE_PATTERN);

        List<String> lineIdList = commTerminalGeneralClient.getRunMonitorIds().getData();
        // List<String> lineIdList = Stream.of("2886ec28f6ea8b0444ce18849f2e5736").collect(Collectors.toList());
        // 获取所有监测点的暂态数据 由于暂态事件较少，暂时查询最近30天的
//        LocalDate last30Day = LocalDate.now().minusDays(31);
//        String startDate = LocalDateTimeUtil.format(LocalDateTimeUtil.beginOfDay(LocalDateTimeUtil.of(last30Day)), DatePattern.NORM_DATE_PATTERN);
        String startDate = "2025-02-10";
        String yesterdayDate = "2025-03-10";

        List<EventCount> eventCounts = getEventCount(lineIdList, startDate, yesterdayDate);
        Map<String, EventCount> eventMap = eventCounts.stream().collect(Collectors.toMap(EventCount::getLineId, pojo -> pojo));
        // 获取所有监测点的元信息
        List<PollutionLineInfoDTO> lineInfoDTOList = commLineClient.getPollutionLineInfo(lineIdList).getData();
//        String beginDay = LocalDateTimeUtil.format(LocalDateTimeUtil.beginOfDay(LocalDateTimeUtil.of(yesterday)), DatePattern.NORM_DATETIME_PATTERN);
//        String endDay = LocalDateTimeUtil.format(LocalDateTimeUtil.endOfDay(LocalDateTimeUtil.of(yesterday)), DatePattern.NORM_DATETIME_PATTERN);
        String beginDay = "2025-02-10 00:00:00";
        String endDay = "2025-03-10 23:59:59";
        //获取监测点的数据完整性
        List<IntegrityVO> integrityList = getIntegrity(startDate, yesterdayDate);
        Map<String, IntegrityVO> integrityMap = integrityList.stream().collect(Collectors.toMap(IntegrityVO::getId, pojo -> pojo));
        //获取装置在线率
        List<IntegrityVO> onlineRateList = getOnlineRate(startDate, yesterdayDate);
        Map<String, IntegrityVO> onlineRateMap = onlineRateList.stream().collect(Collectors.toMap(IntegrityVO::getId, pojo -> pojo));
        List<LinePollution> linePollutionList = new ArrayList<>();
        long startTime = System.currentTimeMillis();
        if (CollUtil.isNotEmpty(lineIdList)) {
            System.out.println("总共" + lineIdList.size() + "个监测点参与污染值计算，开始执行");
            // 获取谐波电压数据&总畸变率&越限限值计算基础污染值
            for (int i = 0; i < lineIdList.size(); i++) {
                String lineId = lineIdList.get(i);
                LinePollution linePollution = new LinePollution();
                linePollution.setLineId(lineId);
                //获取监测点数据完整性
                IntegrityVO vo = integrityMap.get(lineId);
                linePollution.setIntegrity(Objects.isNull(vo) ? 0.0 : vo.getIntegrityData());
                //获取监测点限值
                Overlimit overlimit = commTerminalGeneralClient.getOverLimitData(lineId).getData();
                LineDevGetDTO lineDetailData = commTerminalGeneralClient.getMonitorDetail(lineId).getData();
                if (Objects.isNull(overlimit) || Objects.isNull(lineDetailData)) {
                    // 如果没有查到限值跳过，后期需要记录这种异常
                    continue;
                }
                linePollution.setLineName(lineDetailData.getPointName());
                linePollution.setInterval(lineDetailData.getInterval());
                // 计算谐波电压的污染值
                linePollution.setVHarmonicValue(PubUtils.doubleRound(2, calcVAllPollutionValue(linePollution, overlimit, beginDay, endDay) * linePollution.getInterval()) + "");
                // 获取暂态数据
//                statisticsEvent(linePollution);
                BeanUtil.copyProperties(eventMap.get(lineId), linePollution);
                //获取该监测点其他元信息
                Optional<PollutionLineInfoDTO> any = lineInfoDTOList.stream().filter(item -> item.getLineId().equals(lineId)).findAny();
                if (any.isPresent()) {
                    PollutionLineInfoDTO data = any.get();
                    BeanUtil.copyProperties(data, linePollution, true);
//                    if (data.getComFlag() == 0) {
//                        linePollution.setRemark("终端通讯状态为中断！");
//                    }
                    IntegrityVO vo2 = onlineRateMap.get(data.getDeviceId());
                    linePollution.setOnlineRate(Objects.isNull(vo2) ? 0.0 : vo2.getIntegrityData());
                }
                linePollutionList.add(linePollution);
            }
        }
        List<LinePollution> finalLinePollutionList = new ArrayList<>(linePollutionList);
        // 全部监测点计算完毕后根据污染值从大到小进行排序
        finalLinePollutionList.sort(Comparator.comparingDouble(o -> Double.parseDouble(o.getVHarmonicValue())));
        Collections.reverse(finalLinePollutionList);

        // 监测点的污染值计算完毕后，输出到指定目录。目前目录是写死的，待后期调整成配置可供用户选择下载。todo...
        // 导出监测点污染值
        String folder = "c:\\njcn";
        File file = new File(folder);
        if (!file.exists()) {
            boolean mkdirs = file.mkdirs();
            if (!mkdirs) {
                System.out.println("无法创建文件夹");
                return;
            }
        }
        String fileName = folder + "\\监测点谐波电压污染值" + yesterdayDate + ".xlsx";
        ExportParams exportParams = new ExportParams();
        exportLinePollution(exportParams, LinePollution.class, finalLinePollutionList, fileName);

        // 处理干扰源用户的报告
        List<LinePollution> loadTypeLineList = new ArrayList<>(linePollutionList);
        /**
         * 1、首先过滤：重要变电站、一类变电站、跨省计量关点 todo...待优化
         * 2、过滤后，以监测对象分组统计数据有多个测点的需要出结果
         */
        List<String> loadTypeSubStation = Stream.of("重要变电站", "一类变电站", "跨省计量关点").collect(Collectors.toList());
        loadTypeLineList = loadTypeLineList.stream().filter(item -> !loadTypeSubStation.contains(item.getLoadType())).collect(Collectors.toList());
        // 监测对象分组
        Map<String, List<LinePollution>> loadTypeMap = loadTypeLineList.stream().collect(Collectors.groupingBy(LinePollution::getObjName));
        List<ObjPollution> objPollutions = new ArrayList<>();
        Set<String> objNameSet = loadTypeMap.keySet();
        for (String objName : objNameSet) {
            ObjPollution objPollution = new ObjPollution();
            List<LinePollution> linePollutions = loadTypeMap.get(objName);
            objPollution.setObjName(linePollutions.get(0).getObjName());
            objPollution.setLoadType(linePollutions.get(0).getLoadType());
//            objPollution.setBusinessType(linePollutions.get(0).getBusinessType());
            // 求出平均污染值
            double objValue = linePollutions.stream()
                    .mapToDouble(o -> Double.parseDouble(o.getVHarmonicValue()))
                    .sum();
            objPollution.setObjValue(PubUtils.doubleRound(2, objValue) + "");

            // 处理该监测对象下面监测点的信息
            List<LoadTypeLineItemPollution> loadTypeLineItemPollutions = new ArrayList<>();
            for (LinePollution linePollution : linePollutions) {
                LoadTypeLineItemPollution loadTypeLineItemPollution = new LoadTypeLineItemPollution();
                BeanUtil.copyProperties(linePollution, loadTypeLineItemPollution, true);
                loadTypeLineItemPollutions.add(loadTypeLineItemPollution);
            }
            objPollution.setLineItemPollutionList(loadTypeLineItemPollutions);
            objPollutions.add(objPollution);
        }
        fileName = folder + "\\用户谐波电压污染值" + yesterdayDate + ".xlsx";
        exportParams = new ExportParams();
        // 排序
        objPollutions.sort(Comparator.comparingDouble(o -> Double.parseDouble(o.getObjValue())));
        Collections.reverse(objPollutions);
        exportLinePollution(exportParams, ObjPollution.class, objPollutions, fileName);

        // 整合变电站待导出的数据
        List<GdPollution> gdPollutionList = new ArrayList<>();
        // 以供电公司分组
        Map<String, List<LinePollution>> gdMap = linePollutionList.stream()
                .collect(Collectors.groupingBy(LinePollution::getGdName));
        // 同一供电公司以变电站分组
        Set<String> gdNameSet = gdMap.keySet();
        for (String gdName : gdNameSet) {
            // 初始化gd实体
            GdPollution gdPollution = new GdPollution();
            gdPollution.setGdName(gdName);
            List<LinePollution> gdLinePollution = gdMap.get(gdName);
            // 以变电站分组
            Map<String, List<LinePollution>> subMap = gdLinePollution.stream()
                    .collect(Collectors.groupingBy(LinePollution::getSubStationName));
            Set<String> subNameMap = subMap.keySet();
            List<SubstationPollution> substationPollutions = new ArrayList<>();
            for (String subName : subNameMap) {
                // 初始化变电站实体
                SubstationPollution substationPollution = new SubstationPollution();
                substationPollution.setSubStationName(subName);
                List<LinePollution> subLinePollution = subMap.get(subName);
                // 需要区分电网侧、非电网侧
                Map<String, List<LinePollution>> powerFlagLinePollution = subLinePollution.stream().collect(Collectors.groupingBy(LinePollution::getPowerFlag));

                List<PowerFlagPollution> powerFlagPollutionList = new ArrayList<>();
                // 电网侧
                List<LinePollution> temp = powerFlagLinePollution.get("电网侧");
                PowerFlagPollution powerFlagPollution1 = new PowerFlagPollution();
                powerFlagPollution1.setPowerFlag("电网侧");
                List<LineItemPollution> lineItemPollutionList1 = new ArrayList<>();
                if (CollUtil.isNotEmpty(temp)) {
                    // 计算电网侧下所有监测点平均污染值
                    double subValue = temp.stream()
                            .mapToDouble(o -> Double.parseDouble(o.getVHarmonicValue()))
                            .average()
                            .orElse(0.0);
                    // 电网侧污染值
                    powerFlagPollution1.setPowerValue(PubUtils.doubleRound(2, subValue) + "");
                    // 设备信息
                    for (LinePollution linePollution : temp) {
                        LineItemPollution lineItemPollution = new LineItemPollution();
                        BeanUtil.copyProperties(linePollution, lineItemPollution, true);
                        lineItemPollutionList1.add(lineItemPollution);
                    }
                } else {
                    // 仅有非电网侧时，电网侧赋予空置
                    LineItemPollution lineItemPollution = new LineItemPollution();
                    lineItemPollutionList1.add(lineItemPollution);
                }
                // 设备信息注入监测位置对象中
                powerFlagPollution1.setLineItemPollutionList(lineItemPollutionList1);
                powerFlagPollutionList.add(powerFlagPollution1);


                // 非电网侧
                List<LinePollution> temp1 = powerFlagLinePollution.get("非电网侧");
                PowerFlagPollution powerFlagPollution2 = new PowerFlagPollution();
                powerFlagPollution2.setPowerFlag("非电网侧");
                List<LineItemPollution> lineItemPollutionList2 = new ArrayList<>();
                if (CollUtil.isNotEmpty(temp1)) {
                    // 计算非电网侧下所有监测点平均污染值
                    double subValue = temp1.stream()
                            .mapToDouble(o -> Double.parseDouble(o.getVHarmonicValue()))
                            .average()
                            .orElse(0.0);
                    powerFlagPollution2.setPowerValue(PubUtils.doubleRound(2, subValue) + "");
                    for (LinePollution linePollution : temp1) {
                        LineItemPollution lineItemPollution = new LineItemPollution();
                        BeanUtil.copyProperties(linePollution, lineItemPollution, true);
                        lineItemPollutionList2.add(lineItemPollution);
                    }
                } else {
                    // 仅有非电网侧时，电网侧赋予空置
                    LineItemPollution lineItemPollution = new LineItemPollution();
                    lineItemPollutionList2.add(lineItemPollution);
                }
                // 设备信息注入监测位置对象中
                powerFlagPollution2.setLineItemPollutionList(lineItemPollutionList2);
                powerFlagPollutionList.add(powerFlagPollution2);

                substationPollution.setPowerFlagPollutionList(powerFlagPollutionList);
                // 如果电网侧有污染值，就作为变电站的污染值，否则就用非电网侧的污染值作为该变电站污染值
                if (Objects.nonNull(powerFlagPollution1.getPowerValue())) {
                    substationPollution.setSubStationValue(powerFlagPollution1.getPowerValue());
                } else {
                    substationPollution.setSubStationValue(powerFlagPollution2.getPowerValue());
                }
                substationPollutions.add(substationPollution);
            }

            // 针对这个供电公司下的变电站污染值排序
            substationPollutions.sort(Comparator.comparingDouble(o -> Double.parseDouble(o.getSubStationValue())));
            Collections.reverse(substationPollutions);
//            List<SubstationPollution> finalSubstation = substationPollutions.stream().sorted((Comparator.comparingDouble(SubstationPollution::getSubStationValue))
//                            .reversed())
//                    .collect(Collectors.toList());
            gdPollution.setSubstationPollutionList(substationPollutions);
            gdPollutionList.add(gdPollution);
        }
        fileName = folder + "\\变电站谐波电压污染值" + yesterdayDate + ".xlsx";
        exportParams = new ExportParams();
        exportLinePollution(exportParams, GdPollution.class, gdPollutionList, fileName);

        long endTime = System.currentTimeMillis();
        long time = (endTime - startTime) / 1000;
        System.out.println("程序执行完毕，总耗时：" + time + "秒");
    }

    @Override
    public void getDataVByLineId() {
        List<DataVDetail> linePollutionList = new ArrayList<>();
        String yesterdayDate = "2025-03-10";
        String beginDay = "2025-02-10 00:00:00";
        String endDay = "2025-03-10 23:59:59";
        List<String> lineIdList = Arrays.asList("123","456","789");
        List<PollutionLineInfoDTO> lineInfoDTOList = commLineClient.getPollutionLineInfo(lineIdList).getData();
        if (CollUtil.isNotEmpty(lineIdList)) {
            // 获取谐波电压数据 电压总谐波畸变率 + 2—50次谐波电压含有率
            for (int i = 0; i < lineIdList.size(); i++) {
                String lineId = lineIdList.get(i);
                DataVDetail linePollution = new DataVDetail();
                linePollution.setLineId(lineId);
                //获取监测点限值
                //Overlimit overlimit = commTerminalGeneralClient.getOverLimitData(lineId).getData();
                LineDevGetDTO lineDetailData = commTerminalGeneralClient.getMonitorDetail(lineId).getData();
                linePollution.setLineName(lineDetailData.getPointName());
                //获取该监测点其他元信息
                Optional<PollutionLineInfoDTO> any = lineInfoDTOList.stream().filter(item -> item.getLineId().equals(lineId)).findAny();
                if (any.isPresent()) {
                    PollutionLineInfoDTO data = any.get();
                    BeanUtil.copyProperties(data, linePollution, true);
                }
                linePollutionList = getData(linePollution,beginDay,endDay);
            }
        }

        List<DataVDetail> finalLinePollutionList = new ArrayList<>(linePollutionList);
        // 全部监测点计算完毕后按时间排序
        finalLinePollutionList.sort(Comparator.comparing(DataVDetail::getTime).thenComparing(DataVDetail::getPhaseType));
        Collections.reverse(finalLinePollutionList);

        // 监测点的污染值计算完毕后，输出到指定目录。目前目录是写死的，待后期调整成配置可供用户选择下载。todo...
        // 导出监测点污染值
        String folder = "c:\\njcn";
        File file = new File(folder);
        if (!file.exists()) {
            boolean mkdirs = file.mkdirs();
            if (!mkdirs) {
                System.out.println("无法创建文件夹");
                return;
            }
        }
        String fileName = folder + "\\各地市谐波电压数据详情" + yesterdayDate + ".xlsx";
        ExportParams exportParams = new ExportParams();
        exportLinePollution(exportParams, LinePollution.class, finalLinePollutionList, fileName);
    }


    /**
     * 输出下载文件
     *
     * @param exportParams excel配置信息
     * @param pojoClass    映射对象
     * @param dataSet      数据集
     * @param fileName     文件名
     */
    private void exportLinePollution(ExportParams exportParams, Class<?> pojoClass, Collection<?> dataSet, String fileName) {
        Workbook workbook = ExcelExportUtil.exportExcel(exportParams, pojoClass, dataSet);
        File outFile = new File(fileName);
        try (FileOutputStream fos = new FileOutputStream(outFile)) {
            workbook.write(fos);
            System.out.println("文档输出成功");
        } catch (IOException e) {
            System.out.println("文档输出异常");
        } finally {
            try {
                workbook.close();
            } catch (IOException exception) {
                System.out.println("关闭通道失败");
            }
        }
    }


    /**
     * 获取规定时间内谐波电压数据
     * 谐波电压包含 电压总谐波畸变率 + 2~50次谐波电压含有率
     * @param linePollution 监测点信息
     */
    private List<DataVDetail> getData(DataVDetail linePollution, String startTime, String endTime) {
        List<DataVDetail> linePollutionList = new ArrayList<>();

        InfluxQueryWrapper dataVQueryWrapper = new InfluxQueryWrapper(DataV.class);
        dataVQueryWrapper.select(DataV::getVThd)
                .select(DataV::getPhaseType)
                .eq(DataV::getLineId, linePollution.getLineId())
                .eq(DataV::getValueType, InfluxDbSqlConstant.CP95)
                .ne(DataV::getPhaseType, InfluxDBTableConstant.PHASE_TYPE_T)
                .between(DataV::getTime, startTime, endTime);
        List<DataV> vthResultList = dataVMapper.getStatisticsByWraper(dataVQueryWrapper);

        InfluxQueryWrapper dataVQueryWrapper2 = new InfluxQueryWrapper(DataHarmRateV.class);
        dataVQueryWrapper2.samePrefixAndSuffix(InfluxDbSqlConstant.V, "", HarmonicTimesUtil.harmonicTimesList(2, 50, 1));
        dataVQueryWrapper2.eq(DataHarmRateV::getLineId, linePollution.getLineId())
                .eq(DataHarmRateV::getValueType, InfluxDbSqlConstant.CP95)
                .ne(DataHarmRateV::getPhaseType, InfluxDBTableConstant.PHASE_TYPE_T)
                .between(DataHarmRateV::getTime, startTime, endTime);
        List<DataHarmRateV> vthResultList2 = dataHarmRateVMapper.getStatisticsByWraper(dataVQueryWrapper2);

        if (CollUtil.isNotEmpty(vthResultList) && CollUtil.isNotEmpty(vthResultList2)) {
            Map<Instant,List<DataV>> map1 = vthResultList.stream().collect(Collectors.groupingBy(DataV::getTime));
            Map<Instant, Map<String, DataV>> map1ByPhase = map1.entrySet().stream()
                    .collect(Collectors.toMap(
                            Map.Entry::getKey,
                            entry -> entry.getValue().stream()
                                    .collect(Collectors.toMap(DataV::getPhaseType, dataV -> dataV))
                    ));
            Map<Instant,List<DataHarmRateV>> map2 = vthResultList2.stream().collect(Collectors.groupingBy(DataHarmRateV::getTime));
            Map<Instant, Map<String, DataHarmRateV>> map2ByPhase = map2.entrySet().stream()
                    .collect(Collectors.toMap(
                            Map.Entry::getKey,
                            entry -> entry.getValue().stream()
                                    .collect(Collectors.toMap(DataHarmRateV::getPhaseType, dataHarmRateV -> dataHarmRateV))
                    ));
            // 获取两个 Map 的时间交集
            Set<Instant> commonTimes = new HashSet<>(map1.keySet());
            commonTimes.retainAll(map2.keySet());
            for (Instant time : commonTimes) {
                Map<String, DataV> phaseData1 = map1ByPhase.get(time);
                Map<String, DataHarmRateV> phaseData2 = map2ByPhase.get(time);
                // 遍历 phaseData1 的所有 phaseType
                phaseData1.forEach((phaseType, dataV) -> {
                    // 在 phaseData2 中查找匹配的 phaseType
                    DataHarmRateV harmRateV = phaseData2.get(phaseType);
                    if (harmRateV != null) {
                        DataVDetail detail = new DataVDetail();
                        BeanUtil.copyProperties(linePollution,detail);
                        detail.setTime(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(time));
                        detail.setPhaseType(phaseType); // 设置相别
                        detail.setVThd(dataV.getVThd()); // 设置 DataV 的值
                        detail.setV2(harmRateV.getV2());
                        detail.setV3(harmRateV.getV3());
                        detail.setV4(harmRateV.getV4());
                        detail.setV5(harmRateV.getV5());
                        detail.setV6(harmRateV.getV6());
                        detail.setV7(harmRateV.getV7());
                        detail.setV8(harmRateV.getV8());
                        detail.setV9(harmRateV.getV9());
                        detail.setV10(harmRateV.getV10());
                        detail.setV11(harmRateV.getV11());
                        detail.setV12(harmRateV.getV12());
                        detail.setV13(harmRateV.getV13());
                        detail.setV14(harmRateV.getV14());
                        detail.setV15(harmRateV.getV15());
                        detail.setV16(harmRateV.getV16());
                        detail.setV17(harmRateV.getV17());
                        detail.setV18(harmRateV.getV18());
                        detail.setV19(harmRateV.getV19());
                        detail.setV20(harmRateV.getV20());
                        detail.setV21(harmRateV.getV21());
                        detail.setV22(harmRateV.getV22());
                        detail.setV23(harmRateV.getV23());
                        detail.setV24(harmRateV.getV24());
                        detail.setV25(harmRateV.getV25());
                        detail.setV26(harmRateV.getV26());
                        detail.setV27(harmRateV.getV27());
                        detail.setV28(harmRateV.getV28());
                        detail.setV29(harmRateV.getV29());
                        detail.setV30(harmRateV.getV30());
                        detail.setV31(harmRateV.getV31());
                        detail.setV32(harmRateV.getV32());
                        detail.setV33(harmRateV.getV33());
                        detail.setV34(harmRateV.getV34());
                        detail.setV35(harmRateV.getV35());
                        detail.setV36(harmRateV.getV36());
                        detail.setV37(harmRateV.getV37());
                        detail.setV38(harmRateV.getV38());
                        detail.setV39(harmRateV.getV39());
                        detail.setV40(harmRateV.getV40());
                        detail.setV41(harmRateV.getV41());
                        detail.setV42(harmRateV.getV42());
                        detail.setV43(harmRateV.getV43());
                        detail.setV44(harmRateV.getV44());
                        detail.setV45(harmRateV.getV45());
                        detail.setV46(harmRateV.getV46());
                        detail.setV47(harmRateV.getV47());
                        detail.setV48(harmRateV.getV48());
                        detail.setV49(harmRateV.getV49());
                        detail.setV50(harmRateV.getV50());
                        linePollutionList.add(detail);
                    }
                });
            }
        }
        return linePollutionList;
    }

    /**
     * 计算谐波电压的污染值，包含了电压总畸变率和谐波电压2~25次
     */
    private double calcVAllPollutionValue(LinePollution linePollution, Overlimit overlimit, String startTime, String endTime) {
        //最大值
        InfluxQueryWrapper dataVQueryWrapper = new InfluxQueryWrapper(DataV.class);
        dataVQueryWrapper.eq(DataV::getLineId, linePollution.getLineId())
                .eq(DataV::getValueType, InfluxDbSqlConstant.CP95)
                .ne(DataHarmRateV::getPhaseType, InfluxDBTableConstant.PHASE_TYPE_T)
                .max(DataV::getVThd)
                .groupBy("time(" + linePollution.getInterval() + "m)")
                .between(DataV::getTime, startTime, endTime);
        List<DataV> vthResultList = dataVMapper.getStatisticsByWraper(dataVQueryWrapper);
        // 计算时间范围内指标越限百分比
        // 总畸变率的限值
        List<Double> thdValueList = vthResultList.stream().map(DataV::getVThd).collect(Collectors.toList());
        double thdPollutionValue = calcPollutionValue(overlimit.getUbalance(), thdValueList);
        // 谐波电压2~50次的数据获取并计算
        InfluxQueryWrapper harmRateVQueryWrapper = new InfluxQueryWrapper(DataHarmRateV.class);
        harmRateVQueryWrapper.maxSamePrefixAndSuffix(InfluxDbSqlConstant.V, "", HarmonicTimesUtil.harmonicTimesList(2, 50, 1));
        harmRateVQueryWrapper.eq(DataHarmRateV::getLineId, linePollution.getLineId())
                .eq(DataHarmRateV::getValueType, InfluxDbSqlConstant.CP95)
                .ne(DataHarmRateV::getPhaseType, InfluxDBTableConstant.PHASE_TYPE_T)
                .groupBy("time(" + linePollution.getInterval() + "m)")
                .between(DataHarmRateV::getTime, startTime, endTime);
        List<DataHarmRateV> dataHarmRateVList = dataHarmRateVMapper.getStatisticsByWraper(harmRateVQueryWrapper);
        double harmRateVPollutionValue = calcHarmRateVPollutionValue(overlimit, dataHarmRateVList);
        return thdPollutionValue + harmRateVPollutionValue;
    }

    /**
     * 计算谐波电压2~50的越限污染值
     *
     * @param overlimit         限值
     * @param dataHarmRateVList 2~50次的谐波电压值
     * @return 谐波电压污染值
     */
    private double calcHarmRateVPollutionValue(Overlimit overlimit, List<DataHarmRateV> dataHarmRateVList) {
        List<Double> pollutionValue = new ArrayList<>();
        // 2次
        for (int i = 2; i < 51; i++) {
            Float limitValue = getValueByFieldName(overlimit, "uharm" + i);
            int finalI = i;
            List<Double> valueList = dataHarmRateVList.stream().map(item -> {
                Float valueByFieldName = getValueByFieldName(item, "v" + finalI);
                if (Objects.isNull(valueByFieldName)) {
                    return 0.0;
                } else {
                    return (double) valueByFieldName;
                }
            }).collect(Collectors.toList());
            pollutionValue.add(calcPollutionValue(limitValue, valueList));
        }
        return pollutionValue.stream().mapToDouble(Double::doubleValue).sum();
    }

    /**
     * 获取当前组数据的污染值
     *
     * @param limit     限值
     * @param valueList 参考数据
     * @return 污染值
     */
    private double calcPollutionValue(Float limit, List<Double> valueList) {
        double pollutionValue = 0;
        // 没有限值的直接返回
        if (Objects.isNull(limit) || limit == 0.0f) {
            return pollutionValue;
        }
        // 计算每个数值的越限百分比MOP
        List<Double> overLimitPercentList = valueList.stream().map(value -> {
            if (Objects.isNull(value)) {
                return 0.0;
            }
            return value * 100 / limit;
        }).collect(Collectors.toList());
        // 计算每个越限百分比对应的污染值，并求和返回
        if (CollUtil.isNotEmpty(overLimitPercentList)) {
            pollutionValue = overLimitPercentList.stream().map(item -> {
                double value = 0;
                if (item >= 100.0 && item < 120.0) {
                    value = 0.1;
                } else if (item >= 120.0 && item < 160.0) {
                    value = 0.2;
                } else if (item >= 160.0 && item < 200.0) {
                    value = 0.3;
                } else if (item >= 200.0) {
                    value = 0.4;
                }
                return value;
            }).mapToDouble(Double::doubleValue).sum();
        }
        return pollutionValue;
    }

    /**
     * 根据标记获取属性对应的值
     *
     * @return 值
     */
    public static Float getValueByFieldName(Object obj, String fieldName) {
        try {
            Field field = obj.getClass().getDeclaredField(fieldName);
            field.setAccessible(true);
            Object val = field.get(obj);
            if (Objects.isNull(val)) {
                return null;
            }
            if (val instanceof Double) {
                Double doubleValue = (Double) val;
                return doubleValue.floatValue();
            }
            return (float) field.get(obj);
        } catch (NoSuchFieldException | IllegalAccessException e) {
            return 0.0f;
        }
    }

    public List<EventCount> getEventCount(List<String> ids, String startDate, String endDate) {
        DateTime startTime = DateUtil.beginOfDay(DateUtil.parse(startDate));
        DateTime endTime = DateUtil.endOfDay(DateUtil.parse(endDate));
        List<EventCount> eventCounts = eventMapper.getEventCount(startTime, endTime);
        Map<String, EventCount> eventMap = eventCounts.stream().collect(Collectors.toMap(EventCount::getLineId, pojo -> pojo));
        List<EventCount> eventCountList = new ArrayList<>();
        for (String id : ids) {
            EventCount eventCountTemp = eventMap.get(id);
            if (Objects.isNull(eventCountTemp)) {
                eventCountTemp = new EventCount(id);
            }
            eventCountList.add(eventCountTemp);
        }
        return eventCountList;
    }

    public List<IntegrityVO> getIntegrity(String startDate, String endDate) {
        DateTime startTime = DateUtil.beginOfDay(DateUtil.parse(startDate));
        DateTime endTime = DateUtil.endOfDay(DateUtil.parse(endDate));
        return eventMapper.getIntegrity(startTime, endTime);
    }

    public List<IntegrityVO> getOnlineRate(String startDate, String endDate) {
        DateTime startTime = DateUtil.beginOfDay(DateUtil.parse(startDate));
        DateTime endTime = DateUtil.endOfDay(DateUtil.parse(endDate));
        return eventMapper.getOnlineRate(startTime, endTime);
    }

}
