package com.ruoyi.system.service.impl;

import com.ruoyi.common.core.utils.DateUtils;
import com.ruoyi.common.core.utils.EchartsDataUtils;
import com.ruoyi.common.core.utils.SpeedUtils;
import com.ruoyi.system.domain.*;
import com.ruoyi.system.enums.ReviewEnum;
import com.ruoyi.system.mapper.*;
import com.ruoyi.system.service.EpsInitialTrafficDataService;
import com.ruoyi.system.util.CalculateUtil;
import com.ruoyi.system.util.DateUtil;
import com.ruoyi.system.util.TableRouterUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.YearMonth;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
@Slf4j
public class EpsInitialTrafficDataServiceImpl implements EpsInitialTrafficDataService {

    private static final String DATE_TIME_FORMATTER = "yyyy-MM-dd HH:mm:ss";
    @Autowired
    private EpsInitialTrafficDataMapper epsInitialTrafficDataMapper;
    @Autowired
    private EpsNodeBandwidthMapper epsNodeBandwidthMapper;
    @Autowired
    private AllInterfaceNameMapper allInterfaceNameMapper;
    @Autowired
    private EpsServerRevenueConfigMapper epsServerRevenueConfigMapper;
    @Autowired
    private EpsMethodChangeRecordMapper epsMethodChangeRecordMapper;
    @Autowired
    private EpsBusinessDeployMapper epsBusinessDeployMapper;
    @Autowired
    private RmEpsTopologyManagementMapper rmEpsTopologyManagementMapper;
    @Override
    public void createNextMonthTables() {
        LocalDate nextMonth = LocalDate.now().plusMonths(1);
//        LocalDate nextMonth = LocalDate.now();
        int year = nextMonth.getYear();
        int month = nextMonth.getMonthValue();

        // 创建流量详情表
        createTrafficDetailsTable(year, month);
        // 创建流量初始表
        createTrafficStatsTable(year, month);
    }

    private void createTrafficDetailsTable(int year, int month) {
        createRangeTables(year, month, "eps_traffic_details", (tableName) -> {
            epsInitialTrafficDataMapper.createEpsTrafficTable(tableName);
        });
    }

    private void createTrafficStatsTable(int year, int month) {
        createRangeTables(year, month, "initial_bandwidth_traffic", (tableName) -> {
            epsInitialTrafficDataMapper.createEpsInitialTrafficTable(tableName);
        });
    }


    /**
     * 通用创建表方法
     * @param year 年份
     * @param month 月份
     * @param tablePrefix 表前缀
     * @param creator 表创建函数
     */
    private void createRangeTables(int year, int month, String tablePrefix, Consumer<String> creator) {
        String[] ranges = {"1_10", "11_20", "21_31"};

        for (String range : ranges) {
            String tableName = String.format("%s_%d_%02d_%s", tablePrefix, year, month, range);
            try {
                creator.accept(tableName);
                log.info("成功创建表: {}", tableName);
            } catch (Exception e) {
                log.error("创建表失败: {}", tableName, e);
            }
        }
    }
    /**
     * 保存单条数据到对应分表
     * @param data 流量数据
     */
    @Override
    @Transactional
    public void save(EpsInitialTrafficData data) {
        if (data.getCreateTime() == null) {
            data.setCreateTime(DateUtils.getNowDate());
        }
        data.setTableName(TableRouterUtil.getTableName(DateUtil.dateToLocalDateTime(data.getCreateTime())));
        epsInitialTrafficDataMapper.insert(data);
    }

    /**
     * 批量保存数据到对应分表
     * @param epsInitialTrafficData 流量数据表
     */
    @Override
    @Transactional(rollbackFor = Exception.class, isolation = Isolation.READ_COMMITTED)
    public void saveBatch(EpsInitialTrafficData epsInitialTrafficData) {
        if (epsInitialTrafficData == null || epsInitialTrafficData.getDataList().isEmpty()) {
            return;
        }

        // 内存去重（基于唯一键）
        List<EpsInitialTrafficData> distinctList = epsInitialTrafficData.getDataList().stream()
                .filter(Objects::nonNull)
                .map(data -> {
                    EpsInitialTrafficData processed = new EpsInitialTrafficData();
                    BeanUtils.copyProperties(data, processed);
                    if (data.getCreateTime() == null) {
                        processed.setCreateTime(DateUtils.getNowDate());
                    }
                    return processed;
                })
                .collect(Collectors.collectingAndThen(
                        // 使用TreeSet按唯一键去重
                        Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(
                                d -> String.join("|",
                                        d.getClientId(),
                                        d.getMac(),
                                        d.getName(),
                                        d.getCreateTime().toString()
                                )
                        ))),
                        ArrayList::new
                ));

        // 按表名分组
        Map<String, List<EpsInitialTrafficData>> groupedData = distinctList.stream()
                .map(data -> {
                    data.setTableName(TableRouterUtil.getTableName(
                            data.getCreateTime().toInstant()
                                    .atZone(ZoneId.systemDefault())
                                    .toLocalDateTime()
                    ));
                    return data;
                })
                .collect(Collectors.groupingBy(
                        EpsInitialTrafficData::getTableName,
                        LinkedHashMap::new,
                        Collectors.toList()
                ));

        // 分表插入（带冲突降级）
        groupedData.forEach((tableName, list) -> {
            try {
                EpsInitialTrafficData batchData = new EpsInitialTrafficData();
                BeanUtils.copyProperties(epsInitialTrafficData, batchData);
                batchData.setTableName(tableName);
                batchData.setDataList(list);

                // 优先尝试批量插入
                epsInitialTrafficDataMapper.batchInsert(batchData);
            } catch (Exception e) {
                log.error("表 {} 插入失败", tableName, e);
                throw new RuntimeException("数据入库失败", e);
            }
        });
    }
    /**
     * 查询流量数据
     */
    @Override
    public List<EpsInitialTrafficData> query(EpsInitialTrafficData queryParam) {
        // 参数校验
//        if (StringUtils.isBlank(queryParam.getDeviceSn())) {
//            throw new IllegalArgumentException("设备序列号不能为空");
//        }

        // 获取涉及的表名
        Set<String> tableNames = TableRouterUtil.getTableNamesBetween(queryParam.getStartTime(), queryParam.getEndTime());

        // 并行查询各表
        return tableNames.parallelStream()
                .flatMap(tableName -> {
                    EpsInitialTrafficData condition = new EpsInitialTrafficData();
                    condition.setTableName(tableName);
                    condition.setClientId(queryParam.getClientId());
                    condition.setServiceSn(queryParam.getServiceSn());
                    condition.setStartTime(queryParam.getStartTime());
                    condition.setEndTime(queryParam.getEndTime());
                    condition.setBusinessId(queryParam.getBusinessId());
                    condition.setBusinessName(queryParam.getBusinessName());
                    return epsInitialTrafficDataMapper.selectByCondition(condition).stream();
                })
                .collect(Collectors.toList());
    }

    /**
     * 查询多台设备的流量数据
     * @param queryParam
     * @return
     */
    @Override
    public List<EpsInitialTrafficData> getTrafficListByClientIds(EpsInitialTrafficData queryParam) {

        // 获取涉及的表名
        Set<String> tableNames = TableRouterUtil.getTableNamesBetween(queryParam.getStartTime(), queryParam.getEndTime());

        // 并行查询各表
        return tableNames.parallelStream()
                .flatMap(tableName -> {
                    EpsInitialTrafficData condition = new EpsInitialTrafficData();
                    condition.setTableName(tableName);
                    condition.setStartTime(queryParam.getStartTime());
                    condition.setEndTime(queryParam.getEndTime());
                    condition.setBusinessId(queryParam.getBusinessId());
                    condition.setBusinessName(queryParam.getBusinessName());
                    condition.setClientIds(queryParam.getClientIds());
                    return epsInitialTrafficDataMapper.getTrafficListByClientIds(condition).stream();
                })
                .collect(Collectors.toList());
    }

    @Override
    public List<EpsInitialTrafficData> getAllTraficMsg(EpsInitialTrafficData queryParam) {

        // 获取涉及的表名
        Set<String> tableNames = TableRouterUtil.getTableNamesBetweenInitial(queryParam.getStartTime(), queryParam.getEndTime());
        // 并行查询各表
        return tableNames.parallelStream()
                .flatMap(tableName -> {
                    EpsInitialTrafficData condition = new EpsInitialTrafficData();
                    condition.setTableName(tableName);
                    condition.setStartTime(queryParam.getStartTime());
                    condition.setEndTime(queryParam.getEndTime());
                    condition.setName(queryParam.getName());
                    return epsInitialTrafficDataMapper.getAllTraficMsg(condition).stream();
                })
                .collect(Collectors.toList());
    }

    /**
     * 计算95带宽值/日
     * @param queryParam
     */
    @Override
    public void calculateBusiness95BandwidthDaily(EpsInitialTrafficData queryParam,
                                                  String dailyStartTime, String dailyEndTime, String calculationMode) {
        // 获取所有设备SN列表
        List<AllInterfaceName> snList = allInterfaceNameMapper.getAllDeviceSn(new AllInterfaceName());
        // 遍历处理每个设备
        snList.forEach(interfaceName -> {
            queryParam.setClientId(interfaceName.getClientId());
            calculateChangedDeviceBandwidth(queryParam, dailyStartTime, dailyEndTime, calculationMode);
        });
    }
    /**
     * 计算金山95带宽值/日
     * @param queryParam
     */
    @Override
    public void calculate95ByJinShan(EpsInitialTrafficData queryParam,
                                                  String dailyStartTime, String dailyEndTime, String calculationMode) {
        // 获取所有设备SN列表
        List<AllInterfaceName> snList = allInterfaceNameMapper.getAllDeviceSn(new AllInterfaceName());
        // 遍历处理每个设备
        snList.forEach(interfaceName -> {
            queryParam.setServiceSn(interfaceName.getDeviceSn());
            queryParam.setStartTime(dailyStartTime);
            queryParam.setEndTime(dailyEndTime);
            List<EpsInitialTrafficData> dataList = query(queryParam);

            if (!dataList.isEmpty()) {
                // 1. 提取并转换带宽值
                List<BigDecimal> speedsInMbps = dataList.stream()
                        .map(data -> CalculateUtil.parseSpeedToMbps(data.getMachineFlow(), calculationMode))
                        .sorted()
                        .collect(Collectors.toList());

                // 2. 计算95百分位
                BigDecimal percentile95 = CalculateUtil.calculatePercentile(speedsInMbps, 0.95);

                // 3. 保存结果
                EpsInitialTrafficData epsInitialTrafficData = dataList.get(0);
                epsInitialTrafficData.setResourceType("1");
                epsInitialTrafficData.setBandwidthType("8");
                saveBandwidthResult(epsInitialTrafficData, percentile95, dailyStartTime, calculationMode);
            }
        });
    }

    /**
     * 重新计算服务器95带宽值
     * @param epsNodeBandwidth 95带宽值收益详情
     * @param dailyStartTime 开始时间
     * @param dailyEndTime 结束时间
     */
    @Override
    public void recalculateServer95Bandwidth(EpsNodeBandwidth epsNodeBandwidth, String dailyStartTime, String dailyEndTime, String calculationMode ) {
        EpsInitialTrafficData epsInitialTrafficData = new EpsInitialTrafficData();
        epsInitialTrafficData.setStartTime(dailyStartTime);
        epsInitialTrafficData.setEndTime(dailyEndTime);
        epsInitialTrafficData.setServiceSn(epsNodeBandwidth.getHardwareSn());
        epsInitialTrafficData.setNodeName(epsNodeBandwidth.getNodeName());
        epsInitialTrafficData.setBusinessName(epsNodeBandwidth.getBusinessName());
        epsInitialTrafficData.setBusinessId(epsNodeBandwidth.getBusinessId());
        List<EpsInitialTrafficData> dataList = query(epsInitialTrafficData);
        if(!dataList.isEmpty()){
            // 1. 提取并转换带宽值
            List<BigDecimal> speedsInMbps = dataList.stream()
                    .map(data -> CalculateUtil.parseSpeedToMbps(data.getOutSpeed(), calculationMode))
                    .sorted()
                    .collect(Collectors.toList());

            // 2. 计算95百分位
            BigDecimal percentile95 = CalculateUtil.calculatePercentile(speedsInMbps, 0.95);

            // 3. 保存结果
            EpsInitialTrafficData initialTrafficData = dataList.get(0);
            initialTrafficData.setResourceType("1");
            initialTrafficData.setBandwidthType(epsNodeBandwidth.getBandwidthType());
            saveBandwidthResult(initialTrafficData, percentile95, dailyStartTime, calculationMode);
        }
    }

    /**
     * 计算服务器流量使用率（处理带单位的数据）
     * @return 包含总带宽、发送带宽和发送占比的Map
     */
    @Override
    public Map<String, Object> trafficRateByServer() {
        Map<String, Object> resultMap = new HashMap<>(3);

        // 初始化默认值
        resultMap.put("outSpeedTotal", BigDecimal.ZERO);
        resultMap.put("speedTotal", BigDecimal.ZERO);
        resultMap.put("outSpeedRate", BigDecimal.ZERO);

        // 获取近5分钟的流量数据
        List<EpsInitialTrafficData> dataList = getTrafficData();
        if (CollectionUtils.isEmpty(dataList)) {
            return resultMap;
        }

        BigDecimal total = BigDecimal.ZERO;
        BigDecimal outTotal = BigDecimal.ZERO;
        boolean hasValidData = false;

        // 计算总带宽和发送带宽
        for (EpsInitialTrafficData data : dataList) {
            // 处理发送带宽（假设outSpeed已经是标准单位）
            try {
                BigDecimal outSpeed = CalculateUtil.parseSpeedToMbps(data.getOutSpeed(), "1000");
                outTotal = outTotal.add(outSpeed);
            } catch (Exception e) {
                log.warn("Invalid outSpeed value: {}", data.getOutSpeed());
                continue;
            }

            // 处理总带宽（带单位的值如"10000Mb/s"）
            String speedWithUnit = data.getSpeed();
            if (speedWithUnit != null && !"Unknown!".equalsIgnoreCase(speedWithUnit)) {
                try {
                    // 移除单位部分（如"Mb/s"）
                    String numericPart = speedWithUnit.replaceAll("[^0-9.]", "");
                    BigDecimal speedValue = new BigDecimal(numericPart);
                    total = total.add(speedValue);
                    hasValidData = true;
                } catch (NumberFormatException e) {
                    log.warn("Invalid speed value format: {}", speedWithUnit);
                }
            }
        }

        // 存储计算结果
        resultMap.put("outSpeedTotal", outTotal.setScale(2, RoundingMode.HALF_UP));
        resultMap.put("speedTotal", total.setScale(2, RoundingMode.HALF_UP));

        // 计算发送带宽占比（只有存在有效数据时才计算）
        if (hasValidData && total.compareTo(BigDecimal.ZERO) != 0) {
            BigDecimal outSpeedRate = outTotal.divide(total, 4, RoundingMode.HALF_UP).multiply(new BigDecimal(100));
            resultMap.put("outSpeedRate", outSpeedRate);
        }

        return resultMap;
    }

    /**
     * 当前在线服务器发送带宽总流量
     * @return
     */
    @Override
    public BigDecimal sumTrafficByServer() {
        // 总带宽
        BigDecimal total = BigDecimal.ZERO;
        // 近5分钟的带宽明细
        List<EpsInitialTrafficData> dataList = getTrafficData();
        if(!dataList.isEmpty()){
            for (EpsInitialTrafficData initialTrafficData : dataList) {
                // 服务器发送带宽流量
                BigDecimal outSpeed = CalculateUtil.parseSpeedToMbps(initialTrafficData.getOutSpeed(), "1000");
                total = total.add(outSpeed);
            }
        }
        return total.setScale(0, RoundingMode.HALF_UP);
    }

    /**
     * 金山流量插入数据
     * @param epsInitialTrafficData
     * @return
     */
    @Override
    public int updateMachineTraffic(EpsInitialTrafficData epsInitialTrafficData) {
        int rows = epsInitialTrafficDataMapper.updateMachineTraffic(epsInitialTrafficData);
        return rows;
    }

    @Override
    public List<Map<String, Object>> getServerGraphicalAnalysisDaily(EpsInitialTrafficData queryParam) {

        // 拿到时间范围
        String startTime = queryParam.getStartTime();
        String endTime = queryParam.getEndTime();
        List<Map<String, Object>> resultList = new ArrayList<>();

        // 2. 解析日期范围
        LocalDate startDate = LocalDate.parse(startTime);
        LocalDate endDate = LocalDate.parse(endTime);

        // 3. 循环处理每一天
        for (LocalDate date = startDate; !date.isAfter(endDate); date = date.plusDays(1)) {
            // 构造当天的开始和结束时间（精确到秒）
            String dayStart = date.atStartOfDay().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
            String dayEnd = date.atTime(23, 59, 59).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));

            // 创建当天的查询条件
            EpsInitialTrafficData dailyQuery = new EpsInitialTrafficData();
            BeanUtils.copyProperties(queryParam, dailyQuery); // 复制原有属性
            dailyQuery.setStartTime(dayStart);
            dailyQuery.setEndTime(dayEnd);
            // 时间范围
            String timeRange = "从" + dayStart + "到" + dayEnd;

            // 根据clientId查询已经配置的接口
            String clientIds = queryParam.getClientIds();
            String[] clientIdArr = clientIds.split(",");
            if(clientIdArr != null){
                for (String clientId : clientIdArr) {
                    try {
                        // 查询95值
                        BigDecimal percentile95 = BigDecimal.ZERO;
                        EpsNodeBandwidth bandwidthQuery = new EpsNodeBandwidth();
                        bandwidthQuery.setBandwidthType("1");
                        bandwidthQuery.setCreateTime(DateUtils.parseDate(date));
                        bandwidthQuery.setCalculationMode(queryParam.getCalculationMode());
                        bandwidthQuery.setClientId(clientId);
                        List<EpsNodeBandwidth> epsNodeBandwidthList = epsNodeBandwidthMapper.selectEpsNodeBandwidthList(bandwidthQuery);

                        if(!epsNodeBandwidthList.isEmpty()){
                            EpsNodeBandwidth nodeBandwidth = epsNodeBandwidthList.get(0);
                            percentile95 = nodeBandwidth.getBandwidthResult();
                        }
                        dailyQuery.setClientIds(clientId);
                        Map<String, Object> resultMap = serverNetSpeedEcharts(dailyQuery, percentile95);
                        // 查询业务信息
                        String businessName = null;
                        EpsBusinessDeploy businessQuery = new EpsBusinessDeploy();
                        businessQuery.setClientId(clientId);
                        businessQuery.setReviewStatus(ReviewEnum.通过.getCode());
                        List<EpsBusinessDeploy> businessDeploys = epsBusinessDeployMapper.selectEpsBusinessDeployList(businessQuery);

                        if(!businessDeploys.isEmpty()){
                            businessName = businessDeploys.get(0).getBusinessName();
                        }

                        StringJoiner joiner = new StringJoiner("");
                        if (clientId != null) {
                            joiner.add("【" + clientId + "】");
                        }
                        if (businessName != null) {
                            joiner.add("【" + businessName + "】");
                        }
                        String name = joiner.toString();
                        resultMap.put("name", name);
                        resultMap.put("timeRange", timeRange);
                        resultList.add(resultMap);
                    } catch (Exception e){
                        e.printStackTrace();
                    }
                }
            }
        }
        return resultList.isEmpty() ? new ArrayList<>() : resultList;
    }

    /**
     * 图形分析-95带宽值/月
     * @param queryParam
     * @return
     */
    @Override
    public List<Map<String, Object>> getServerGraphicalAnalysisMonthy(EpsInitialTrafficData queryParam) {
        // 拿到时间范围
        String startTime = queryParam.getStartTime();
        String endTime = queryParam.getEndTime();
        List<Map<String, Object>> resultList = new ArrayList<>();
        // 2. 解析月份范围
        YearMonth start = YearMonth.parse(startTime);
        YearMonth end = YearMonth.parse(endTime);
        // 3. 循环处理每个月
        for (YearMonth month = start; !month.isAfter(end); month = month.plusMonths(1)) {
            // 获取当月的第一天和最后一天（精确到秒）
            String monthStart = month.atDay(1).atStartOfDay().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
            String monthEnd = month.atEndOfMonth().atTime(23, 59, 59)
                    .format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
            // 创建当天的查询条件
            EpsInitialTrafficData dailyQuery = new EpsInitialTrafficData();
            BeanUtils.copyProperties(queryParam, dailyQuery); // 复制原有属性
            dailyQuery.setStartTime(monthStart);
            dailyQuery.setEndTime(monthEnd);
            String timeRange = "从" + monthStart + "到" + monthEnd;
            // 根据clientId查询已经配置的接口
            String clientIds = queryParam.getClientIds();
            String[] clientIdArr = clientIds.split(",");
            if(clientIdArr != null){
                for (String clientId : clientIdArr) {
                    try {
                        // 查询95值
                        BigDecimal percentile95 = BigDecimal.ZERO;
                        EpsNodeBandwidth bandwidthQuery = new EpsNodeBandwidth();
                        bandwidthQuery.setBandwidthType("1");
                        bandwidthQuery.setCreateTime(DateUtils.parseDate(monthStart));
                        bandwidthQuery.setCalculationMode(queryParam.getCalculationMode());
                        bandwidthQuery.setClientId(clientId);
                        List<EpsNodeBandwidth> epsNodeBandwidthList = epsNodeBandwidthMapper.selectEpsNodeBandwidthList(bandwidthQuery);

                        if(!epsNodeBandwidthList.isEmpty()){
                            EpsNodeBandwidth nodeBandwidth = epsNodeBandwidthList.get(0);
                            percentile95 = nodeBandwidth.getBandwidthResult();
                        }
                        dailyQuery.setClientIds(clientId);
                        Map<String, Object> resultMap = serverNetSpeedEcharts(dailyQuery, percentile95);
                        // 查询业务信息
                        String businessName = null;
                        EpsBusinessDeploy businessQuery = new EpsBusinessDeploy();
                        businessQuery.setClientId(clientId);
                        businessQuery.setReviewStatus(ReviewEnum.通过.getCode());
                        List<EpsBusinessDeploy> businessDeploys = epsBusinessDeployMapper.selectEpsBusinessDeployList(businessQuery);

                        if(!businessDeploys.isEmpty()){
                            businessName = businessDeploys.get(0).getBusinessName();
                        }

                        StringJoiner joiner = new StringJoiner("");
                        if (clientId != null) {
                            joiner.add("【" + clientId + "】");
                        }
                        if (businessName != null) {
                            joiner.add("【" + businessName + "】");
                        }
                        String name = joiner.toString();
                        resultMap.put("name", name);
                        resultMap.put("timeRange", timeRange);
                        resultList.add(resultMap);
                    } catch (Exception e){
                        e.printStackTrace();
                    }
                }
            }
        }
        return resultList.isEmpty() ? new ArrayList<>() : resultList;
    }
    /**
     * 获取服务器网口网络速率
     * @param epsInitialTrafficData
     * @return
     */
    public Map<String, Object> serverNetSpeedEcharts(EpsInitialTrafficData epsInitialTrafficData, BigDecimal percentile95) {
        List<EpsInitialTrafficData> list = getTrafficListByClientIds(epsInitialTrafficData);
        if(!list.isEmpty()){
            try {
                list.forEach(data -> data.setPercentile95(SpeedUtils.mbitToBit(percentile95)));
                SpeedUtils.SpeedResult result = SpeedUtils.calculateWithStringTraffic(list, "inSpeed", "outSpeed");
                BigDecimal divisor = SpeedUtils.getDivisor(result.getRecommendedUnit());
                Map<String, Function<EpsInitialTrafficData, ?>> extractors = new LinkedHashMap<>();

                extractors.put("netOutSpeedData", info ->
                        info != null && info.getOutSpeed() != null ?
                                new BigDecimal(info.getOutSpeed()).divide(divisor, 0, RoundingMode.HALF_UP) :
                                0);
                extractors.put("netMachineFlowData", info ->
                        info != null && info.getMachineFlow() != null ?
                                new BigDecimal(info.getMachineFlow()).divide(divisor, 0, RoundingMode.HALF_UP) :
                                0);
                extractors.put("percentile95", info ->
                        info != null && info.getPercentile95() != null ?
                                info.getPercentile95().divide(divisor, 2, RoundingMode.HALF_UP) :
                                0);
                Map<String, Object> resultMap = EchartsDataUtils.buildEchartsData(list, EpsInitialTrafficData::getCreateTime, extractors);
                resultMap.put("other", result);
                resultMap.put("95value", percentile95);
                return resultMap;
            } catch (Exception e){
                e.printStackTrace();
            }
        }
        return new HashMap<>();
    }
    /**
     * 提取公共方法
     * @return
     */
    private List<EpsInitialTrafficData> getTrafficData(){
        // 获取当前时间
        LocalDateTime now = LocalDateTime.now();
        // 结束时间
        LocalDateTime endTime = now.minusSeconds(1);
        // 开始时间
        LocalDateTime startTime = now.minusMinutes(5);
        // 定义日期时间格式
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        // 格式化为字符串
        String dailyStartTime = startTime.format(formatter);
        String dailyEndTime = endTime.format(formatter);
        EpsInitialTrafficData epsInitialTrafficData = new EpsInitialTrafficData();
        epsInitialTrafficData.setStartTime(dailyStartTime);
        epsInitialTrafficData.setEndTime(dailyEndTime);
        List<EpsInitialTrafficData> dataList = query(epsInitialTrafficData);
        return dataList;
    }

    /**
     * 计算有业务变更设备的带宽
     */
    private void calculateChangedDeviceBandwidth(EpsInitialTrafficData queryParam,
                                                 String dailyStartTime,
                                                 String dailyEndTime, String calculationMode) {
        // 1. 获取业务变更记录（按时间降序）
        EpsMethodChangeRecord changeQuery = new EpsMethodChangeRecord();
        changeQuery.setClientId(queryParam.getClientId());
        changeQuery.setStartTime(dailyStartTime);
        changeQuery.setEndTime(dailyEndTime);
        List<EpsMethodChangeRecord> records = epsMethodChangeRecordMapper
                .selectEpsMethodChangeRecordList(changeQuery);

        if (!records.isEmpty()) {
            // 2. 确保按时间降序排列
            records.sort((r1, r2) -> r2.getCreateTime().compareTo(r1.getCreateTime()));

            // 3. 计算各时间段95值
            calculateTimeSegments95(queryParam, records, dailyStartTime, dailyEndTime, calculationMode);
        }else{
            calculateNormalDeviceBandwidth(queryParam, dailyStartTime, dailyEndTime, calculationMode);
        }
    }
    /**
     * 计算无业务变更设备的带宽
     */
    private void calculateNormalDeviceBandwidth(EpsInitialTrafficData queryParam,
                                                String dailyStartTime,
                                                String dailyEndTime, String calculationMode) {
        queryParam.setStartTime(dailyStartTime);
        queryParam.setEndTime(dailyEndTime);
        List<EpsInitialTrafficData> dataList = query(queryParam);

        if (!dataList.isEmpty()) {
            calculateAndSave95Bandwidth(dataList, dailyStartTime, queryParam.getDayOrMonth(), calculationMode);
        }
    }
    /**
     * 计算并保存95带宽值
     */
    private void calculateAndSave95Bandwidth(List<EpsInitialTrafficData> dataList, String dateTime, String dayOrMonth, String calculationMode) {
        if(!dataList.isEmpty()){
            // 1. 提取并转换带宽值
            List<BigDecimal> speedsInMbps = dataList.stream()
                    .map(data -> CalculateUtil.parseSpeedToMbps(data.getOutSpeed(), calculationMode))
                    .sorted()
                    .collect(Collectors.toList());

            // 2. 计算95百分位
            BigDecimal percentile95 = CalculateUtil.calculatePercentile(speedsInMbps, 0.95);

            // 3. 保存结果
            EpsInitialTrafficData epsInitialTrafficData = dataList.get(0);
            epsInitialTrafficData.setResourceType("1");
            if("1".equals(dayOrMonth)){
                epsInitialTrafficData.setBandwidthType("1");
            }
            if("2".equals(dayOrMonth)){
                epsInitialTrafficData.setBandwidthType("2");
            }
            saveBandwidthResult(epsInitialTrafficData, percentile95, dateTime, calculationMode);
        }
    }

    /**
     * 计算设备各时间段的95带宽值
     */
    private void calculateTimeSegments95(EpsInitialTrafficData queryParam,
                                         List<EpsMethodChangeRecord> records,
                                         String dailyStartTime,
                                         String dailyEndTime, String calculationMode) {
        // 1. 处理变更时间段（从最新到最早）
        String endTime = DateUtils.parseDateToStr(DATE_TIME_FORMATTER, records.get(0).getCreateTime());
        for (int i = 1; i < records.size(); i++) {
            String startTime = DateUtils.parseDateToStr(DATE_TIME_FORMATTER, records.get(i).getCreateTime());
            calculateSegment95(queryParam, startTime, endTime, calculationMode);
            endTime = startTime; // 移动时间窗口
        }

        // 2. 处理最早变更前的时间段（昨天00:00:00 ~ 最早变更时间）
        String earliestChangeTime = DateUtils.parseDateToStr(DATE_TIME_FORMATTER, records.get(records.size()-1).getCreateTime());
        calculateSegment95(queryParam, dailyStartTime, earliestChangeTime, calculationMode);

        // 3. 处理最后变更后的时间段（最新变更时间 ~ 昨天23:59:59）
        calculateSegment95(queryParam, endTime, dailyEndTime, calculationMode);
    }

    /**
     * 计算单个时间段的95带宽值
     */
    private void calculateSegment95(EpsInitialTrafficData queryParam, String startTime, String endTime, String calculationMode) {
        queryParam.setStartTime(startTime);
        queryParam.setEndTime(endTime);
        List<EpsInitialTrafficData> dataList = query(queryParam);
        if (!dataList.isEmpty()) {
            calculate95BandwidthDaily(dataList, startTime, queryParam.getDayOrMonth(), calculationMode);
        }
    }

    /**
     * 计算日95带宽值
     * @param dataList
     */
    private void calculate95BandwidthDaily(List<EpsInitialTrafficData> dataList, String startTime, String dayOrMonth, String calculationMode){
        // 1. 提取 outSpeed 并转换为 Mbps
        List<BigDecimal> speedsInMbps = dataList.stream()
                .map(data -> CalculateUtil.parseSpeedToMbps(data.getOutSpeed(), calculationMode))
                .sorted()
                .collect(Collectors.toList());

        // 2. 计算 95% 位置（向上取整）
        int total = speedsInMbps.size();
        int position = (int) Math.ceil(0.95 * total) - 1; // 转换为 0-based 索引
        if (position < 0){
            position = 0;
        }
        if (position >= total){
            position = total - 1;
        }

        // 3. 获取 95 值并四舍五入到两位小数
        BigDecimal percentile95 = speedsInMbps.get(position);
        BigDecimal dailyResult = percentile95.setScale(2, RoundingMode.HALF_UP);
        // 服务器信息
        EpsInitialTrafficData epsInitialTrafficData = dataList.get(0);
        epsInitialTrafficData.setResourceType("1");
        if("1".equals(dayOrMonth)){
            epsInitialTrafficData.setBandwidthType("1");
        }
        if("2".equals(dayOrMonth)){
            epsInitialTrafficData.setBandwidthType("2");
        }
        saveBandwidthResult(epsInitialTrafficData, dailyResult, startTime, calculationMode);
    }
    /**
     * 保存带宽结果
     */
    private void saveBandwidthResult(EpsInitialTrafficData data,
                                     BigDecimal result,
                                     String dateTime, String calculationMode) {
        EpsNodeBandwidth bandwidth = new EpsNodeBandwidth();
        bandwidth.setClientId(data.getClientId());
        bandwidth.setHardwareSn(data.getServiceSn());
        bandwidth.setCalculationMode(calculationMode);
        bandwidth.setBusinessId(data.getBusinessId());
        bandwidth.setBusinessName(data.getBusinessName());
        bandwidth.setResourceType(data.getResourceType());
        bandwidth.setBandwidthType(data.getBandwidthType());
        bandwidth.setCreateTime(DateUtils.parseDate(dateTime));
        // 查询此条数据是否存在
        List<EpsNodeBandwidth> exitsList = epsNodeBandwidthMapper.selectEpsNodeBandwidthList(bandwidth);
        bandwidth.setBandwidthResult(result);
        switch (data.getBandwidthType()){
            case "1":
                bandwidth.setBandwidth95Daily(result);
                break;
            case "2":
                bandwidth.setBandwidth95Monthly(result);
                break;
            case "3":
                bandwidth.setPackageBandwidthDaily(result);
                break;
            case "4":
                bandwidth.setAvgMonthlyBandwidth95(result);
                break;
            case "5":
                bandwidth.setEffectiveBandwidth95Daily(result);
                break;
            case "6":
                bandwidth.setEffectiveBandwidth95Monthly(result);
                break;
            case "7":
                bandwidth.setEffectiveAvgMonthlyBandwidth95(result);
                break;
            case "8":
                bandwidth.setMachineFlow(result);
                break;
            default:
                throw new IllegalArgumentException("Unknown bandwidthType: " + data.getBandwidthType());
        }
        // 根据clientId查询交换机上联
        RmEpsTopologyManagement topologQuery = new RmEpsTopologyManagement();
        topologQuery.setServerClientId(data.getClientId());
        List<RmEpsTopologyManagement> topologyList = rmEpsTopologyManagementMapper.selectRmEpsTopologyManagementList(topologQuery);
        if(!topologyList.isEmpty()){
            RmEpsTopologyManagement rmEpsTopologyManagement = topologyList.get(0);
            bandwidth.setUplinkSwitch(rmEpsTopologyManagement.getSwitchName());
            bandwidth.setInterfaceName(rmEpsTopologyManagement.getInterfaceName());
        }
        if(!exitsList.isEmpty()){
            bandwidth.setUpdateTime(DateUtils.getNowDate());
            bandwidth.setId(exitsList.get(0).getId());
            epsNodeBandwidthMapper.updateEpsNodeBandwidth(bandwidth);
        }else{
            bandwidth.setUpdateTime(DateUtils.getNowDate());
            epsNodeBandwidthMapper.insertEpsNodeBandwidth(bandwidth);
        }
    }

}
