package com.njcn.harmonic.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.lang.Pair;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.njcn.csdevice.api.CsLineFeignClient;
import com.njcn.csdevice.pojo.po.CsLinePO;
import com.njcn.dataProcess.param.LineCountEvaluateParam;
import com.njcn.dataProcess.pojo.dto.AbnormalData;
import com.njcn.dataProcess.pojo.dto.DataLimitRateDetailTimeDto;
import com.njcn.device.biz.pojo.po.Overlimit;
import com.njcn.device.pq.api.OverLimitClient;
import com.njcn.harmonic.pojo.param.LimitCalendarQueryParam;
import com.njcn.harmonic.pojo.param.LimitExtentDayQueryParam;
import com.njcn.harmonic.pojo.param.LimitExtentQueryParam;
import com.njcn.harmonic.pojo.param.LimitProbabilityQueryParam;
import com.njcn.harmonic.pojo.po.day.RStatLimitRateDetailDPO;
import com.njcn.harmonic.pojo.vo.LimitCalendarVO;
import com.njcn.harmonic.pojo.vo.LimitExtentVO;
import com.njcn.harmonic.pojo.vo.LimitProbabilityVO;
import com.njcn.harmonic.pojo.vo.LimitTimeProbabilityVO;
import com.njcn.harmonic.mapper.RStatLimitRateDetailDMapper;
import com.njcn.harmonic.service.IRStatLimitRateDService;
import com.njcn.harmonic.service.IRStatLimitRateDetailDService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

@DS("sjzx")
@RequiredArgsConstructor
@Service
public class RStatLimitRateDetailDServiceImpl extends ServiceImpl<RStatLimitRateDetailDMapper, RStatLimitRateDetailDPO> implements IRStatLimitRateDetailDService {

    private final CsLineFeignClient csLineFeignClient;
    private final OverLimitClient overLimitClient;
    private final IRStatLimitRateDService rStatLimitRateDService;

    private final DecimalFormat df = new DecimalFormat("#0.00");

    static Map<String, String> indexMap = new HashMap<>();
    static List<List<Integer>> timePeriodList = new ArrayList<>();
    static List<List<Integer>> extentPeriodList = new ArrayList<>();

    static {
        indexMap.put("flicker", "闪变");
        indexMap.put("uharm", "谐波电压");
        indexMap.put("iharm", "谐波电流");
        indexMap.put("ubalance", "三相电压不平衡度");
        indexMap.put("voltageDev", "电压偏差");
        indexMap.put("freqDev", "频率偏差");

        timePeriodList.add(Arrays.asList(0, 8));
        timePeriodList.add(Arrays.asList(8, 12));
        timePeriodList.add(Arrays.asList(12, 14));
        timePeriodList.add(Arrays.asList(14, 18));
        timePeriodList.add(Arrays.asList(18, 24));

        extentPeriodList.add(Arrays.asList(0, 20));
        extentPeriodList.add(Arrays.asList(20, 40));
        extentPeriodList.add(Arrays.asList(40, 60));
        extentPeriodList.add(Arrays.asList(60, 80));
        extentPeriodList.add(Arrays.asList(80, 100));
    }

    @Override
    public List<LimitExtentVO> limitExtentData(LimitExtentQueryParam param) {
        List<LimitExtentVO> result = new ArrayList<>();
        LimitExtentVO flicker = new LimitExtentVO();
        flicker.setCode("flicker");
        flicker.setName(indexMap.get(flicker.getCode()));
        LimitExtentVO uharm = new LimitExtentVO();
        uharm.setCode("uharm");
        uharm.setName(indexMap.get(uharm.getCode()));
        LimitExtentVO iharm = new LimitExtentVO();
        iharm.setCode("iharm");
        iharm.setName(indexMap.get(iharm.getCode()));
        LimitExtentVO voltageDev = new LimitExtentVO();
        voltageDev.setCode("voltageDev");
        voltageDev.setName(indexMap.get(voltageDev.getCode()));
        LimitExtentVO ubalance = new LimitExtentVO();
        ubalance.setCode("ubalance");
        ubalance.setName(indexMap.get(ubalance.getCode()));
        List<RStatLimitRateDetailDPO> detailList = this.list(new LambdaQueryWrapper<RStatLimitRateDetailDPO>()
                .ge(StrUtil.isNotBlank(param.getSearchBeginTime()), RStatLimitRateDetailDPO::getTime, param.getSearchBeginTime())
                .le(StrUtil.isNotBlank(param.getSearchEndTime()), RStatLimitRateDetailDPO::getTime, param.getSearchEndTime())
                .orderByAsc(RStatLimitRateDetailDPO::getTime)
        );
        if (CollUtil.isNotEmpty(detailList)) {
            List<String> lineIds = detailList.stream().map(RStatLimitRateDetailDPO::getLineId).distinct().collect(Collectors.toList());
            List<Overlimit> overlimitList = overLimitClient.getOverLimitByLineIds(lineIds).getData();

            Map<String, Pair<Float, RStatLimitRateDetailDPO>> findResult = findMaxValueHandle(detailList);
            // 闪变
            Pair<Float, RStatLimitRateDetailDPO> flickerResult = findResult.get(flicker.getCode());
            setLimitExtentInfo(flicker, flickerResult);
            // 电压偏差
            Pair<Float, RStatLimitRateDetailDPO> voltageDevResult = findResult.get(voltageDev.getCode());
            setLimitExtentInfo(voltageDev, voltageDevResult);
            // 谐波电压
            String uharmKey = findResult.keySet().stream().filter(code -> code.startsWith("uharm")).findFirst().orElse("uharm");
            Pair<Float, RStatLimitRateDetailDPO> uharmResult = findResult.get(uharmKey);
            setLimitExtentInfo(uharm, uharmResult);
            uharm.setCode(uharmKey);
            String iharmKey = findResult.keySet().stream().filter(code -> code.startsWith("iharm")).findFirst().orElse("iharm");
            // 谐波电流
            Pair<Float, RStatLimitRateDetailDPO> iharmResult = findResult.get(iharmKey);
            setLimitExtentInfo(iharm, iharmResult);
            iharm.setCode(iharmKey);
            // 电压三相不平衡
            Pair<Float, RStatLimitRateDetailDPO> ubalanceResult = findResult.get(ubalance.getCode());
            setLimitExtentInfo(ubalance, ubalanceResult);

            if (CollUtil.isNotEmpty(overlimitList)) {
                // 取所有监测点中的最大闪变限值，作为闪变国际限值
                float flickerMaxOverlimit = (float) overlimitList.stream().mapToDouble(Overlimit::getFlicker).max().orElse(0.0F);
                float voltageDevMaxOverlimit = (float) overlimitList.stream().mapToDouble(Overlimit::getVoltageDev).max().orElse(0.0F);
                float ubalanceMaxOverlimit = (float) overlimitList.stream().mapToDouble(Overlimit::getUbalance).max().orElse(0.0F);
                float iharmMaxOverlimit = 0.0F;
                float uharmMaxOverlimit = 0.0F;
                for (Overlimit overlimit : overlimitList) {
                    JSONObject entries = JSONUtil.parseObj(overlimit);
                    for (Map.Entry<String, Object> entry : entries.entrySet()) {
                        String key = entry.getKey();
                        if (key.startsWith("uharm")) {
                            Object value = entry.getValue();
                            if (value instanceof Number) {
                                uharmMaxOverlimit = Math.max(uharmMaxOverlimit, ((Number) value).floatValue());
                            }
                        } else if (key.startsWith("iharm")) {
                            Object value = entry.getValue();
                            if (value instanceof Number) {
                                iharmMaxOverlimit = Math.max(iharmMaxOverlimit, ((Number) value).floatValue());
                            }
                        }

                    }
                }
                flicker.setInternationalValue(flickerMaxOverlimit);
                voltageDev.setInternationalValue(voltageDevMaxOverlimit);
                ubalance.setInternationalValue(ubalanceMaxOverlimit);
                iharm.setInternationalValue(iharmMaxOverlimit);
                uharm.setInternationalValue(uharmMaxOverlimit);
            }
        }
        result.add(flicker);
        result.add(uharm);
        result.add(iharm);
        result.add(voltageDev);
        result.add(ubalance);
        return result;
    }

    @Override
    public JSONArray limitExtentDayData(LimitExtentDayQueryParam param) {
        List<RStatLimitRateDetailDPO> records = this.page(new Page<>(1, 1),
                new LambdaQueryWrapper<RStatLimitRateDetailDPO>()
                        .eq(RStatLimitRateDetailDPO::getLineId, param.getLineId())
                        .eq(RStatLimitRateDetailDPO::getTime, param.getTime())

        ).getRecords();
        String code = param.getCode();
        if (CollUtil.isNotEmpty(records)) {
            RStatLimitRateDetailDPO detail = records.get(0);
            JSONObject entries = JSONUtil.parseObj(detail);
            for (Map.Entry<String, Object> entry : entries.entrySet()) {
                String key = entry.getKey();
                if (key.endsWith("Overtime")) {
                    Object value = entry.getValue();
                    if (StrUtil.equals(code, key)) {
                        return JSONUtil.parseArray(value);
                    } else if (key.startsWith(code)) {
                        return JSONUtil.parseArray(value);
                    }

                }
            }
        }
        return JSONUtil.createArray();
    }

    @Override
    public List<LimitCalendarVO> limitCalendarData(LimitCalendarQueryParam param) {
        List<LimitCalendarVO> result = new ArrayList<>();
        List<RStatLimitRateDetailDPO> detailList = this.list(new LambdaQueryWrapper<RStatLimitRateDetailDPO>()
                .ge(StrUtil.isNotBlank(param.getSearchBeginTime()), RStatLimitRateDetailDPO::getTime, param.getSearchBeginTime())
                .le(StrUtil.isNotBlank(param.getSearchEndTime()), RStatLimitRateDetailDPO::getTime, param.getSearchEndTime())
                .orderByAsc(RStatLimitRateDetailDPO::getTime)
        );
        if (CollUtil.isEmpty(detailList)) {
            return result;
        }
        Map<LocalDate, List<RStatLimitRateDetailDPO>> detailMap = detailList.stream().collect(Collectors.groupingBy(RStatLimitRateDetailDPO::getTime));
        LimitCalendarVO calendarVO;
        for (Map.Entry<LocalDate, List<RStatLimitRateDetailDPO>> entry : detailMap.entrySet()) {
            calendarVO = new LimitCalendarVO();
            LocalDate time = entry.getKey();
            calendarVO.setTime(time);
            int status = 0;
            List<String> items = new ArrayList<>();
            List<RStatLimitRateDetailDPO> dayDetailList = entry.getValue();
            for (RStatLimitRateDetailDPO detail : dayDetailList) {
                String lineId = detail.getLineId();
                List<Overlimit> overlimitList = overLimitClient.getOverLimitByLineIds(Collections.singletonList(lineId)).getData();
                Overlimit overlimit = overlimitList.stream().findFirst().orElse(null);
                JSONObject entries = JSONUtil.parseObj(detail);
                for (Map.Entry<String, Object> dayEntry : entries.entrySet()) {
                    String key = dayEntry.getKey();
                    if (key.endsWith("Overtime")) {
                        Object data = dayEntry.getValue();
                        // 有数据有越限
                        if (ObjectUtil.isNotEmpty(data)) {
                            status = 1;
                            String description = getDescription(key);
                            if (StrUtil.isNotBlank(description) && !items.contains(description)) {
                                items.add(description);
                            }
                            float maxValue = parseMaxValueFromJsonArray(data);
                            if (overlimit != null) {
                                JSONObject overlimitJSON = JSONUtil.parseObj(overlimit);
                                String itemKey = StrUtil.sub(key, 0, key.length() - 8);
                                float limitValue = overlimitJSON.getFloat(itemKey);
                                if (limitValue != 0) {
                                    double overlimitPercent = calculatePercentage(maxValue - limitValue, limitValue);
                                    if (overlimitPercent >= 80) {
                                        status = 2;
                                    }
                                }
                            }
                        }
                    }
                }
            }
            calendarVO.setItems(items);
            calendarVO.setStatus(status);
            result.add(calendarVO);
        }
        result.sort(Comparator.comparing(LimitCalendarVO::getTime));
        return result;
    }

    @Override
    public List<LimitProbabilityVO> limitProbabilityData(LimitProbabilityQueryParam param) {
        List<LimitProbabilityVO> result = new ArrayList<>();
        List<RStatLimitRateDetailDPO> detailList = this.list(new LambdaQueryWrapper<RStatLimitRateDetailDPO>()
                .eq(RStatLimitRateDetailDPO::getLineId, param.getLineId())
                .ge(StrUtil.isNotBlank(param.getSearchBeginTime()), RStatLimitRateDetailDPO::getTime, param.getSearchBeginTime())
                .le(StrUtil.isNotBlank(param.getSearchEndTime()), RStatLimitRateDetailDPO::getTime, param.getSearchEndTime())
                .orderByAsc(RStatLimitRateDetailDPO::getTime)
        );
        CsLinePO linePO = csLineFeignClient.getById(param.getLineId()).getData();
        List<Overlimit> overlimitList = overLimitClient.getOverLimitByLineIds(Collections.singletonList(linePO.getLineId())).getData();
        JSONObject overlimitJSON = null;
        if (CollUtil.isNotEmpty(overlimitList)) {
            overlimitJSON = JSONUtil.parseObj(overlimitList.get(0));
        }
        LimitProbabilityVO probabilityVO;
        for (Map.Entry<String, String> indexEntry : indexMap.entrySet()) {
            String indexCode = indexEntry.getKey();
            probabilityVO = new LimitProbabilityVO();
            probabilityVO.setIndexName(indexEntry.getValue());
            probabilityVO.setIndexCode(indexCode);
            probabilityVO.setLineId(linePO.getLineId());
            probabilityVO.setLineName(linePO.getName());
            // 计算越限程度
            List<Double> extentValuesList = new ArrayList<>();
            for (RStatLimitRateDetailDPO detail : detailList) {
                JSONObject entries = JSONUtil.parseObj(detail);
                for (Map.Entry<String, Object> dayEntry : entries.entrySet()) {
                    String key = dayEntry.getKey();
                    if (key.endsWith("Overtime") && key.startsWith(indexCode)) {
                        double extentValue = 0;
                        Object data = dayEntry.getValue();
                        // 有数据有越限
                        if (ObjectUtil.isNotEmpty(data)) {
                            float maxValue = parseMaxValueFromJsonArray(data);
                            if (overlimitJSON != null) {
                                String itemKey = StrUtil.sub(key, 0, key.length() - 8);
                                double limitValue = overlimitJSON.getDouble(itemKey);
                                if (limitValue != 0) {
                                    extentValue = calculatePercentage(maxValue - limitValue, limitValue);

                                }
                            }
                        }
                        extentValuesList.add(extentValue);
                    }
                }

            }
            List<Map<Integer, Integer>> extentGrades = new ArrayList<>();
            for (int i = 0; i < extentPeriodList.size(); i++) {
                Map<Integer, Integer> grade = new HashMap<>();
                int times = 0;
                for (Double extentValue : extentValuesList) {
                    List<Integer> period = extentPeriodList.get(i);
                    Integer start = period.get(0);
                    Integer end = period.get(1);
                    if (extentValue > start && extentValue <= end) {
                        times++;
                    }
                }
                grade.put(i, times);
                extentGrades.add(grade);
            }
            probabilityVO.setExtentGrades(extentGrades);
            result.add(probabilityVO);
        }
        return result;
    }

    @Override
    public List<LimitTimeProbabilityVO> limitTimeProbabilityData(LimitProbabilityQueryParam param) {

        List<LimitTimeProbabilityVO> result = new ArrayList<>();
        List<RStatLimitRateDetailDPO> detailList = this.list(new LambdaQueryWrapper<RStatLimitRateDetailDPO>()
                .eq(RStatLimitRateDetailDPO::getLineId, param.getLineId())
                .ge(StrUtil.isNotBlank(param.getSearchBeginTime()), RStatLimitRateDetailDPO::getTime, param.getSearchBeginTime())
                .le(StrUtil.isNotBlank(param.getSearchEndTime()), RStatLimitRateDetailDPO::getTime, param.getSearchEndTime())
                .orderByAsc(RStatLimitRateDetailDPO::getTime)
        );
        CsLinePO linePO = csLineFeignClient.getById(param.getLineId()).getData();

        LimitTimeProbabilityVO timeProbabilityVO;
        JSONArray detailJSONArray = null;
        if (CollUtil.isNotEmpty(detailList)) {
            detailJSONArray = JSONUtil.parseArray(detailList);
        }
        for (Map.Entry<String, String> entry : indexMap.entrySet()) {
            String indexCode = entry.getKey();
            for (List<Integer> period : timePeriodList) {
                timeProbabilityVO = new LimitTimeProbabilityVO();
                timeProbabilityVO.setLineId(linePO.getLineId());
                timeProbabilityVO.setLineName(linePO.getName());
                timeProbabilityVO.setIndexName(entry.getValue());
                timeProbabilityVO.setIndexCode(indexCode);
                int start = period.get(0);
                int end = period.get(1);
                timeProbabilityVO.setTimePeriod(start + "时-" + end + "时");
                int times = 0;
                if (CollUtil.isNotEmpty(detailJSONArray)) {
                    for (int i = 0; i < detailJSONArray.size(); i++) {
                        JSONObject detail = detailJSONArray.getJSONObject(i);
                        // 获取包含的指标key
                        List<String> includeKeys = detail.keySet().stream().filter(f -> f.startsWith(indexCode)).collect(Collectors.toList());
                        for (String key : includeKeys) {
                            // 获取指标越限数据
                            // [{"time": "17:10:00,17:20:00,17:30:00", "value": "7.1092,7.1092,7.1093", "phasic": "A", "valueType": "CP95"}, {"time": "17:10:00,17:20:00,17:30:00", "value": "7.8081,7.808,7.8081", "phasic": "C", "valueType": "CP95"}, {"time": "17:10:00,17:20:00,17:30:00", "value": "7.5095,7.5095,7.5095", "phasic": "B", "valueType": "CP95"}]
                            JSONArray values = detail.getJSONArray(key);
                            if (CollUtil.isNotEmpty(values)) {
                                // 取出第一个数据
                                JSONObject value = values.getJSONObject(0);
                                // 获取时间
                                String time = value.getStr("time");
                                for (String t : StrUtil.split(time, StrUtil.COMMA)) {
                                    // 判断在时间段内，次数加一
                                    int hour = Integer.parseInt(t.substring(0, 2));
                                    if (hour >= start && hour < end) {
                                        times++;
                                    }
                                }
                            }
                        }
                    }
                }
                timeProbabilityVO.setTimes(times);
                result.add(timeProbabilityVO);
            }
        }

        return result;
    }



    @Override
    public List<DataLimitRateDetailTimeDto> getLimitRateDetailTime(LineCountEvaluateParam lineParam) {
        List<DataLimitRateDetailTimeDto> info = new ArrayList<>();
        LambdaQueryWrapper<RStatLimitRateDetailDPO> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.in(CollUtil.isNotEmpty(lineParam.getLineId()), RStatLimitRateDetailDPO::getLineId, lineParam.getLineId())
                .between(RStatLimitRateDetailDPO::getTime, lineParam.getStartTime(),lineParam.getEndTime())
        // .le(RStatLimitRateDetailDPO::getTime, )
        // .orderByAsc(RStatLimitRateDetailDPO::getTime)
        ;

        List<RStatLimitRateDetailDPO> list = this.list(lambdaQueryWrapper);
        DataLimitRateDetailTimeDto dto;
        for (RStatLimitRateDetailDPO detailD : list) {
            dto = new DataLimitRateDetailTimeDto();
            dto.setLineId(detailD.getLineId());
            dto.setTime(detailD.getTime().format((DateTimeFormatter.ofPattern(DatePattern.NORM_DATE_PATTERN))));
            dto.setFlickerOvertime(toList(detailD.getFlickerOvertime()));
            dto.setFreqDevOvertime(toList(detailD.getFreqDevOvertime()));
            dto.setVoltageDevOvertime(toList(detailD.getVoltageDevOvertime()));
            dto.setUbalanceOvertime(toList(detailD.getUbalanceOvertime()));
            dto.setUaberranceOvertime(toList(detailD.getUaberranceOvertime()));
            dto.setINegOvertime(toList(detailD.getINegOvertime()));
            dto.setUharmOvertime(toList(detailD,2,25,"getUharm"));
            dto.setIharmOvertime(toList(detailD,2,25,"getIharm"));
            dto.setInuharmOvertime(toList(detailD,1,16,"getInuharm"));
            info.add(dto);
        }
        return info;
    }

    private List<String> toList(RStatLimitRateDetailDPO detailD,Integer start, Integer end, String targetName){
        List<AbnormalData.Json> json = new ArrayList<>();
        for (int i = start; i <= end; i++) {
            // 构造方法名
            String methodName = targetName + i + "Overtime";
            try {
                // 获取 DataHarmDto 类的 getVx 方法
                Method getVMethod = RStatLimitRateDetailDPO.class.getMethod(methodName);
                String value = (String) getVMethod.invoke(detailD);
                if(StrUtil.isNotBlank(value)){
                    json.addAll(JSON.parseArray(value, AbnormalData.Json.class));
                }
            } catch (InvocationTargetException e) {
                throw new RuntimeException(e);
            } catch (NoSuchMethodException e) {
                throw new RuntimeException(e);
            } catch (IllegalAccessException e) {
                throw new RuntimeException(e);
            }
        }
        return getString(json);
    }

    private List<String> toList(String json){
        List<AbnormalData.Json> jsons = JSON.parseArray(json, AbnormalData.Json.class);
        return getString(jsons);
    }

    private List<String> getString(List<AbnormalData.Json> jsons) {
        if (CollUtil.isNotEmpty(jsons)){
            List<String> times = jsons.stream().map(AbnormalData.Json::getTime).collect(Collectors.toList());
            String join = String.join(",", times);
            String[] split = join.split(",");
            return Arrays.stream(split).distinct().collect(Collectors.toList());
        }
        return new ArrayList<>();
    }

    /**
     * 设置LimitExtentVO的最大值和相关信息
     */
    private void setLimitExtentInfo(LimitExtentVO limitExtentVO, Pair<Float, RStatLimitRateDetailDPO> result) {
        float maxValue = result.getKey();
        limitExtentVO.setMaxValue(maxValue);
        RStatLimitRateDetailDPO maxDetail = result.getValue();
        if (maxDetail != null) {
            limitExtentVO.setTime(maxDetail.getTime());
            CsLinePO maxLinePO = csLineFeignClient.getById(maxDetail.getLineId()).getData();
            if (maxLinePO != null) {
                limitExtentVO.setLineName(maxLinePO.getName());
                limitExtentVO.setLineId(maxLinePO.getLineId());
            }
        }
    }

    /**
     * 查找数据中的最大值及其对应的记录
     *
     * @param detailList 数据列表
     * @return 包含最大值和对应记录的Pair对象
     */
    private Map<String, Pair<Float, RStatLimitRateDetailDPO>> findMaxValueHandle(List<RStatLimitRateDetailDPO> detailList) {

        Map<String, Pair<Float, RStatLimitRateDetailDPO>> result = new HashMap<>();

        RStatLimitRateDetailDPO flickerMaxDetail = null;
        float flickerMaxValue = 0.0000F;

        RStatLimitRateDetailDPO voltageDevMaxDetail = null;
        float voltageDevMaxValue = 0.0000F;
        RStatLimitRateDetailDPO ubalanceMaxDetail = null;
        float ubalanceMaxValue = 0.0000F;

        RStatLimitRateDetailDPO uharmMaxDetail = null;
        float uharmMaxValue = 0.0000F;
        String uharmMaxKey = ""; // 记录uharm最大值对应的key
        RStatLimitRateDetailDPO iharmMaxDetail = null;
        float iharmMaxValue = 0.0000F;
        String iharmMaxKey = ""; // 记录iharm最大值对应的key

        for (RStatLimitRateDetailDPO po : detailList) {
            String flickerOvertime = po.getFlickerOvertime();
            String voltageDevOvertime = po.getVoltageDevOvertime();
            String ubalanceOvertime = po.getUbalanceOvertime();
            if (StrUtil.isNotBlank(flickerOvertime)) {
                float dayFlickerMaxValue = parseMaxValueFromJsonArray(flickerOvertime);
                if (dayFlickerMaxValue > flickerMaxValue) {
                    flickerMaxValue = dayFlickerMaxValue;
                    flickerMaxDetail = po;
                }
            }
            if (StrUtil.isNotBlank(voltageDevOvertime)) {
                float dayVoltageDevMaxValue = parseMaxValueFromJsonArray(voltageDevOvertime);
                if (dayVoltageDevMaxValue > voltageDevMaxValue) {
                    voltageDevMaxValue = dayVoltageDevMaxValue;
                    voltageDevMaxDetail = po;
                }
            }
            if (StrUtil.isNotBlank(ubalanceOvertime)) {
                float dayUbalanceMaxValue = parseMaxValueFromJsonArray(ubalanceOvertime);
                if (dayUbalanceMaxValue > ubalanceMaxValue) {
                    ubalanceMaxValue = dayUbalanceMaxValue;
                    ubalanceMaxDetail = po;
                }
            }
            JSONObject entries = JSONUtil.parseObj(po);
            float dayUharmMaxValue = 0.0000F;
            String dayUharmMaxKey = ""; // 当前记录中uharm的最大值key
            float dayIharmMaxValue = 0.0000F;
            String dayIharmMaxKey = ""; // 当前记录中iharm的最大值key

            for (Map.Entry<String, Object> entry : entries.entrySet()) {
                String key = entry.getKey();
                if (key.endsWith("Overtime")) {
                    if (key.startsWith("uharm")) {
                        Object value = entry.getValue();
                        if (ObjectUtil.isNotEmpty(value)) {
                            float timeMaxValue = parseMaxValueFromJsonArray(value);
                            // 取次数最大的未当天的最大值
                            dayUharmMaxValue = Math.max(dayUharmMaxValue, timeMaxValue);
                            dayUharmMaxKey = key;
                        }
                    }
                    if (key.startsWith("iharm")) {
                        Object value = entry.getValue();
                        if (ObjectUtil.isNotEmpty(value)) {
                            float timeMaxValue = parseMaxValueFromJsonArray(value);
                            // 取次数最大的为当天的最大值
                            dayIharmMaxValue = Math.max(dayIharmMaxValue, timeMaxValue);
                            dayIharmMaxKey = key;
                        }
                    }
                }
            }
            if (dayUharmMaxValue > uharmMaxValue) {
                uharmMaxValue = dayUharmMaxValue;
                uharmMaxDetail = po;
                uharmMaxKey = dayUharmMaxKey; // 记录产生最大值的key
            }
            if (dayIharmMaxValue > iharmMaxValue) {
                iharmMaxValue = dayIharmMaxValue;
                iharmMaxDetail = po;
                iharmMaxKey = dayIharmMaxKey; // 记录产生最大值的key
            }
        }
        result.put("flicker", Pair.of(flickerMaxValue, flickerMaxDetail));
        result.put("voltageDev", Pair.of(voltageDevMaxValue, voltageDevMaxDetail));
        result.put("ubalance", Pair.of(ubalanceMaxValue, ubalanceMaxDetail));
        result.put(uharmMaxKey.isEmpty() ? "uharm" : uharmMaxKey, Pair.of(uharmMaxValue, uharmMaxDetail));
        result.put(iharmMaxKey.isEmpty() ? "iharm" : iharmMaxKey, Pair.of(iharmMaxValue, iharmMaxDetail));

        return result;
    }

    /**
     * 从JSON数组字符串中解析出最大值
     *
     * @param value JSON数组字符串
     * @return 解析出的最大值
     */
    private float parseMaxValueFromJsonArray(Object value) {
        JSONArray overtimeArray = JSONUtil.parseArray(value);
        float maxValue = 0.0000F;
        for (Object data : overtimeArray) {
            JSONObject entries = JSONUtil.parseObj(data);
            String values = entries.getStr("value");
            float currentValue = (float) StrUtil.split(values, StrUtil.COMMA)
                    .stream()
                    .mapToDouble(Float::parseFloat)
                    .max()
                    .orElse(0.0000F);
            maxValue = Math.max(maxValue, currentValue);
        }

        return maxValue;
    }

    private String getDescription(String key) {
        if (StrUtil.equals(key, "flickerOvertime")) {
            return "闪变越限";
        }
        if (StrUtil.equals(key, "freqDevOvertime")) {
            return "频率偏差越限";
        }
        if (StrUtil.equals(key, "voltageDevOvertime")) {
            return "电压偏差越限";
        }
        if (StrUtil.equals(key, "ubalanceOvertime")) {
            return "三相电压不平衡越限";
        }
        // 电压
        if (StrUtil.startWith(key, "uharm")) {
            return "谐波电压越限";
        }
        // 电流
        if (StrUtil.startWith(key, "iharm")) {
            return "谐波电流越限";
        }
        return null;
    }

    private double calculatePercentage(double part, double total) {
        return Double.parseDouble(df.format(BigDecimal.valueOf(part / total * 100.0)
                .setScale(2, RoundingMode.HALF_UP).doubleValue()));
    }
}
