package com.ruoyi.system.service.impl;

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

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

/**
 * 交换机监控信息Service业务层处理
 * 
 * @author gyt
 * @date 2025-08-26
 */
@Service
@Slf4j
public class InitialSwitchInfoDetailsServiceImpl implements IInitialSwitchInfoDetailsService
{
    @Autowired
    private InitialSwitchInfoDetailsMapper initialSwitchInfoDetailsMapper;
    @Autowired
    private RmEpsTopologyManagementMapper rmEpsTopologyManagementMapper;
    @Autowired
    private RmSwitchManagementMapper rmSwitchManagementMapper;
    @Autowired
    private AllInterfaceNameMapper allInterfaceNameMapper;
    @Autowired
    private EpsServerRevenueConfigMapper epsServerRevenueConfigMapper;
    @Autowired
    private EpsMethodChangeRecordMapper epsMethodChangeRecordMapper;
    @Autowired
    private EpsNodeBandwidthMapper epsNodeBandwidthMapper;
    @Autowired
    private RmSwitchInterfaceInfoMapper rmSwitchInterfaceInfoMapper;
    @Autowired
    private EpsBusinessDeployMapper epsBusinessDeployMapper;

    private static final String DATE_TIME_FORMATTER = "yyyy-MM-dd HH:mm:ss";

    /**
     * 查询交换机监控信息
     * 
     * @param id 交换机监控信息主键
     * @return 交换机监控信息
     */
    @Override
    public InitialSwitchInfoDetails selectInitialSwitchInfoDetailsById(Long id)
    {
        return initialSwitchInfoDetailsMapper.selectInitialSwitchInfoDetailsById(id);
    }

    /**
     * 查询交换机监控信息列表
     * 
     * @param initialSwitchInfoDetails 交换机监控信息
     * @return 交换机监控信息
     */
    @Override
    public List<InitialSwitchInfoDetails> selectInitialSwitchInfoDetailsList(InitialSwitchInfoDetails initialSwitchInfoDetails)
    {
        return initialSwitchInfoDetailsMapper.selectInitialSwitchInfoDetailsList(initialSwitchInfoDetails);
    }

    /**
     * 新增交换机监控信息
     * 
     * @param initialSwitchInfoDetails 交换机监控信息
     * @return 结果
     */
    @Override
    public int insertInitialSwitchInfoDetails(InitialSwitchInfoDetails initialSwitchInfoDetails)
    {
        initialSwitchInfoDetails.setCreateTime(DateUtils.getNowDate());
        return initialSwitchInfoDetailsMapper.insertInitialSwitchInfoDetails(initialSwitchInfoDetails);
    }

    /**
     * 修改交换机监控信息
     * 
     * @param initialSwitchInfoDetails 交换机监控信息
     * @return 结果
     */
    @Override
    public int updateInitialSwitchInfoDetails(InitialSwitchInfoDetails initialSwitchInfoDetails)
    {
        initialSwitchInfoDetails.setUpdateTime(DateUtils.getNowDate());
        return initialSwitchInfoDetailsMapper.updateInitialSwitchInfoDetails(initialSwitchInfoDetails);
    }

    /**
     * 批量删除交换机监控信息
     * 
     * @param ids 需要删除的交换机监控信息主键
     * @return 结果
     */
    @Override
    public int deleteInitialSwitchInfoDetailsByIds(Long[] ids)
    {
        return initialSwitchInfoDetailsMapper.deleteInitialSwitchInfoDetailsByIds(ids);
    }

    /**
     * 删除交换机监控信息信息
     * 
     * @param id 交换机监控信息主键
     * @return 结果
     */
    @Override
    public int deleteInitialSwitchInfoDetailsById(Long id)
    {
        return initialSwitchInfoDetailsMapper.deleteInitialSwitchInfoDetailsById(id);
    }
    /**
     * 保存交换机流量信息
     * @param initialSwitchInfoDetails
     */
    @Transactional(rollbackFor = Exception.class, isolation = Isolation.READ_COMMITTED)
    public R<String> autoSaveSwitchTraffic(InitialSwitchInfoDetails initialSwitchInfoDetails) {
        // 查询初始流量数据
        List<InitialSwitchInfoDetails> dataList = initialSwitchInfoDetailsMapper.getAllSwitchInfoMsg(initialSwitchInfoDetails);
        List<InitialSwitchInfoDetails> batchList = new ArrayList<>();
        if(!dataList.isEmpty()){
            for (InitialSwitchInfoDetails details : dataList) {
                // 取发送或接收流量最大值赋值到maxSpeed
                calculateMaxSpeed(details);
                // id自增
                details.setId(null);
                // 根据接口名称查询交换机信息
                String interfaceName = details.getName();
                RmEpsTopologyManagement rmEpsTopologyManagement = new RmEpsTopologyManagement();
                rmEpsTopologyManagement.setInterfaceName(interfaceName);
                rmEpsTopologyManagement.setClientId(details.getClientId());
                List<RmEpsTopologyManagement> managements = rmEpsTopologyManagementMapper.selectRmEpsTopologyManagementList(rmEpsTopologyManagement);
                // 赋值
                if(!managements.isEmpty()){
                    for (RmEpsTopologyManagement management : managements) {
                        details.setSwitchSn(management.getSwitchSn());
                        details.setSwitchName(management.getSwitchName());
                        details.setInterfaceDeviceType(management.getConnectedDeviceType());
                        details.setServerName(management.getServerName());
                        details.setServerPort(management.getServerPort());
                        details.setServerClientId(management.getServerClientId());
                        // 查询端口备注信息
                        RmSwitchInterfaceInfo queryOtheName = new RmSwitchInterfaceInfo();
                        queryOtheName.setClientId(details.getClientId());
                        queryOtheName.setInterfaceName(management.getInterfaceName());
                        List<RmSwitchInterfaceInfo> interfaceInfos = rmSwitchInterfaceInfoMapper.selectRmSwitchInterfaceInfoList(queryOtheName);
                        if(!interfaceInfos.isEmpty()){
                            // 接口别名
                            details.setInterfaceNameRemark(interfaceInfos.get(0).getInterfaceRemark());
                        }
                        // 根据服务器sn查询业务
                        if(management.getServerClientId() != null){
                            String serverClientId = management.getServerClientId();
                            // 查询业务信息
                            EpsBusinessDeploy queryBD = new EpsBusinessDeploy();
                            queryBD.setClientId(serverClientId);
                            queryBD.setReviewStatus(ReviewEnum.通过.getCode());
                            List<EpsBusinessDeploy> businessDeploys = epsBusinessDeployMapper.selectEpsBusinessDeployList(queryBD);
                            if(!businessDeploys.isEmpty()){
                                details.setBusinessCode(businessDeploys.get(0).getBusinessCode());
                                details.setBusinessName(businessDeploys.get(0).getBusinessName());
                            }
                        }else {
                            details.setBusinessCode(null);
                            details.setBusinessName(null);
                        }
                        batchList.add(details);
                    }
                }else{
                    batchList.add(details);
                }
            }
        }
        initialSwitchInfoDetails.setDataList(batchList);
        if(batchList.isEmpty()){
            return R.fail("交换机流量数据为空");
        }else{
            // 流量相关数据入库
            try {
                initialSwitchInfoDetailsMapper.saveBatchSwitchTraffic(initialSwitchInfoDetails);
                log.info("交换机流量数据批量入库成功，数据量：{}", batchList.size());
                // 接口名称保存
                processSwitchInterfaceNames(batchList);
                return R.ok("数据保存成功");
            } catch (Exception e) {
                log.error("交换机流量数据入库失败，数据量：{}，错误原因：{}",
                        batchList.size(), e.getMessage(), e);
                return R.fail("数据保存失败：" + e.getMessage());
            }
        }
    }
    /**
     * 辅助方法
     * 获取 inSpeed 和 outSpeed 的最大值并设置到 maxSpeed
     * @param switchInfo 包含速度信息的实体类
     */
    public static void calculateMaxSpeed(InitialSwitchInfoDetails switchInfo) {
        if (switchInfo == null) {
            return;
        }
        // 获取 inSpeed 和 outSpeed
        BigDecimal inSpeed = switchInfo.getInSpeed();
        BigDecimal outSpeed = switchInfo.getOutSpeed();
        // 处理可能为null的情况
        if (inSpeed == null && outSpeed == null) {
            switchInfo.setMaxSpeed(null);
            return;
        }
        if (inSpeed == null) {
            switchInfo.setMaxSpeed(outSpeed);
            return;
        }
        if (outSpeed == null) {
            switchInfo.setMaxSpeed(inSpeed);
            return;
        }
        // 比较并设置最大值
        switchInfo.setMaxSpeed(inSpeed.compareTo(outSpeed) > 0 ? inSpeed : outSpeed);
    }
    /**
     * 批量处理接口名称
     */
    private void processSwitchInterfaceNames(List<InitialSwitchInfoDetails> initialSwitchInfoDetails) {
        // 分类处理：新增列表 vs 更新列表
        List<AllInterfaceName> namesToInsert = new ArrayList<>();
        List<AllInterfaceName> namesToUpdate = new ArrayList<>();

        initialSwitchInfoDetails.forEach(data -> {
            String name = data.getName();
            String ip = data.getSwitchIp();
            String clientId = data.getClientId();
            if (StringUtils.isBlank(name) || StringUtils.isBlank(ip) || StringUtils.isBlank(clientId)) {
                return;
            }
            AllInterfaceName record = new AllInterfaceName();
            record.setInterfaceName(name);
            record.setClientId(data.getClientId());
            record.setResourceType("2");
            record.setDeviceSn(data.getServerSn());
            record.setNodeName(data.getServerName());
            record.setServerPort(data.getServerPort());
            record.setInterfaceDeviceType(data.getInterfaceDeviceType());
            record.setSwitchName(data.getSwitchName());
            record.setSwitchSn(data.getSwitchSn());
            record.setSwitchIp(data.getSwitchIp());
            List<AllInterfaceName> existingNames = allInterfaceNameMapper.selectByNames(record);
            // 根据服务器sn查询业务
            if(data.getServerSn() != null){
                EpsServerRevenueConfig epsServerRevenueConfig = new EpsServerRevenueConfig();
                epsServerRevenueConfig.setHardwareSn(data.getServerSn());
                List<EpsServerRevenueConfig> businessList = epsServerRevenueConfigMapper.selectEpsServerRevenueConfigList(epsServerRevenueConfig);
                if(!businessList.isEmpty()){
                    EpsServerRevenueConfig revenueConfig = businessList.get(0);
                    record.setBusinessName(revenueConfig.getBusinessName());
                    record.setBusinessCode(revenueConfig.getBusinessCode());
                }
            }else {
                record.setBusinessCode(null);
                record.setBusinessName(null);
            }
            // 判断是否需要更新
            if (!existingNames.isEmpty()) {
                for (AllInterfaceName existingName : existingNames) {
                    if(isRecordChanged(existingName,record)){
                        record.setId(existingName.getId()); // 保留原ID
                        // 检查是否已经存在于更新列表中
                        boolean alreadyInUpdateList = namesToUpdate.stream()
                                .anyMatch(item -> item.getId() != null && item.getId().equals(existingName.getId()));
                        if (!alreadyInUpdateList) {
                            namesToUpdate.add(record);
                        }
                    }
                }
            } else {
                // 检查namesToInsert中是否已有相同记录
                boolean alreadyInInsertList = namesToInsert.stream()
                        .anyMatch(item -> item.getInterfaceName().equals(name)
                                && item.getClientId().equals(clientId)
                                && item.getSwitchIp().equals(ip));

                if (!alreadyInInsertList) {
                    namesToInsert.add(record);
                }
            }
        });

        // 批量操作数据库
        if (!namesToInsert.isEmpty()) {
            try {
                allInterfaceNameMapper.batchInsert(namesToInsert);
                log.info("新增接口名称数量：{}", namesToInsert.size());
            } catch (DuplicateKeyException e) {
                // 如果批量插入出现重复，转为逐条插入（带异常处理）
                log.warn("批量插入出现重复，转为逐条处理");
                namesToInsert.forEach(record -> {
                    try {
                        allInterfaceNameMapper.insertAllInterfaceName(record);
                    } catch (DuplicateKeyException ex) {
                        // 重复记录转为更新
                        AllInterfaceName query = new AllInterfaceName();
                        query.setInterfaceName(record.getInterfaceName());
                        query.setClientId(record.getClientId());
                        query.setServerIp(record.getServerIp());

                        List<AllInterfaceName> existing = allInterfaceNameMapper.selectByNames(query);
                        if (!existing.isEmpty()) {
                            record.setId(existing.get(0).getId());
                            allInterfaceNameMapper.updateAllInterfaceName(record);
                        }
                    }
                });
            }
        }

        if (!namesToUpdate.isEmpty()) {
            allInterfaceNameMapper.batchUpdate(namesToUpdate);
            log.info("更新接口名称数量：{}", namesToUpdate.size());
        }
    }

    // 辅助方法：检查记录是否有变化
    private boolean isRecordChanged(AllInterfaceName oldRecord, AllInterfaceName newRecord) {
        return !Objects.equals(oldRecord.getDeviceSn(), newRecord.getDeviceSn()) ||
                !Objects.equals(oldRecord.getNodeName(), newRecord.getNodeName()) ||
                !Objects.equals(oldRecord.getServerPort(), newRecord.getServerPort()) ||
                !Objects.equals(oldRecord.getInterfaceDeviceType(), newRecord.getInterfaceDeviceType()) ||
                !Objects.equals(oldRecord.getSwitchName(), newRecord.getSwitchName()) ||
                !Objects.equals(oldRecord.getBusinessCode(), newRecord.getBusinessCode()) ||
                !Objects.equals(oldRecord.getBusinessName(), newRecord.getBusinessName()) ||
                !Objects.equals(oldRecord.getSwitchSn(), newRecord.getSwitchSn()) ||
                !Objects.equals(oldRecord.getSwitchIp(), newRecord.getSwitchIp());
    }

    public void calculateSwitch95BandwidthDaily(InitialSwitchInfoDetails queryParam, String dailyStartTime,
                                                String dailyEndTime, String calculationMode) {
        // 查询所有的交换机SN列表
        AllInterfaceName allInterfaceName = new AllInterfaceName();
        List<AllInterfaceName> switchSnList = allInterfaceNameMapper.getAllSwitchSn(allInterfaceName);

        // 遍历处理每个交换机
        switchSnList.forEach(interfaceName -> {
            queryParam.setClientId(interfaceName.getClientId());
            processSwitchBandwidth(queryParam, dailyStartTime, dailyEndTime, calculationMode);
        });
    }

    /**
     * 重新计算交换机95带宽值
     * @param epsNodeBandwidth 95带宽值收益详情
     * @param dailyStartTime 开始时间
     * @param dailyEndTime 结束时间
     */
    @Override
    public void recalculateSwitch95Bandwidth(EpsNodeBandwidth epsNodeBandwidth, String dailyStartTime,
                                             String dailyEndTime, String calculationMode) {
        InitialSwitchInfoDetails switchInfoDetails = new InitialSwitchInfoDetails();
        switchInfoDetails.setClientId(epsNodeBandwidth.getClientId());
        switchInfoDetails.setStartTime(dailyStartTime);
        switchInfoDetails.setEndTime(dailyEndTime);
        switchInfoDetails.setSwitchSn(epsNodeBandwidth.getSwitchSn());
        switchInfoDetails.setSwitchName(epsNodeBandwidth.getUplinkSwitch());
        switchInfoDetails.setServerSn(epsNodeBandwidth.getHardwareSn());
        switchInfoDetails.setInterfaceDeviceType(epsNodeBandwidth.getInterfaceLinkDeviceType());
        switchInfoDetails.setName(epsNodeBandwidth.getInterfaceName());
        switchInfoDetails.setBusinessCode(epsNodeBandwidth.getBusinessId());
        switchInfoDetails.setBusinessName(epsNodeBandwidth.getBusinessName());
        List<InitialSwitchInfoDetails> dataList = initialSwitchInfoDetailsMapper
                .selectInitialSwitchInfoDetailsList(switchInfoDetails);
        if(!dataList.isEmpty()){
            // 1. 提取并转换带宽值
            List<BigDecimal> speedsInMbps = dataList.stream()
                    .map(data -> {
                        // 根据 interfaceDeviceType 选择 inSpeed 或 outSpeed
                        String speed = data.getMaxSpeed() != null ? data.getMaxSpeed().toString() : BigDecimal.ZERO.toString();
                        // 如果 speed 是纯数字，补充单位 "B/S"（Bytes/s）
                        if (speed.matches("^\\d+(\\.\\d+)?$")) {
                            speed += " B/S";
                        }
                        return CalculateUtil.parseSpeedToMbps(speed, calculationMode);
                    })
                    .sorted()
                    .collect(Collectors.toList());

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

            // 3. 保存结果
            InitialSwitchInfoDetails switchInfo = dataList.get(0);
            switchInfo.setResourceType("2");
            switchInfo.setBandwidthType(epsNodeBandwidth.getBandwidthType());
            saveSwitchBandwidthResult(switchInfo, percentile95, dailyStartTime, calculationMode);
        }
    }

    /**
     * 交换机相关数据
     * @param epsNodeBandwidth
     * @param dailyStartTime
     * @param dailyEndTime
     * @return
     */
    @Override
    public List<InitialSwitchInfoDetails> getRelevantSwitch(EpsNodeBandwidth epsNodeBandwidth, String dailyStartTime, String dailyEndTime) {
        InitialSwitchInfoDetails switchInfoDetails = new InitialSwitchInfoDetails();
        switchInfoDetails.setStartTime(dailyStartTime);
        switchInfoDetails.setEndTime(dailyEndTime);
        switchInfoDetails.setSwitchSn(epsNodeBandwidth.getSwitchSn());
//        switchInfoDetails.setSwitchName(epsNodeBandwidth.getUplinkSwitch());
        switchInfoDetails.setServerSn(epsNodeBandwidth.getHardwareSn());
        switchInfoDetails.setInterfaceDeviceType(epsNodeBandwidth.getInterfaceLinkDeviceType());
        switchInfoDetails.setName(epsNodeBandwidth.getInterfaceName());
        switchInfoDetails.setBusinessCode(epsNodeBandwidth.getBusinessId());
//        switchInfoDetails.setBusinessName(epsNodeBandwidth.getBusinessName());
        List<InitialSwitchInfoDetails> dataList = initialSwitchInfoDetailsMapper
                .selectInitialSwitchInfoDetailsList(switchInfoDetails);
        return dataList;
    }

    @Override
    public BigDecimal sumTrafficBySwitch() {
        // 获取当前时间
        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);
        BigDecimal total = BigDecimal.ZERO;
        InitialSwitchInfoDetails switchInfoDetails = new InitialSwitchInfoDetails();
        switchInfoDetails.setStartTime(dailyStartTime);
        switchInfoDetails.setEndTime(dailyEndTime);
        List<InitialSwitchInfoDetails> dataList = initialSwitchInfoDetailsMapper
                .selectInitialSwitchInfoDetailsList(switchInfoDetails);
        if(!dataList.isEmpty()){
            for (InitialSwitchInfoDetails initialSwitchInfoDetails : dataList) {
                // 交换机接收带宽流量
                String speed = initialSwitchInfoDetails.getInSpeed() != null ? initialSwitchInfoDetails.getInSpeed().toString() : BigDecimal.ZERO.toString();
                // 如果 speed 是纯数字，补充单位 "B/S"（Bytes/s）
                if (speed.matches("^\\d+(\\.\\d+)?$")) {
                    speed += " B/S";
                }
                BigDecimal inSpeed = CalculateUtil.parseSpeedToMbps(speed, "1000");
                total = total.add(inSpeed);
            }
        }
        return total.setScale(0, RoundingMode.HALF_UP);
    }


    /**
     * 处理单个交换机的带宽计算
     */
    private void processSwitchBandwidth(InitialSwitchInfoDetails queryParam,
                                        String dailyStartTime,
                                        String dailyEndTime, String calculationMode) {
        // 根据交换机sn查询连接的服务器sn
        RmEpsTopologyManagement management = new RmEpsTopologyManagement();
        management.setClientId(queryParam.getClientId());
        List<RmEpsTopologyManagement> serverSnList = rmEpsTopologyManagementMapper.selectRmEpsTopologyManagementList(management);
        if(!serverSnList.isEmpty()){
            for (RmEpsTopologyManagement rmEpsTopologyManagement : serverSnList) {
                queryParam.setName(rmEpsTopologyManagement.getInterfaceName());
                if("1".equals(rmEpsTopologyManagement.getConnectedDeviceType()) && rmEpsTopologyManagement.getServerClientId() != null){
                    queryParam.setServerClientId(rmEpsTopologyManagement.getServerClientId());
                    // 根据业务变更情况选择计算方式
                    calculateChangedSwitchBandwidth(queryParam, dailyStartTime, dailyEndTime, calculationMode);
                }else{
                    queryParam.setServerClientId(null);
                    calculateNormalSwitchBandwidth(queryParam, dailyStartTime, dailyEndTime, calculationMode);
                }
            }
        }
    }

    /**
     * 判断是否为流量型业务变更
     */
    private boolean hasTrafficMethodChanged(List<EpsServerRevenueConfig> changedList) {
        return !changedList.isEmpty() &&
                "1".equals(changedList.get(0).getChanged()) &&
                "1".equals(changedList.get(0).getRevenueMethod());
    }
    /**
     * 计算有业务变更交换机的带宽
     */
    private void calculateChangedSwitchBandwidth(InitialSwitchInfoDetails queryParam,
                                                 String dailyStartTime,
                                                 String dailyEndTime, String calculationMode) {
        // 获取业务变更记录（按时间降序）
        EpsMethodChangeRecord changeQuery = new EpsMethodChangeRecord();
        changeQuery.setClientId(queryParam.getServerClientId());
        changeQuery.setStartTime(dailyStartTime);
        changeQuery.setEndTime(dailyEndTime);
        List<EpsMethodChangeRecord> records = epsMethodChangeRecordMapper
                .selectEpsMethodChangeRecordList(changeQuery);

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

            // 计算各时间段95值
            calculateSwitchTimeSegments95(queryParam, records, dailyStartTime, dailyEndTime, calculationMode);
        }else {
            calculateNormalSwitchBandwidth(queryParam, dailyStartTime, dailyEndTime, calculationMode);
        }
    }

    /**
     * 计算无业务变更交换机的带宽
     */
    private void calculateNormalSwitchBandwidth(InitialSwitchInfoDetails queryParam,
                                                String dailyStartTime,
                                                String dailyEndTime, String calculationMode) {
        queryParam.setStartTime(dailyStartTime);
        queryParam.setEndTime(dailyEndTime);
        List<InitialSwitchInfoDetails> dataList = initialSwitchInfoDetailsMapper
                .selectInitialSwitchInfoDetailsList(queryParam);

        if (!dataList.isEmpty()) {
            calculateAndSaveSwitch95Bandwidth(dataList, dailyStartTime, queryParam.getDayOrMonth(), calculationMode);
        }
    }

    /**
     * 计算并保存交换机95带宽值
     */
    private void calculateAndSaveSwitch95Bandwidth(List<InitialSwitchInfoDetails> dataList, String dateTime,
                                                   String dayOrMonth, String calculationMode) {
        if(!dataList.isEmpty()){
            // 1. 提取并转换带宽值
            List<BigDecimal> speedsInMbps = dataList.stream()
                    .map(data -> {
                        // 根据 interfaceDeviceType 选择 inSpeed 或 outSpeed
                        String speed = data.getMaxSpeed() != null ? data.getMaxSpeed().toString() : BigDecimal.ZERO.toString();
                        // 如果 speed 是纯数字，补充单位 "B/S"（Bytes/s）
                        if (speed.matches("^\\d+(\\.\\d+)?$")) {
                            speed += " B/S";
                        }
                        return CalculateUtil.parseSpeedToMbps(speed, calculationMode);
                    })
                    .sorted()
                    .collect(Collectors.toList());

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

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

    /**
     * 计算交换机各时间段的95带宽值
     */
    private void calculateSwitchTimeSegments95(InitialSwitchInfoDetails 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());
            calculateSwitchSegment95(queryParam, startTime, endTime, calculationMode);
            endTime = startTime; // 移动时间窗口
        }

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

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

    /**
     * 计算交换机单个时间段的95带宽值
     */
    private void calculateSwitchSegment95(InitialSwitchInfoDetails queryParam, String startTime, String endTime, String calculationMode) {
        queryParam.setStartTime(startTime);
        queryParam.setEndTime(endTime);
        List<InitialSwitchInfoDetails> dataList = initialSwitchInfoDetailsMapper
                .selectInitialSwitchInfoDetailsList(queryParam);
        if (!dataList.isEmpty()) {
            calculateSwitch95BandwidthDaily(dataList, startTime, queryParam.getDayOrMonth(), calculationMode);
        }
    }

    /**
     * 计算交换机日95带宽值
     */
    private void calculateSwitch95BandwidthDaily(List<InitialSwitchInfoDetails> dataList,
                                                 String startTime, String dayOrMonth, String calculationMode) {
        // 1. 提取并转换带宽值
        List<BigDecimal> speedsInMbps = dataList.stream()
                .map(data -> {
                    // 根据 interfaceDeviceType 选择 inSpeed 或 outSpeed
                    String speed = data.getMaxSpeed() != null ? data.getMaxSpeed().toString() : BigDecimal.ZERO.toString();
                    if (speed.matches("^\\d+(\\.\\d+)?$")) {
                        speed += " B/S";
                    }
                    return CalculateUtil.parseSpeedToMbps(speed, calculationMode);
                })
                .sorted()
                .collect(Collectors.toList());

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

        // 3. 保存结果
        InitialSwitchInfoDetails switchInfo = dataList.get(0);
        switchInfo.setResourceType("2");
        if("1".equals(dayOrMonth)){
            switchInfo.setBandwidthType("1");
        }
        if("2".equals(dayOrMonth)){
            switchInfo.setBandwidthType("2");
        }
        saveSwitchBandwidthResult(switchInfo, dailyResult, startTime, calculationMode);
    }

    /**
     * 保存交换机带宽结果
     */
    private void saveSwitchBandwidthResult(InitialSwitchInfoDetails data,
                                           BigDecimal result,
                                           String dateTime, String calculationMode) {
        EpsNodeBandwidth bandwidth = new EpsNodeBandwidth();
        // 根据clientId查询交换机名称
        RmSwitchManagement query = new RmSwitchManagement();
        query.setClientId(data.getClientId());
        List<RmSwitchManagement> switchMsgList = rmSwitchManagementMapper.selectRmSwitchManagementList(query);
        if(!switchMsgList.isEmpty()){
            RmSwitchManagement switchManagement = switchMsgList.get(0);
            bandwidth.setUplinkSwitch(switchManagement.getSwitchName());
        }
        bandwidth.setBusinessName(data.getBusinessName());
        bandwidth.setBusinessId(data.getBusinessCode());
        bandwidth.setClientId(data.getClientId());
        bandwidth.setHardwareSn(data.getServerSn());
        bandwidth.setCalculationMode(calculationMode);
        bandwidth.setSwitchSn(data.getSwitchSn());
        bandwidth.setInterfaceName(data.getName());
        bandwidth.setRemark1(data.getInterfaceNameRemark());
        bandwidth.setServerClientId(data.getServerClientId());
        bandwidth.setResourceType(data.getResourceType());
        bandwidth.setBandwidthType(data.getBandwidthType());
        bandwidth.setInterfaceLinkDeviceType(data.getInterfaceDeviceType());
        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;
            default:
                throw new IllegalArgumentException("Unknown bandwidthType: " + data.getBandwidthType());
        }
        if(!exitsList.isEmpty()){
            bandwidth.setUpdateTime(DateUtils.getNowDate());
            bandwidth.setId(exitsList.get(0).getId());
            epsNodeBandwidthMapper.updateEpsNodeBandwidth(bandwidth);
        }else{
            bandwidth.setUpdateTime(DateUtils.getNowDate());
            epsNodeBandwidthMapper.insertEpsNodeBandwidth(bandwidth);
        }
    }
    /**
     * 图形分析 - 日95
     * @param initialSwitchInfoDetails
     * @return
     */
    @Override
    public List<Map<String, Object>> getGraphicalAnalysisDaily(InitialSwitchInfoDetails initialSwitchInfoDetails) {
        // 拿到时间范围
        String startTime = initialSwitchInfoDetails.getStartTime();
        String endTime = initialSwitchInfoDetails.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"));
            // 时间范围
            String timeRange = "从" + dayStart + "到" + dayEnd;
            // 创建当天的查询条件
            InitialSwitchInfoDetails dailyQuery = new InitialSwitchInfoDetails();
            BeanUtils.copyProperties(initialSwitchInfoDetails, dailyQuery); // 复制原有属性
            dailyQuery.setStartTime(dayStart);
            dailyQuery.setEndTime(dayEnd);
            // 根据交换机名称查询clientId
            String clientIds = initialSwitchInfoDetails.getClientIds();
            String[] clientIdArr = clientIds.split(",");
            for (String clientId : clientIdArr) {
                // 根据clientId查询已经配置的接口
                RmEpsTopologyManagement queryParam = new RmEpsTopologyManagement();
                queryParam.setClientId(clientId);
                List<RmEpsTopologyManagement> rmEpsTopologyManagements = rmEpsTopologyManagementMapper.selectRmEpsTopologyManagementList(queryParam);
                if(!rmEpsTopologyManagements.isEmpty()){
                    for (RmEpsTopologyManagement rmEpsTopologyManagement : rmEpsTopologyManagements) {
                        try {
                            // 查询95值
                            BigDecimal percentile95 = BigDecimal.ZERO;
                            EpsNodeBandwidth query = new EpsNodeBandwidth();
                            query.setBandwidthType("1");
                            query.setCreateTime(DateUtils.parseDate(date));
                            query.setCalculationMode(initialSwitchInfoDetails.getCalculationMode());
                            query.setClientId(clientId);
                            query.setInterfaceName(rmEpsTopologyManagement.getInterfaceName());
                            List<EpsNodeBandwidth> epsNodeBandwidthList = epsNodeBandwidthMapper.selectEpsNodeBandwidthList(query);
                            if(!epsNodeBandwidthList.isEmpty()){
                                EpsNodeBandwidth nodeBandwidth = epsNodeBandwidthList.get(0);
                                percentile95 = nodeBandwidth.getBandwidthResult();
                            }
                            dailyQuery.setName(rmEpsTopologyManagement.getInterfaceName());
                            Map<String, Object> resultMap = switchNetSpeedEcharts(dailyQuery, percentile95);
                            // 查询端口备注信息
                            RmSwitchInterfaceInfo queryOtheName = new RmSwitchInterfaceInfo();
                            queryOtheName.setClientId(clientId);
                            queryOtheName.setInterfaceName(rmEpsTopologyManagement.getInterfaceName());
                            List<RmSwitchInterfaceInfo> interfaceInfos = rmSwitchInterfaceInfoMapper.selectRmSwitchInterfaceInfoList(queryOtheName);
                            String otherName = null;
                            if(!interfaceInfos.isEmpty()){
                                otherName = interfaceInfos.get(0).getInterfaceRemark();
                            }
                            // 查询业务信息
                            String businessName = null;
                            EpsBusinessDeploy queryBD = new EpsBusinessDeploy();
                            queryBD.setClientId(clientId);
                            queryBD.setReviewStatus(ReviewEnum.通过.getCode());
                            List<EpsBusinessDeploy> businessDeploys = epsBusinessDeployMapper.selectEpsBusinessDeployList(queryBD);
                            if(!businessDeploys.isEmpty()){
                                businessName = businessDeploys.get(0).getBusinessName();
                            }
                            StringJoiner joiner = new StringJoiner("");
                            if (rmEpsTopologyManagement.getSwitchName() != null) {
                                joiner.add("【" + rmEpsTopologyManagement.getSwitchName() + "】");
                            }
                            if (rmEpsTopologyManagement.getInterfaceName() != null) {
                                joiner.add("【" + rmEpsTopologyManagement.getInterfaceName() + "】");
                            }
                            if (otherName != null) {
                                joiner.add("【" + otherName + "】");
                            }
                            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 initialSwitchInfoDetails
     * @return
     */
    @Override
    public List<Map<String, Object>> getGraphicalAnalysisMonthy(InitialSwitchInfoDetails initialSwitchInfoDetails) {
        // 拿到时间范围
        String startTime = initialSwitchInfoDetails.getStartTime();
        String endTime = initialSwitchInfoDetails.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"));

            // 创建当天的查询条件
            InitialSwitchInfoDetails dailyQuery = new InitialSwitchInfoDetails();
            BeanUtils.copyProperties(initialSwitchInfoDetails, dailyQuery); // 复制原有属性
            dailyQuery.setStartTime(monthStart);
            dailyQuery.setEndTime(monthEnd);
            // 时间范围
            String timeRange = "从" + monthStart + "到" + monthEnd;
            // 根据交换机名称查询clientId
            String clientIds = initialSwitchInfoDetails.getClientIds();
            String[] clientIdArr = clientIds.split(",");
            for (String clientId : clientIdArr) {
                // 根据clientId查询已经配置的接口
                RmEpsTopologyManagement queryParam = new RmEpsTopologyManagement();
                queryParam.setClientId(clientId);
                List<RmEpsTopologyManagement> rmEpsTopologyManagements = rmEpsTopologyManagementMapper.selectRmEpsTopologyManagementList(queryParam);
                if(!rmEpsTopologyManagements.isEmpty()){
                    for (RmEpsTopologyManagement rmEpsTopologyManagement : rmEpsTopologyManagements) {
                        try {
                            // 查询95值
                            BigDecimal percentile95 = BigDecimal.ZERO;
                            EpsNodeBandwidth query = new EpsNodeBandwidth();
                            query.setBandwidthType("1");
                            query.setCreateTime(DateUtils.parseDate(monthStart));
                            query.setCalculationMode(initialSwitchInfoDetails.getCalculationMode());
                            query.setClientId(clientId);
                            List<EpsNodeBandwidth> epsNodeBandwidthList = epsNodeBandwidthMapper.selectEpsNodeBandwidthList(query);
                            if(!epsNodeBandwidthList.isEmpty()){
                                EpsNodeBandwidth nodeBandwidth = epsNodeBandwidthList.get(0);
                                percentile95 = nodeBandwidth.getBandwidthResult();
                            }
                            dailyQuery.setName(rmEpsTopologyManagement.getInterfaceName());
                            Map<String, Object> resultMap = switchNetSpeedEcharts(dailyQuery, percentile95);
                            // 查询端口备注信息
                            RmSwitchInterfaceInfo queryOtheName = new RmSwitchInterfaceInfo();
                            queryOtheName.setClientId(clientId);
                            queryOtheName.setInterfaceName(rmEpsTopologyManagement.getInterfaceName());
                            List<RmSwitchInterfaceInfo> interfaceInfos = rmSwitchInterfaceInfoMapper.selectRmSwitchInterfaceInfoList(queryOtheName);
                            String otherName = null;
                            if(!interfaceInfos.isEmpty()){
                                otherName = interfaceInfos.get(0).getInterfaceRemark();
                            }
                            // 查询业务信息
                            String businessName = null;
                            EpsBusinessDeploy queryBD = new EpsBusinessDeploy();
                            queryBD.setClientId(clientId);
                            queryBD.setReviewStatus(ReviewEnum.通过.getCode());
                            List<EpsBusinessDeploy> businessDeploys = epsBusinessDeployMapper.selectEpsBusinessDeployList(queryBD);
                            if(!businessDeploys.isEmpty()){
                                businessName = businessDeploys.get(0).getBusinessName();
                            }
                            StringJoiner joiner = new StringJoiner("");
                            if (rmEpsTopologyManagement.getSwitchName() != null) {
                                joiner.add("【" + rmEpsTopologyManagement.getSwitchName() + "】");
                            }
                            if (rmEpsTopologyManagement.getInterfaceName() != null) {
                                joiner.add("【" + rmEpsTopologyManagement.getInterfaceName() + "】");
                            }
                            if (otherName != null) {
                                joiner.add("【" + otherName + "】");
                            }
                            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 initialSwitchInfoDetails
     * @return
     */
    public Map<String, Object> switchNetSpeedEcharts(InitialSwitchInfoDetails initialSwitchInfoDetails, BigDecimal percentile95) {
        List<InitialSwitchInfoDetails> list = initialSwitchInfoDetailsMapper.getswitchDetailList(initialSwitchInfoDetails);
        try {
            list.forEach(data -> data.setPercentile95(SpeedUtils.mbitToBit(percentile95)));
            SpeedUtils.SpeedResult result = SpeedUtils.calculateWithAverageBasedUnit(list, "inSpeed", "outSpeed");
            BigDecimal divisor = SpeedUtils.getDivisor(result.getRecommendedUnit());
            Map<String, Function<InitialSwitchInfoDetails, ?>> extractors = new LinkedHashMap<>();
            extractors.put("netInSpeedData", info ->
                    info != null && info.getInSpeed() != null ?
                            info.getInSpeed().divide(divisor, 0, RoundingMode.HALF_UP) :
                            0);

            extractors.put("netOutSpeedData", info ->
                    info != null && info.getOutSpeed() != null ?
                            info.getOutSpeed().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, InitialSwitchInfoDetails::getCreateTime, extractors);
            resultMap.put("other", result);
            resultMap.put("95value", percentile95);
            return resultMap;
        } catch (Exception e){
            e.printStackTrace();
        }
        return new HashMap<>();
    }
}
