package com.njcn.csharmonic.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
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.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.CsCommTerminalFeignClient;
import com.njcn.csdevice.api.CsLineFeignClient;
import com.njcn.csdevice.api.CsOverLimitClient;
import com.njcn.csdevice.pojo.dto.DevDetailDTO;
import com.njcn.csdevice.pojo.po.CsLinePO;
import com.njcn.csharmonic.mapper.RStatLimitRateDetailDMapper;
import com.njcn.csharmonic.pojo.param.LimitCalendarQueryParam;
import com.njcn.csharmonic.pojo.param.LimitExtentDayQueryParam;
import com.njcn.csharmonic.pojo.param.LimitExtentQueryParam;
import com.njcn.csharmonic.pojo.param.LimitProbabilityQueryParam;
import com.njcn.csharmonic.pojo.po.RStatLimitRateDetailDPO;
import com.njcn.csharmonic.pojo.vo.LimitCalendarVO;
import com.njcn.csharmonic.pojo.vo.LimitExtentVO;
import com.njcn.csharmonic.pojo.vo.LimitProbabilityVO;
import com.njcn.csharmonic.pojo.vo.LimitTimeProbabilityVO;
import com.njcn.csharmonic.service.IRStatLimitRateDetailDService;
import com.njcn.device.biz.pojo.po.Overlimit;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;

import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.time.LocalDate;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

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

    private final CsLineFeignClient csLineFeignClient;
    private final CsOverLimitClient overLimitClient;
    private final CsCommTerminalFeignClient csCommTerminal;
    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<String> keywordsLineIds = new ArrayList<>();
        List<CsLinePO> poList = csLineFeignClient.getSimpleLine().getData();
        if (CollUtil.isNotEmpty(poList)) {
            keywordsLineIds = poList.stream().map(CsLinePO::getLineId).collect(Collectors.toList());
        }
        if (CollUtil.isEmpty(keywordsLineIds)) {
            return result;
        }
        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())
                .in(RStatLimitRateDetailDPO::getLineId, keywordsLineIds)
                .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, Overlimit> overLimitMap = overlimitList.stream().collect(Collectors.toMap(Overlimit::getId, item -> item));

            List<DevDetailDTO> devDetailDTOList = csCommTerminal.getLedgerByLineId(lineIds).getData();
            Map<String, DevDetailDTO> devDetailDTOMap = devDetailDTOList.stream().collect(Collectors.toMap(DevDetailDTO::getLineId, item -> item));

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

            setInternationalValue(flicker, flicker.getLineId(), null, overLimitMap, "getFlicker");
            setInternationalValue(uharm, uharm.getLineId(), uharm.getCode(), overLimitMap, null);
            setInternationalValue(iharm, iharm.getLineId(), iharm.getCode(), overLimitMap, null);
            setInternationalValue(voltageDev, voltageDev.getLineId(), null, overLimitMap, "getVoltageDev");
            setInternationalValue(ubalance, ubalance.getLineId(), null, overLimitMap, "getUbalance");
        }
        result.add(flicker);
        result.add(uharm);
        result.add(iharm);
        result.add(voltageDev);
        result.add(ubalance);
        return result;
    }

    /**
     * 通用属性值设置方法
     * @param entity        目标实体对象 (如 flicker, uharm)
     * @param lineId        线路ID (用于从 Map 中获取数据)
     * @param code          动态属性编码 (可为 null，若为 null 则使用固定 getterName)
     * @param overLimitMap  数据源 Map
     * @param fixedGetter   当 code 为 null 时，指定的固定 Getter 方法名 (如 "getFlicker")
     */
    private void setInternationalValue(Object entity, String lineId, String code,
                                       Map<String, Overlimit> overLimitMap, String fixedGetter) {
        if (Objects.isNull(lineId)) {
            // 通过反射统一处理实体的setter
            invokeSetter(entity, "setMaxValue", null);
            invokeSetter(entity, "setInternationalValue", null);
            return;
        }

        Object mapValue = overLimitMap.get(lineId);
        if (mapValue == null) return;

        try {
            Object result;
            if (StringUtils.isNotBlank(code)) {
                // 1. 动态反射模式：根据 code 截取前缀并拼接 Getter
                String propertyName = StringUtils.substringBefore(code, "Overtime");
                String methodName = "get" + StringUtils.capitalize(propertyName);
                Method method = mapValue.getClass().getMethod(methodName);
                result = method.invoke(mapValue);
            } else {
                // 2. 固定 Getter 模式：直接调用传入的固定方法名
                Method method = mapValue.getClass().getMethod(fixedGetter);
                result = method.invoke(mapValue);
            }

            // 将获取到的值设置到实体中
            invokeSetter(entity, "setInternationalValue", result);

        } catch (Exception e) {
            log.error("反射获取或设置属性失败");
        }
    }

    private void invokeSetter(Object target, String methodName, Object value) {
        try {
            Class<?>[] paramTypes = (value != null) ? new Class[]{value.getClass()} : new Class[0];
            // 如果 value 是 Float，可能需要匹配 float.class 或包装类，这里简化处理
            for (Method m : target.getClass().getMethods()) {
                if (m.getName().equals(methodName) && m.getParameterCount() == 1) {
                    m.invoke(target, value);
                    break;
                }
            }
        } catch (Exception e) {
            log.error("调用 setter 失败");
        }
    }

    @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<String> keywordsLineIds = new ArrayList<>();
        List<CsLinePO> poList = csLineFeignClient.getSimpleLine().getData();
        if (CollUtil.isNotEmpty(poList)) {
            keywordsLineIds = poList.stream().map(CsLinePO::getLineId).collect(Collectors.toList());
        }
        if (CollUtil.isEmpty(keywordsLineIds)) {
            return result;
        }
        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())
                .in(RStatLimitRateDetailDPO::getLineId, keywordsLineIds)
                .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,null,null);
                            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;
        if (CollUtil.isNotEmpty(overlimitList)) {
            overlimitJSON = JSONUtil.parseObj(overlimitList.get(0));
        } else {
            overlimitJSON = null;
        }
        //按日期获取各个指标最大值
        Map<LocalDate, List<RStatLimitRateDetailDPO>> detailMap = detailList.stream().sorted(Comparator.comparing(RStatLimitRateDetailDPO::getTime)).collect(Collectors.groupingBy(RStatLimitRateDetailDPO::getTime));
        Map<LocalDate, Map<String,Float>> maxValueMapByDay = new HashMap<>();
        detailMap.forEach((k,v)->{
            Map<String, Pair<Float, RStatLimitRateDetailDPO>> maxValueMap = findMaxValueHandle(v);
            Map<String,Float> m1 = new HashMap<>();
            maxValueMap.forEach((k1,v1)->{
                m1.put(k1,v1.getKey());
            });

            Map<String,Float> m2 = new HashMap<>();
            m1.forEach((k1,v1)->{
                double extentValue = 0;
                if (k1.startsWith("uharm") && k1.endsWith("Overtime")) {
                    String d1 = k1.replaceAll("([a-zA-Z]+)(\\d+)(.*)", "$1$2");
                    String d2 = k1.replaceAll("([a-zA-Z]+)(\\d+)(.*)", "$1");
                    assert overlimitJSON != null;
                    double limitValue = overlimitJSON.getDouble(d1);
                    extentValue = calculatePercentage(v1.doubleValue() - limitValue, limitValue);
                    m2.put(d2,(float) extentValue);
                } else if (k1.startsWith("iharm") && k1.endsWith("Overtime")) {
                    String d1 = k1.replaceAll("([a-zA-Z]+)(\\d+)(.*)", "$1$2");
                    String d2 = k1.replaceAll("([a-zA-Z]+)(\\d+)(.*)", "$1");
                    assert overlimitJSON != null;
                    double limitValue = overlimitJSON.getDouble(d1);
                    extentValue = calculatePercentage(v1.doubleValue() - limitValue, limitValue);
                    m2.put(d2,(float) extentValue);
                } else {
                    if (v1.doubleValue() != 0.0) {
                        assert overlimitJSON != null;
                        double limitValue = overlimitJSON.getDouble(k1);
                        extentValue = calculatePercentage(v1.doubleValue() - limitValue, limitValue);
                    }
                    m2.put(k1,(float) extentValue);
                }
            });
            Float f1 = m2.get("uharm");
            Float f2 = m2.get("uaberrance");
            m2.remove("uharm");
            m2.remove("uaberrance");
            m2.put("uharm",Math.max(f1,f2));
            maxValueMapByDay.put(k,m2);
        });

        // 确保 extentMap 初始化为线程安全的 ConcurrentHashMap
        Map<String, List<Float>> extentMap = new ConcurrentHashMap<>();
        maxValueMapByDay.forEach((dayKey, dayValues) -> {
            dayValues.forEach((key, value) -> {
                // 获取当前 key 对应的列表，若不存在则初始化为空列表
                List<Float> list = extentMap.computeIfAbsent(key, k -> new ArrayList<>());
                // 直接添加值到列表中
                if (value > 0.0) {
                    list.add(value);
                }
            });
        });

        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<Map<Integer, Integer>> extentGrades = getFenBu(extentMap.get(indexCode));
            probabilityVO.setExtentGrades(extentGrades);
            result.add(probabilityVO);
        }
        return result;
    }

    public List<Map<Integer, Integer>> getFenBu(List<Float> data) {
        List<Map<Integer, Integer>> result = new ArrayList<>();
        for (int i = 0; i < extentPeriodList.size(); i++) {
            Map<Integer, Integer> grade = new HashMap<>();
            int times = 0;
            if (CollectionUtil.isNotEmpty(data)) {
                for (Float extentValue : data) {
                    List<Integer> period = extentPeriodList.get(i);
                    Integer start = period.get(0);
                    Integer end = period.get(1);
                    if (extentValue > start && extentValue <= end) {
                        times++;
                    }
                    if ((i == extentPeriodList.size() - 1) && extentValue > 100.0) {
                        times++;
                    }
                }
            }
            grade.put(i, times);
            result.add(grade);
        }
        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 (shouldProcess(key, indexCode)) {
//                        double extentValue = 0;
//                        Object data = dayEntry.getValue();
//                        if (ObjectUtil.isNotEmpty(data) && overlimitJSON != null) {
//                            float maxValue = parseMaxValueFromJsonArray(data);
//                            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++;
//                    }
//                    if ((i == extentPeriodList.size() - 1) && extentValue > 100.0) {
//                        times++;
//                    }
//                }
//                grade.put(i, times);
//                extentGrades.add(grade);
//            }
//            probabilityVO.setExtentGrades(extentGrades);
//            result.add(probabilityVO);
//        }
//        return result;
//    }

    private boolean shouldProcess(String key, String indexCode) {
        return (key.endsWith("Overtime") && key.startsWith(indexCode)) ||
                (Objects.equals(indexCode, "uharm") && key.startsWith("uaberrance"));
    }

    @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<RStatLimitRateDetailDPO> monitorIdsGetLimitRateInfo(String date, List<String> monitorIds) {
        return this.baseMapper.selectList(new LambdaQueryWrapper<RStatLimitRateDetailDPO>()
                .in(RStatLimitRateDetailDPO::getLineId, monitorIds)
                .eq(RStatLimitRateDetailDPO::getTime, date));
    }

    /**
     * 设置LimitExtentVO的最大值和相关信息
     */
    private void setLimitExtentInfo(LimitExtentVO limitExtentVO, Pair<Float, RStatLimitRateDetailDPO> result, Map<String, DevDetailDTO> devDetailDTOMap) {
        float maxValue = result.getKey();
        limitExtentVO.setMaxValue(maxValue);
        RStatLimitRateDetailDPO maxDetail = result.getValue();
        if (maxDetail != null) {
            limitExtentVO.setTime(maxDetail.getTime());
            limitExtentVO.setEngineeringName(devDetailDTOMap.get(maxDetail.getLineId()).getEngineeringName());
            limitExtentVO.setProjectName(devDetailDTOMap.get(maxDetail.getLineId()).getProjectName());
            limitExtentVO.setDevName(devDetailDTOMap.get(maxDetail.getLineId()).getEquipmentName());
            limitExtentVO.setLineName(devDetailDTOMap.get(maxDetail.getLineId()).getLineName());
            limitExtentVO.setLineId(devDetailDTOMap.get(maxDetail.getLineId()).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 uaberranceMaxDetail = null;
        float uaberranceMaxValue = 0.0000F;

        RStatLimitRateDetailDPO freqDevMaxDetail = null;
        float freqDevMaxValue = 0.0000F;

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

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

        for (RStatLimitRateDetailDPO po : detailList) {
            String flickerOvertime = po.getFlickerOvertime();
            String voltageDevOvertime = po.getVoltageDevOvertime();
            String ubalanceOvertime = po.getUbalanceOvertime();
            String uaberranceOvertime = po.getUaberranceOvertime();
            String freqDevOvertime = po.getFreqDevOvertime();

            if (StrUtil.isNotBlank(flickerOvertime)) {
                float dayFlickerMaxValue = parseMaxValueFromJsonArray(flickerOvertime,0.0,20.0);
                if (dayFlickerMaxValue > flickerMaxValue) {
                    flickerMaxValue = dayFlickerMaxValue;
                    flickerMaxDetail = po;
                }
            }
            if (StrUtil.isNotBlank(voltageDevOvertime)) {
                float dayVoltageDevMaxValue = parseMaxValueFromJsonArray(voltageDevOvertime,-20.0,20.0);
                if (dayVoltageDevMaxValue > voltageDevMaxValue) {
                    voltageDevMaxValue = dayVoltageDevMaxValue;
                    voltageDevMaxDetail = po;
                }
            }
            if (StrUtil.isNotBlank(ubalanceOvertime)) {
                float dayUbalanceMaxValue = parseMaxValueFromJsonArray(ubalanceOvertime,0.0,40.0);
                if (dayUbalanceMaxValue > ubalanceMaxValue) {
                    ubalanceMaxValue = dayUbalanceMaxValue;
                    ubalanceMaxDetail = po;
                }
            }
            if (StrUtil.isNotBlank(uaberranceOvertime)) {
                    float dayuaberranceMaxValue = parseMaxValueFromJsonArray(uaberranceOvertime,0.0,30.0);
                if (dayuaberranceMaxValue > uaberranceMaxValue) {
                    uaberranceMaxValue = dayuaberranceMaxValue;
                    uaberranceMaxDetail = po;
                }
            }
            if (StrUtil.isNotBlank(freqDevOvertime)) {
                float dayFreqDevMaxValue = parseMaxValueFromJsonArray(freqDevOvertime,-7.5,7.5);
                if (dayFreqDevMaxValue > freqDevMaxValue) {
                    freqDevMaxValue = dayFreqDevMaxValue;
                    freqDevMaxDetail = po;
                }
            }



            JSONObject entries = JSONUtil.parseObj(po);
            float dayUharmMaxValue = 0.0000F;
            // 当前记录中uharm的最大值key
            String dayUharmMaxKey = "";
            float dayIharmMaxValue = 0.0000F;
            // 当前记录中iharm的最大值key
            String dayIharmMaxKey = "";

            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,0.0,30.0);
                            // 取次数最大的未当天的最大值
                            dayUharmMaxValue = Math.max(dayUharmMaxValue, timeMaxValue);
                            dayUharmMaxKey = key;
                        }
                    }
                    if (key.startsWith("iharm")) {
                        Object value = entry.getValue();
                        if (ObjectUtil.isNotEmpty(value)) {
                            float timeMaxValue = parseMaxValueFromJsonArray(value,null,null);
                            // 取次数最大的为当天的最大值
                            dayIharmMaxValue = Math.max(dayIharmMaxValue, timeMaxValue);
                            dayIharmMaxKey = key;
                        }
                    }
                }
            }
            if (dayUharmMaxValue > uharmMaxValue) {
                uharmMaxValue = dayUharmMaxValue;
                uharmMaxDetail = po;
                // 记录产生最大值的key
                uharmMaxKey = dayUharmMaxKey;
            }
            if (dayIharmMaxValue > iharmMaxValue) {
                iharmMaxValue = dayIharmMaxValue;
                iharmMaxDetail = po;
                // 记录产生最大值的key
                iharmMaxKey = dayIharmMaxKey;
            }
        }
        result.put("flicker", Pair.of(flickerMaxValue, flickerMaxDetail));
        result.put("voltageDev", Pair.of(voltageDevMaxValue, voltageDevMaxDetail));
        result.put("ubalance", Pair.of(ubalanceMaxValue, ubalanceMaxDetail));
        result.put("uaberrance", Pair.of(uaberranceMaxValue, uaberranceMaxDetail));
        result.put("freqDev", Pair.of(freqDevMaxValue, freqDevMaxDetail));
        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, Double minRange, Double maxRange) {
        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)
                    // 核心修改：在 filter 中判断边界是否为 null
                    .filter(f ->
                            (minRange == null || f >= minRange) &&
                                    (maxRange == null || f <= maxRange)
                    )
                    .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()));
    }
}
