package com.njcn.harmonic.service.majornetwork.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.njcn.common.pojo.dto.SimpleDTO;
import com.njcn.device.biz.commApi.CommTerminalGeneralClient;
import com.njcn.device.biz.pojo.dto.DeptGetSubStationDTO;
import com.njcn.device.biz.pojo.param.DeptGetLineParam;
import com.njcn.device.pms.api.DistributionMonitorClient;
import com.njcn.device.pms.pojo.param.pwUser.PwUserMonitorParam;
import com.njcn.device.pms.pojo.vo.pwUser.PwUserMonitorDataVO;
import com.njcn.device.pq.api.GeneralDeviceInfoClient;
import com.njcn.device.pq.api.LineIntegrityClient;
import com.njcn.device.pq.pojo.dto.GeneralDeviceDTO;
import com.njcn.device.pq.pojo.param.DeviceInfoParam;
import com.njcn.device.pq.pojo.param.OnlineRateParam;
import com.njcn.device.pq.pojo.po.RStatIntegrityD;
import com.njcn.device.pq.pojo.vo.GridDiagramVO;
import com.njcn.device.pq.pojo.vo.RStatOnlineRateVO;
import com.njcn.harmonic.mapper.RStatLimitTargetDMapper;
import com.njcn.harmonic.pojo.param.StatSubstationBizBaseParam;
import com.njcn.harmonic.pojo.po.day.RStatLimitRateDPO;
import com.njcn.harmonic.pojo.po.day.RStatLimitTargetDPO;
import com.njcn.harmonic.pojo.vo.MonitorLimitRateVO;
import com.njcn.harmonic.pojo.vo.PwLimitDataVO;
import com.njcn.harmonic.pojo.vo.RStatLimitTargetVO;
import com.njcn.harmonic.common.mapper.RStatLimitRateDMapper;
import com.njcn.harmonic.service.IRStatLimitTargetDService;
import com.njcn.harmonic.service.majornetwork.RStatLimitService;
import com.njcn.system.pojo.enums.StatisticsEnum;
import com.njcn.web.factory.PageFactory;
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.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * pqs
 *
 * @author cdf
 * @date 2024/2/28
 */
@Service
@RequiredArgsConstructor
public class RStatLimitServiceImpl implements RStatLimitService {

    private final RStatLimitRateDMapper rStatLimitRateDMapper;
    private final RStatLimitTargetDMapper rStatLimitTargetDMapper;
    private final GeneralDeviceInfoClient generalDeviceInfoClient;
    private final LineIntegrityClient lineIntegrityClient;
    private final IRStatLimitTargetDService targetDService;
    private final CommTerminalGeneralClient commTerminalGeneralClient;
    private final DistributionMonitorClient distributionMonitorClient;


    @Override
    public List<RStatLimitTargetDPO> monitorIdsGetLimitTargetInfo(String date, List<String> monitorIds) {
        return rStatLimitTargetDMapper.selectList(new LambdaQueryWrapper<RStatLimitTargetDPO>().in(RStatLimitTargetDPO::getLineId, monitorIds)
                .eq(RStatLimitTargetDPO::getTime, date).gt(RStatLimitTargetDPO::getAllTime, 0));
    }

    @Override
    public List<RStatLimitTargetVO> monitorOverLimitDays(String date, String endDate, List<String> monitorIds) {
        return rStatLimitTargetDMapper.getSumTargetDetails(monitorIds, date, endDate);
    }

    @Override
    public List<GridDiagramVO.LineData> getGridDiagramLineData(DeviceInfoParam.BusinessParam deviceInfoParam) {
        List<GridDiagramVO.LineData> info = new ArrayList<>();
        deviceInfoParam.setLineRunFlag(0);
        deviceInfoParam.setLineOrDevice(1);
        List<GeneralDeviceDTO> data = generalDeviceInfoClient.getPracticalRunDeviceInfo(deviceInfoParam).getData();
        List<GeneralDeviceDTO> list = data.stream().sorted(Comparator.comparing(x -> x.getLineIndexes().size(), Comparator.reverseOrder())).collect(Collectors.toList());
        //终端总数量
        List<String> devIds = list.stream().flatMap(x -> x.getDeviceIndexes().stream()).distinct().collect(Collectors.toList());
        //监测点总数量
        List<String> lineIds = list.stream().flatMap(x -> x.getLineIndexes().stream()).distinct().collect(Collectors.toList());
        //超标监测点信息
        List<String> limitTargetList = new ArrayList<>();
        List<RStatIntegrityD> integrityList = new ArrayList<>();
        if (CollUtil.isNotEmpty(lineIds)) {
            StatSubstationBizBaseParam baseParam = new StatSubstationBizBaseParam();
            baseParam.setIds(lineIds);
            baseParam.setStartTime(DateUtil.beginOfDay(DateUtil.parse(deviceInfoParam.getSearchBeginTime())).toString());
            baseParam.setEndTime(DateUtil.endOfDay(DateUtil.parse(deviceInfoParam.getSearchEndTime())).toString());
            limitTargetList = targetDService.getLinesHarmTarget(baseParam);
            integrityList = lineIntegrityClient.getIntegrityByLineIds(lineIds, deviceInfoParam.getSearchBeginTime(), deviceInfoParam.getSearchEndTime()).getData();
        }
        //终端在线率
        List<RStatOnlineRateVO> onlineRateList = new ArrayList<>();
        if (CollUtil.isNotEmpty(devIds)) {
            OnlineRateParam param = new OnlineRateParam();
            param.setIds(devIds);
            param.setStartTime(deviceInfoParam.getSearchBeginTime());
            param.setEndTime(deviceInfoParam.getSearchEndTime());
            onlineRateList = generalDeviceInfoClient.getOnlineRateByDevIds(param).getData();
        }
        List<GeneralDeviceDTO> topList = new ArrayList<>();
        List<GeneralDeviceDTO> otherList = new ArrayList<>();
        if (ObjectUtil.isNotNull(deviceInfoParam.getStatisticalType())) {
            SimpleDTO statisticalType = deviceInfoParam.getStatisticalType();
            if (!StatisticsEnum.POWER_NETWORK.getCode().equals(statisticalType.getCode())) {
                if (list.size() > 4) {
                    topList.addAll(list.subList(0, 4));
                    otherList.addAll(list.subList(4, list.size()));
                } else {
                    if (list.size() > 3) {
                        topList.addAll(list.subList(0, 3));
                        otherList.addAll(list.subList(3, list.size()));
                    } else {
                        if (list.size() > 2) {
                            topList.addAll(list.subList(0, 2));
                            otherList.addAll(list.subList(2, list.size()));
                        } else {
                            topList.addAll(list.subList(0, 1));
                            otherList.addAll(list.subList(1, list.size()));
                        }
                    }
                }
            } else {
                topList.addAll(list);
            }
        } else {
            topList.addAll(list);
        }
        GridDiagramVO.LineData lineData;
        for (GeneralDeviceDTO dto : topList) {
            lineData = new GridDiagramVO.LineData();
            lineData.setOrgId(dto.getIndex());
            lineData.setOrgName(dto.getName() + "(" + dto.getLineIndexes().size() + ")");
            onLineAndIntegrity(dto.getLineIndexes(), integrityList, dto.getDeviceIndexes(), onlineRateList, limitTargetList, lineData);
            info.add(lineData);
        }
        if (CollUtil.isNotEmpty(otherList)) {
            List<String> otherDevIds = otherList.stream().flatMap(x -> x.getDeviceIndexes().stream()).distinct().collect(Collectors.toList());
            List<String> otherLineIds = otherList.stream().flatMap(x -> x.getLineIndexes().stream()).distinct().collect(Collectors.toList());
            lineData = new GridDiagramVO.LineData();
            lineData.setOrgId("123456");
            lineData.setOrgName("其他(" + otherLineIds.size() + ")");
            onLineAndIntegrity(otherLineIds, integrityList, otherDevIds, onlineRateList, limitTargetList, lineData);
            info.add(lineData);
        }
        return info;
    }

    @Override
    public List<GridDiagramVO.AreaData> getGridDiagramAreaData(DeviceInfoParam.BusinessParam param) {
        List<GridDiagramVO.AreaData> info = new ArrayList<>();
        param.setLineRunFlag(0);
        GridDiagramVO.AreaData areaData;
        //监测点总数
        List<GeneralDeviceDTO> data = generalDeviceInfoClient.getPracticalRunDeviceInfo(param).getData();
        //在线
        param.setComFlagStatus(1);
        List<GeneralDeviceDTO> onData = generalDeviceInfoClient.getPracticalRunDeviceInfo(param).getData();
        List<String> onLine = onData.stream().flatMap(x -> x.getLineIndexes().stream()).distinct().collect(Collectors.toList());

        Map<String, GeneralDeviceDTO> onMap = onData.stream().collect(Collectors.toMap(GeneralDeviceDTO::getIndex, Function.identity()));

        DeptGetLineParam deptGetLineParam = new DeptGetLineParam();
        deptGetLineParam.setDeptId(param.getDeptIndex());
        deptGetLineParam.setPowerFlag(0);
        //变电站公共方法
        List<DeptGetSubStationDTO.Info> deptGetChildrenMoreDTOS = commTerminalGeneralClient.deptGetSubStationInfo(deptGetLineParam).getData();
        Map<String, DeptGetSubStationDTO.Info> deptLineMap = deptGetChildrenMoreDTOS.stream().collect(Collectors.toMap(DeptGetSubStationDTO.Info::getUnitId, Function.identity()));

        StatSubstationBizBaseParam baseParam = new StatSubstationBizBaseParam();
        baseParam.setIds(onLine);
        baseParam.setStartTime(DateUtil.beginOfDay(DateUtil.parse(param.getSearchBeginTime())).toString());
        baseParam.setEndTime(DateUtil.endOfDay(DateUtil.parse(param.getSearchEndTime())).toString());
        List<String> linesTarget = targetDService.getLinesHarmTarget(baseParam);
        List<RStatIntegrityD> integrityDS = lineIntegrityClient.getIntegrityByLineIds(onLine,
                DateUtil.beginOfDay(DateUtil.parse(param.getSearchBeginTime())).toString(),
                DateUtil.endOfDay(DateUtil.parse(param.getSearchEndTime())).toString()).getData();
        List<String> integrityDS0 = integrityDS.stream().filter(x -> 0.9 <= x.getIntegrityData()).map(RStatIntegrityD::getLineIndex).collect(Collectors.toList());

        for (GeneralDeviceDTO datum : data) {
            areaData = new GridDiagramVO.AreaData();
            areaData.setOrgId(datum.getIndex());
            areaData.setOrgName(datum.getName());
            areaData.setLineNum(datum.getLineIndexes().size());
            areaData.setLineList(datum.getLineIndexes());
            areaData.setDeviceNum(datum.getDeviceIndexes().size());
            if (onMap.containsKey(datum.getIndex())) {
                GeneralDeviceDTO dto = onMap.get(datum.getIndex());
                areaData.setOnlineNum(dto.getLineIndexes().size());
                areaData.setOnlineList(dto.getLineIndexes());
                areaData.setOnDevice(dto.getDeviceIndexes().size());
                if (deptLineMap.containsKey(datum.getIndex())) {
                    DeptGetSubStationDTO.Info deptSub = deptLineMap.get(datum.getIndex());
                    areaData.setSubNum(deptSub.getStationIds().size());
                    AtomicLong num = new AtomicLong();
                    List<String> alarm = new ArrayList<>();
                    deptSub.getStationIds().stream().forEach(x -> {
                        List<String> lineIds = new ArrayList<>();
                        List<String> onlineIds = new ArrayList<>();
                        //0：全部 1：国网
                        if (ObjectUtil.isNull(param.getMonitorFlag())) {
                            lineIds.addAll(x.getUnitChildrenList());
                            onlineIds.addAll(x.getUnitChildrenList().stream().filter(d -> onLine.contains(d)).collect(Collectors.toList()));
                        } else {
                            if (0 == param.getMonitorFlag()) {
                                lineIds.addAll(x.getUnitChildrenList());
                                onlineIds.addAll(x.getUnitChildrenList().stream().filter(d -> onLine.contains(d)).collect(Collectors.toList()));
                            } else {
                                lineIds.addAll(x.getGwUnitChildrenList());
                                onlineIds.addAll(x.getGwUnitChildrenList().stream().filter(d -> onLine.contains(d)).collect(Collectors.toList()));
                            }
                        }
                        List<String> collect = new ArrayList<>();
                        //监测点数据完整率大于90的
                        List<String> onIntegrity = integrityDS0.stream().filter(d -> onlineIds.contains(d)).collect(Collectors.toList());
                        //没有超标监测点
                        collect.addAll(onIntegrity.stream().filter(d -> !linesTarget.contains(d)).collect(Collectors.toList()));
                        //总监测点剔除合格监测点其他都是不合格信息
                        List<String> alarmList = lineIds.stream().filter(d -> !collect.contains(d)).collect(Collectors.toList());
                        if (CollUtil.isNotEmpty(alarmList)) {
                            num.getAndIncrement();
                            alarm.addAll(alarmList);
                        }

                    });
                    areaData.setAlarmSubNum(Math.toIntExact(num.get()));
                    areaData.setAlarmSubList(alarm.stream().distinct().collect(Collectors.toList()));
                }
                List<String> lineAlarm = new ArrayList<>();
                List<String> onIds = datum.getLineIndexes().stream().filter(d -> onLine.contains(d)).collect(Collectors.toList());
                List<String> onIntegrity = integrityDS0.stream().filter(d -> onIds.contains(d)).collect(Collectors.toList());
                lineAlarm.addAll(onIntegrity.stream().filter(d -> !linesTarget.contains(d)).collect(Collectors.toList()));
                List<String> alarm = datum.getLineIndexes().stream().filter(d -> !lineAlarm.contains(d)).collect(Collectors.toList());
                areaData.setAlarm(alarm.size());
                areaData.setAlarmList(alarm);

            }
            info.add(areaData);
        }
        return info;
    }

    @Override
    public List<GridDiagramVO.RunData> getGridDiagramRunData(DeviceInfoParam.BusinessParam param) {
        List<GridDiagramVO.RunData> info = new ArrayList<>();
        param.setLineRunFlag(0);
        //监测点总数
        List<GeneralDeviceDTO> data = generalDeviceInfoClient.getPracticalRunDeviceInfo(param).getData();
        List<String> line = data.stream().flatMap(x -> x.getLineIndexes().stream()).distinct().collect(Collectors.toList());
        //在线
        param.setComFlagStatus(1);
        List<GeneralDeviceDTO> onData = generalDeviceInfoClient.getPracticalRunDeviceInfo(param).getData();
        List<String> online = onData.stream().flatMap(x -> x.getLineIndexes().stream()).distinct().collect(Collectors.toList());

        StatSubstationBizBaseParam baseParam = new StatSubstationBizBaseParam();
        baseParam.setIds(online);
        baseParam.setStartTime(DateUtil.beginOfDay(DateUtil.parse(param.getSearchBeginTime())).toString());
        baseParam.setEndTime(DateUtil.endOfDay(DateUtil.parse(param.getSearchEndTime())).toString());
        List<String> linesTarget = targetDService.getLinesHarmTarget(baseParam);
        List<RStatIntegrityD> integrityDS = lineIntegrityClient.getIntegrityByLineIds(line,
                DateUtil.beginOfDay(DateUtil.parse(param.getSearchBeginTime())).toString(),
                DateUtil.endOfDay(DateUtil.parse(param.getSearchEndTime())).toString()).getData();
        //在线率大于90的点
        List<String> integrityDS90 = integrityDS.stream().filter(x -> 0.9 <= x.getIntegrityData()).map(RStatIntegrityD::getLineIndex).collect(Collectors.toList());

        //合格-告警
        GridDiagramVO.RunData alarmData = new GridDiagramVO.RunData();
        List<String> alarm = integrityDS90.stream().filter(d -> !linesTarget.contains(d)).distinct().collect(Collectors.toList());
        List<String> us = line.stream().filter(x -> !alarm.contains(x)).distinct().collect(Collectors.toList());
        alarmData.setLineNumOne(alarm.size());
        alarmData.setLineListOne(alarm);
        alarmData.setLineNumTwo(us.size());
        alarmData.setLineListTwo(us);
        info.add(alarmData);

        //在线-离线
        GridDiagramVO.RunData runData = new GridDiagramVO.RunData();
        List<String> Offline = line.stream().filter(x -> !online.contains(x)).distinct().collect(Collectors.toList());
        runData.setLineNumOne(online.size());
        runData.setLineListOne(online);
        runData.setLineNumTwo(Offline.size());
        runData.setLineListTwo(Offline);
        info.add(runData);

        //数据完整性≥90% - <90%
        GridDiagramVO.RunData integrityData = new GridDiagramVO.RunData();
        List<String> integrity = line.stream().filter(x -> !integrityDS90.contains(x)).distinct().collect(Collectors.toList());
        integrityData.setLineNumOne(integrityDS90.size());
        integrityData.setLineListOne(integrityDS90);
        integrityData.setLineNumTwo(integrity.size());
        integrityData.setLineListTwo(integrity);
        info.add(integrityData);


        //电能质量指标未超标-超标
        GridDiagramVO.RunData targetData = new GridDiagramVO.RunData();
        List<String> integrityS = line.stream().filter(x -> !linesTarget.contains(x)).distinct().collect(Collectors.toList());
        targetData.setLineNumOne(integrityS.size());
        targetData.setLineListOne(integrityS);
        targetData.setLineNumTwo(linesTarget.size());
        targetData.setLineListTwo(linesTarget);
        info.add(targetData);
        return info;
    }


    @Override
    public Page<MonitorLimitRateVO> pwMonitorLimitData(PwUserMonitorParam pwUserMonitorParam) {
        Page<MonitorLimitRateVO> pageResult = new Page<>(PageFactory.getPageNum(pwUserMonitorParam), PageFactory.getPageSize(pwUserMonitorParam));
        List<PwUserMonitorDataVO> pwUserMonitorDataVOList = distributionMonitorClient.getPwUserIds(pwUserMonitorParam).getData();
        if (CollUtil.isEmpty(pwUserMonitorDataVOList)) {
            return pageResult;
        }
        List<String> ids = pwUserMonitorDataVOList.stream().map(PwUserMonitorDataVO::getId).collect(Collectors.toList());

        QueryWrapper<RStatLimitRateDPO> queryWrapper = new QueryWrapper<>();
        StringBuilder stringBuilder = new StringBuilder();
        for (int i = 2; i < 26; i++) {
            if (i == 25) {
                stringBuilder.append("sum(uharm_").append(i).append("_overtime) as uharm_").append(i).append("_overtime ");
            } else {
                stringBuilder.append("sum(uharm_").append(i).append("_overtime) as uharm_").append(i).append("_overtime").append(",");
            }
        }
        queryWrapper.select("my_index  lineId ,sum(all_time) all_time,sum(flicker_all_time) flicker_all_time,sum(freq_dev_overtime) freq_dev_overtime,sum(voltage_dev_overtime) voltage_dev_overtime,sum(ubalance_overtime) ubalance_overtime,sum(flicker_overtime) flicker_overtime,sum(uaberrance_overtime) uaberrance_overtime", stringBuilder.toString())
                .in("my_index", ids).between("time_id", pwUserMonitorParam.getSearchBeginTime(), pwUserMonitorParam.getSearchEndTime()).eq("phasic_type", "T").groupBy("my_index");

        if (StrUtil.isNotBlank(pwUserMonitorParam.getOrderBy())) {
            String sortBy = strToSql(pwUserMonitorParam.getSortBy());
            if (pwUserMonitorParam.getOrderBy().equals("asc")) {
                queryWrapper.orderBy(true, true, sortBy);
            } else {
                queryWrapper.orderBy(true, false, sortBy);
            }

        }

        Page<RStatLimitRateDPO> temPage = rStatLimitRateDMapper.selectPage(new Page<>(PageFactory.getPageNum(pwUserMonitorParam), PageFactory.getPageSize(pwUserMonitorParam)), queryWrapper);
        pageResult.setTotal(temPage.getTotal());
        if (CollUtil.isNotEmpty(temPage.getRecords())) {
            Map<String, PwUserMonitorDataVO> map = pwUserMonitorDataVOList.stream().collect(Collectors.toMap(PwUserMonitorDataVO::getId, Function.identity()));
            List<MonitorLimitRateVO> resultList = new ArrayList<>();
            for (RStatLimitRateDPO item : temPage.getRecords()) {
                MonitorLimitRateVO monitorLimitRateVO = new MonitorLimitRateVO();
                PwUserMonitorDataVO pwUserMonitorDataVO = map.get(item.getLineId());
                BeanUtil.copyProperties(pwUserMonitorDataVO, monitorLimitRateVO);
                if (item.getAllTime() == 0) {
                    monitorLimitRateVO.setFreqDevOvertime(BigDecimal.valueOf(3.14159));
                    monitorLimitRateVO.setUaberranceOvertime(BigDecimal.valueOf(3.14159));
                    monitorLimitRateVO.setUbalanceOvertime(BigDecimal.valueOf(3.14159));
                    monitorLimitRateVO.setVoltageDevOvertime(BigDecimal.valueOf(3.14159));
                } else {
                    monitorLimitRateVO.setFreqDevOvertime(calculatePercentage(item.getFreqDevOvertime(), item.getAllTime()));
                    monitorLimitRateVO.setUaberranceOvertime(calculatePercentage(item.getUaberranceOvertime(), item.getAllTime()));
                    monitorLimitRateVO.setUbalanceOvertime(calculatePercentage(item.getUbalanceOvertime(), item.getAllTime()));
                    monitorLimitRateVO.setVoltageDevOvertime(calculatePercentage(item.getVoltageDevOvertime(), item.getAllTime()));
                }

                if (item.getFlickerAllTime() == 0) {
                    monitorLimitRateVO.setFlickerOvertime(BigDecimal.valueOf(3.14159));
                } else {
                    monitorLimitRateVO.setFlickerOvertime(calculatePercentage(item.getFlickerOvertime(), item.getFlickerAllTime()));
                }

                setUharmOvertimeRatios(item, monitorLimitRateVO);
                resultList.add(monitorLimitRateVO);
            }
            pageResult.setRecords(resultList);
        }
        return pageResult;
    }


    /**
     * 计算百分比，结果不超过100
     *
     * @param flickerOvertime 闪烁超时时间
     * @param flickerAllTime  总闪烁时间
     * @return 计算的百分比（如果结果超过100，则返回100）
     */
    public BigDecimal calculatePercentage(Integer flickerOvertime, Integer flickerAllTime) {
        // 检查参数是否为null
        if (flickerOvertime == null || flickerAllTime == null) {
            throw new IllegalArgumentException("方法遇到不合法参数");
        }
        // 将Integer转换为BigDecimal进行计算
        BigDecimal overtime = BigDecimal.valueOf(flickerOvertime);
        BigDecimal allTime = BigDecimal.valueOf(flickerAllTime);

        // 计算百分比
        BigDecimal percentage = overtime.divide(allTime, 10, RoundingMode.HALF_UP)
                .multiply(BigDecimal.valueOf(100))
                .setScale(2, RoundingMode.HALF_UP);

        // 如果百分比超过100，则调整为100
        return percentage.compareTo(BigDecimal.valueOf(100)) > 0 ? BigDecimal.valueOf(100) : percentage;
    }

    @Override
    public List<PwLimitDataVO> pwMonitorLimitDataRange(PwUserMonitorParam pwUserMonitorParam) {
        List<PwLimitDataVO> result = new ArrayList<>();
        if (CollUtil.isEmpty(pwUserMonitorParam.getIds())) {
            return result;
        }

        LambdaQueryWrapper<RStatLimitTargetDPO> lambdaQueryWrapper = new LambdaQueryWrapper<>();

        LocalDate startDate = LocalDate.parse(pwUserMonitorParam.getSearchBeginTime(), DateTimeFormatter.ofPattern(DatePattern.NORM_DATE_PATTERN));
        LocalDate endDate = LocalDate.parse(pwUserMonitorParam.getSearchEndTime(), DateTimeFormatter.ofPattern(DatePattern.NORM_DATE_PATTERN));

        lambdaQueryWrapper.select(RStatLimitTargetDPO::getLineId, RStatLimitTargetDPO::getTime, RStatLimitTargetDPO::getAllTime).in(RStatLimitTargetDPO::getLineId, pwUserMonitorParam.getIds());
        lambdaQueryWrapper.between(RStatLimitTargetDPO::getTime, pwUserMonitorParam.getSearchBeginTime(), pwUserMonitorParam.getSearchEndTime());
        List<RStatLimitTargetDPO> rStatLimitTargetDPOList = rStatLimitTargetDMapper.selectList(lambdaQueryWrapper);
        if (CollUtil.isNotEmpty(rStatLimitTargetDPOList)) {
            Map<String, List<RStatLimitTargetDPO>> map = rStatLimitTargetDPOList.stream().collect(Collectors.groupingBy(RStatLimitTargetDPO::getLineId));
            processDateRange(startDate, endDate, map, result);
        }


        return result;
    }

    public void processDateRange(LocalDate startDate, LocalDate endDate, Map<String, List<RStatLimitTargetDPO>> map, List<PwLimitDataVO> result) {
        map.forEach((lineKey, list) -> {
            PwLimitDataVO pwLimitDataVO = new PwLimitDataVO();
            pwLimitDataVO.setLineId(lineKey);
            pwLimitDataVO.setName(lineKey);
            List<PwLimitDataVO.LimitDetail> detailList = new ArrayList<>();

            if (startDate.getYear() == endDate.getYear() && startDate.getMonth() == endDate.getMonth()) {
                Map<LocalDate, RStatLimitTargetDPO> targetDPOMap = list.stream().collect(Collectors.toMap(RStatLimitTargetDPO::getTime, Function.identity()));
                // 如果在同一个月，则遍历每一天
                for (LocalDate date = startDate; !date.isAfter(endDate.minusDays(1)); date = date.plusDays(1)) {
                    PwLimitDataVO.LimitDetail limitDetail = new PwLimitDataVO.LimitDetail();
                    if (targetDPOMap.containsKey(date)) {
                        limitDetail.setLimitFlag(targetDPOMap.get(date).getAllTime() > 0 ? 2 : 1);
                    } else {
                        limitDetail.setLimitFlag(0);
                    }
                    limitDetail.setDay(date.getDayOfMonth() + "日");
                    detailList.add(limitDetail);
                }

            } else {
                Map<String, List<RStatLimitTargetDPO>> targetDPOMap = list.stream().collect(Collectors.groupingBy(it -> LocalDateTimeUtil.format(it.getTime(), DatePattern.NORM_MONTH_PATTERN)));
                // 如果在同一个月，则遍历每一天

                // 如果不在同一个月，则遍历每个月（这里简化处理，只打印月份和年份）
                LocalDate currentDate = startDate;
                while (!currentDate.isAfter(endDate)) {
                    String date = LocalDateTimeUtil.format(currentDate, DatePattern.NORM_MONTH_PATTERN);

                    PwLimitDataVO.LimitDetail limitDetail = new PwLimitDataVO.LimitDetail();
                    if (targetDPOMap.containsKey(date)) {
                        boolean res = targetDPOMap.get(date).stream().anyMatch(item -> item.getAllTime() > 0);
                        limitDetail.setLimitFlag(res ? 2 : 1);
                    } else {
                        limitDetail.setLimitFlag(0);
                    }
                    limitDetail.setDay(currentDate.getMonthValue() + "月");
                    detailList.add(limitDetail);


                    // 跳到下一个月的第一天（注意：这里简化了处理，没有实际遍历这个月的每一天）
                    currentDate = currentDate.plusMonths(1).withDayOfMonth(1);

                    // 如果当前月已经超过了结束月，则退出循环
                    if (currentDate.isAfter(endDate)) {
                        break;
                    }
                }
            }
            pwLimitDataVO.setDetailList(detailList);
            result.add(pwLimitDataVO);
        });


    }


    public String strToSql(String originalString) {
        StringBuilder modifiedStringBuilder = new StringBuilder();

        // 标记是否需要在下一个字符前添加下划线
        boolean needUnderscore = false;

        for (int i = 0; i < originalString.length(); i++) {
            char currentChar = originalString.charAt(i);

            // 检查当前字符是否为大写字母
            if (Character.isUpperCase(currentChar)) {
                // 如果不是字符串的第一个字符，或者即使是第一个字符但也需要下划线（实际上第一个大写不需要）
                // 但由于逻辑简化，我们只在需要时设置needUnderscore
                needUnderscore = true;
            } else if (Character.isDigit(currentChar)) {
                // 如果当前字符是数字
                // 检查下一个字符（如果存在）是否也是数字
                if (i + 1 < originalString.length() && Character.isDigit(originalString.charAt(i + 1))) {
                    // 当前字符和下一个字符都是数字，但我们只在数字序列的开头添加下划线
                    // 如果这不是字符串的开头，并且之前没有添加过下划线（即不是在前一个数字后）
                    if (i > 0 && !Character.isDigit(originalString.charAt(i - 1))) {
                        needUnderscore = true;
                    }
                    // 对于数字序列的其余部分，我们不需要再设置needUnderscore为true
                } else {
                    // 当前字符是单个数字，且不是字符串的开头，则可能需要下划线
                    if (i > 0 && !Character.isDigit(originalString.charAt(i - 1))) {
                        needUnderscore = true;
                    }
                }
            } else {
                // 重置needUnderscore，因为当前字符既不是大写也不是数字
                // 但注意，如果当前字符后面紧跟大写或数字序列，needUnderscore会在后续迭代中被设置
                needUnderscore = false;
            }

            // 如果需要下划线且不是字符串的开头，则添加下划线
            if (needUnderscore && i > 0) {
                modifiedStringBuilder.append('_');
                needUnderscore = false; // 重置标记，因为我们已经添加了下划线
            }

            // 将当前字符添加到StringBuilder中
            modifiedStringBuilder.append(currentChar);
        }

        return modifiedStringBuilder.toString();
    }

    //赋值2到25次谐波
    public void setUharmOvertimeRatios(final RStatLimitRateDPO item, final MonitorLimitRateVO monitorLimitRateVO) {
        // 使用一个循环来避免重复代码
        for (int i = 2; i <= 25; i++) {
            // 使用反射来动态调用方法（如果方法名遵循getUharmXOvertime()模式）
            String methodName = "getUharm" + i + "Overtime";
            String setterName = "setUharm" + i + "Overtime";

            // 假设这些方法都存在且返回long或int类型
            long uharmOvertime = 0;
            try {
                Method method = item.getClass().getMethod(methodName);
                uharmOvertime = (int) method.invoke(item);

                long allTime = item.getAllTime();
                if (allTime == 0) {
                    // 防止除以0的错误
                    monitorLimitRateVO.getClass().getMethod(setterName, BigDecimal.class)
                            .invoke(monitorLimitRateVO, BigDecimal.valueOf(3.14159));
                } else {
                    BigDecimal ratio = BigDecimal.valueOf((double) uharmOvertime / allTime * 100)
                            .setScale(2, RoundingMode.HALF_UP);
                    ratio = ratio.compareTo(BigDecimal.valueOf(100)) > 0 ? BigDecimal.valueOf(100) : ratio;
                    monitorLimitRateVO.getClass().getMethod(setterName, BigDecimal.class)
                            .invoke(monitorLimitRateVO, ratio);
                }
            } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
                // 处理异常，例如记录日志或抛出运行时异常
                throw new RuntimeException("Error setting UharmOvertime ratio", e);
            }
        }
    }


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