package com.tongran.common.core.utils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

public class EchartsMoreDataUtils {


    /**
     * 构建多网卡ECharts图表数据（带汇总流量）
     * 每个网卡会生成两个独立的Y轴属性：{interfaceName}netInTraffic 和 {interfaceName}netOutTraffic
     * 同时生成汇总流量：totalNetInTraffic 和 totalNetOutTraffic
     */
    public static <T> Map<String, Object> buildMultiInterfaceEchartsDataWithTotal(
            Map<String, List<T>> interfaceDataMap,
            Function<T, Date> timeExtractor,
            Function<T, BigDecimal> inSpeedExtractor,
            Function<T, BigDecimal> outSpeedExtractor,
            String startTime,
            String endTime,
            BigDecimal divisor) {

        try {
            // 解析时间字符串
            Date startDate = parseStringToDate(startTime);
            Date endDate = parseStringToDate(endTime);

            if (startDate == null || endDate == null) {
                throw new IllegalArgumentException("开始时间或结束时间格式错误");
            }

            if (startDate.after(endDate)) {
                throw new IllegalArgumentException("开始时间不能晚于结束时间");
            }

            // 收集所有网卡的时间点
            Set<Date> allTimePoints = new TreeSet<>();
            Map<String, Map<Long, T>> interfaceTimeMap = new LinkedHashMap<>();

            // 为每个网卡处理数据
            for (Map.Entry<String, List<T>> entry : interfaceDataMap.entrySet()) {
                String interfaceName = entry.getKey();
                List<T> interfaceList = entry.getValue();

                if (interfaceList == null || interfaceList.isEmpty()) {
                    continue;
                }

                // 按时间排序
                List<T> sortedList = interfaceList.stream()
                        .sorted(Comparator.comparing(timeExtractor))
                        .collect(Collectors.toList());

                // 自动检测时间间隔
                long timeInterval = detectTimeInterval(sortedList, timeExtractor);

                // 创建时间到数据的映射
                Map<Long, T> timeMap = sortedList.stream()
                        .collect(Collectors.toMap(
                                item -> normalizeTime(timeExtractor.apply(item), timeInterval),
                                Function.identity(),
                                (a, b) -> a
                        ));

                interfaceTimeMap.put(interfaceName, timeMap);

                // 添加时间点到总集合
                for (T item : sortedList) {
                    allTimePoints.add(timeExtractor.apply(item));
                }
            }

            // 生成完整的时间序列
            List<Date> fullTimeSeries = generateFullTimeSeriesForMultiInterface(
                    allTimePoints, startDate, endDate);

            // 准备X轴和Y轴数据
            List<String> xAxisData = new ArrayList<>();
            Map<String, Object> yData = new LinkedHashMap<>();

            // 初始化每个网卡的Y轴数据结构
            interfaceDataMap.keySet().forEach(interfaceName -> {
                yData.put(interfaceName + "netInTraffic", new ArrayList<BigDecimal>());
                yData.put(interfaceName + "netOutTraffic", new ArrayList<BigDecimal>());
            });

            // 初始化汇总流量数据结构
            List<BigDecimal> totalNetInTraffic = new ArrayList<>();
            List<BigDecimal> totalNetOutTraffic = new ArrayList<>();
            yData.put("totalNetInTraffic", totalNetInTraffic);
            yData.put("totalNetOutTraffic", totalNetOutTraffic);

            // 遍历所有时间点
            for (Date time : fullTimeSeries) {
                // X轴数据
                xAxisData.add(parseDateToStr(time));

                // 标准化当前时间
                long normalizedTime = normalizeTime(time, 300000L); // 5分钟间隔

                // 当前时间点的总流量
                BigDecimal timeTotalInSpeed = BigDecimal.ZERO;
                BigDecimal timeTotalOutSpeed = BigDecimal.ZERO;

                // 处理每个网卡的数据
                for (Map.Entry<String, Map<Long, T>> entry : interfaceTimeMap.entrySet()) {
                    String interfaceName = entry.getKey();
                    Map<Long, T> timeMap = entry.getValue();

                    T item = timeMap.get(normalizedTime);

                    // 获取入方向数据列表
                    @SuppressWarnings("unchecked")
                    List<BigDecimal> inSpeedList = (List<BigDecimal>) yData.get(interfaceName + "netInTraffic");
                    // 获取出方向数据列表
                    @SuppressWarnings("unchecked")
                    List<BigDecimal> outSpeedList = (List<BigDecimal>) yData.get(interfaceName + "netOutTraffic");

                    if (item != null) {
                        // 有真实数据
                        BigDecimal inSpeed = inSpeedExtractor.apply(item);
                        BigDecimal outSpeed = outSpeedExtractor.apply(item);

                        // 单位转换
                        BigDecimal convertedInSpeed = inSpeed != null ?
                                inSpeed.divide(divisor, 2, RoundingMode.HALF_UP) : null;
                        BigDecimal convertedOutSpeed = outSpeed != null ?
                                outSpeed.divide(divisor, 2, RoundingMode.HALF_UP) : null;

                        inSpeedList.add(convertedInSpeed);
                        outSpeedList.add(convertedOutSpeed);

                        // 累加到总流量
                        if (convertedInSpeed != null) {
                            timeTotalInSpeed = timeTotalInSpeed.add(convertedInSpeed);
                        }
                        if (convertedOutSpeed != null) {
                            timeTotalOutSpeed = timeTotalOutSpeed.add(convertedOutSpeed);
                        }
                    } else {
                        // 无数据的时间点，补null
                        inSpeedList.add(null);
                        outSpeedList.add(null);
                    }
                }

                // 添加当前时间点的总流量
                totalNetInTraffic.add(timeTotalInSpeed.compareTo(BigDecimal.ZERO) == 0 ? null : timeTotalInSpeed);
                totalNetOutTraffic.add(timeTotalOutSpeed.compareTo(BigDecimal.ZERO) == 0 ? null : timeTotalOutSpeed);
            }

            Map<String, Object> result = new HashMap<>();
            result.put("xData", xAxisData);
            result.put("yData", yData);
            return result;

        } catch (Exception e) {
            // 记录日志
            System.err.println("构建多网卡图表数据失败: " + e.getMessage());
            return createEmptyMultiInterfaceResultWithTotal(interfaceDataMap.keySet(), startTime, endTime);
        }
    }

    /**
     * 为多网卡生成完整的时间序列
     */
    private static List<Date> generateFullTimeSeriesForMultiInterface(
            Set<Date> allInterfaceTimePoints,
            Date startDate,
            Date endDate) {

        // 获取实际数据的时间范围
        Date actualStartTime = allInterfaceTimePoints.isEmpty() ? startDate :
                Collections.min(allInterfaceTimePoints);
        Date actualEndTime = allInterfaceTimePoints.isEmpty() ? endDate :
                Collections.max(allInterfaceTimePoints);

        // 计算稀疏间隔
        long totalTimeRange = endDate.getTime() - startDate.getTime();
        long sparseInterval = totalTimeRange > 12L * 30 * 24 * 60 * 60 * 1000 ?
                30L * 24 * 60 * 60 * 1000 : 2L * 24 * 60 * 60 * 1000;

        // 使用默认的5分钟作为数据期间间隔
        long dataInterval = 300000L;

        // 生成三段时间序列
        List<Date> fullTimeSeries = new ArrayList<>();

        // 1. 开始时间到数据开始时间（稀疏间隔）
        if (startDate.before(actualStartTime)) {
            List<Date> beforeSeries = generateTimeSeries(startDate, actualStartTime, sparseInterval);
            fullTimeSeries.addAll(beforeSeries);
        }

        // 2. 数据开始时间到数据结束时间（正常间隔）
        List<Date> dataSeries = generateTimeSeries(actualStartTime, actualEndTime, dataInterval);
        fullTimeSeries.addAll(dataSeries);

        // 3. 数据结束时间到结束时间（稀疏间隔）
        if (actualEndTime.before(endDate)) {
            // 调整actualEndTime的下一个点开始，避免重复
            Calendar cal = Calendar.getInstance();
            cal.setTime(actualEndTime);
            cal.setTimeInMillis(cal.getTimeInMillis() + dataInterval);
            Date nextAfterActualEnd = cal.getTime();

            if (nextAfterActualEnd.before(endDate) || nextAfterActualEnd.equals(endDate)) {
                List<Date> afterSeries = generateTimeSeries(nextAfterActualEnd, endDate, sparseInterval);
                fullTimeSeries.addAll(afterSeries);
            }
        }
        // 在generateFullTimeSeriesForMultiInterface方法的最后添加：
        fullTimeSeries.sort(Date::compareTo);
        // 去重
        List<Date> uniqueSeries = new ArrayList<>();
        Date lastDate = null;
        for (Date date : fullTimeSeries) {
            if (lastDate == null || !date.equals(lastDate)) {
                uniqueSeries.add(date);
                lastDate = date;
            }
        }
        return uniqueSeries;
    }

    /**
     * 创建多网卡空结果（带汇总流量）
     */
    private static Map<String, Object> createEmptyMultiInterfaceResultWithTotal(
            Set<String> interfaceNames, String startTime, String endTime) {

        Map<String, Object> result = new HashMap<>();

        try {
            // 解析时间范围
            Date startDate = parseStringToDate(startTime);
            Date endDate = parseStringToDate(endTime);

            if (startDate != null && endDate != null && !startDate.after(endDate)) {
                // 动态计算时间间隔
                long timeRange = endDate.getTime() - startDate.getTime();
                long interval;

                if (timeRange > 12L * 30 * 24 * 60 * 60 * 1000) { // 超过12个月
                    interval = 30L * 24 * 60 * 60 * 1000; // 每月1个点
                } else {
                    interval = 2L * 24 * 60 * 60 * 1000; // 2天1个点
                }

                List<Date> fullTimeSeries = generateTimeSeries(startDate, endDate, interval);

                // 构建x轴数据
                List<String> xAxisData = new ArrayList<>();
                for (Date date : fullTimeSeries) {
                    xAxisData.add(parseDateToStr(date));
                }
                result.put("xData", xAxisData);

                // 构建y轴数据（空数据集）
                Map<String, Object> yData = new LinkedHashMap<>();
                int dataSize = xAxisData.size();

                // 为每个网卡创建空数据系列
                for (String interfaceName : interfaceNames) {
                    List<Object> inSpeedSeries = new ArrayList<>();
                    List<Object> outSpeedSeries = new ArrayList<>();

                    for (int i = 0; i < dataSize; i++) {
                        if (i == 0) {
                            // 第一个点补0
                            inSpeedSeries.add(0);
                            outSpeedSeries.add(0);
                        } else {
                            // 其他点补null
                            inSpeedSeries.add(null);
                            outSpeedSeries.add(null);
                        }
                    }

                    yData.put(interfaceName + "netInTraffic", inSpeedSeries);
                    yData.put(interfaceName + "netOutTraffic", outSpeedSeries);
                }

                // 创建汇总流量的空数据系列
                List<Object> totalInSpeedSeries = new ArrayList<>();
                List<Object> totalOutSpeedSeries = new ArrayList<>();
                for (int i = 0; i < dataSize; i++) {
                    if (i == 0) {
                        totalInSpeedSeries.add(0);
                        totalOutSpeedSeries.add(0);
                    } else {
                        totalInSpeedSeries.add(null);
                        totalOutSpeedSeries.add(null);
                    }
                }
                yData.put("totalNetInTraffic", totalInSpeedSeries);
                yData.put("totalNetOutTraffic", totalOutSpeedSeries);

                result.put("yData", yData);

            } else {
                // 时间解析失败时返回空数据
                result.put("xData", new ArrayList<>());
                Map<String, Object> yData = new LinkedHashMap<>();
                for (String interfaceName : interfaceNames) {
                    yData.put(interfaceName + "netInTraffic", new ArrayList<>());
                    yData.put(interfaceName + "netOutTraffic", new ArrayList<>());
                }
                yData.put("totalNetInTraffic", new ArrayList<>());
                yData.put("totalNetOutTraffic", new ArrayList<>());
                result.put("yData", yData);
            }

        } catch (Exception e) {
            // 异常时返回空数据
            result.put("xData", new ArrayList<>());
            Map<String, Object> yData = new LinkedHashMap<>();
            for (String interfaceName : interfaceNames) {
                yData.put(interfaceName + "netInTraffic", new ArrayList<>());
                yData.put(interfaceName + "netOutTraffic", new ArrayList<>());
            }
            yData.put("totalNetInTraffic", new ArrayList<>());
            yData.put("totalNetOutTraffic", new ArrayList<>());
            result.put("yData", yData);
        }

        return result;
    }


    /**
     * 字符串转日期
     */
    private static Date parseStringToDate(String dateStr) {
        if (dateStr == null || dateStr.trim().isEmpty()) {
            return null;
        }
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            sdf.setLenient(false); // 严格模式
            return sdf.parse(dateStr);
        } catch (ParseException e) {
            System.err.println("日期解析失败: " + dateStr);
            return null;
        }
    }

    /**
     * 日期转字符串
     */
    private static String parseDateToStr(Date date) {
        if (date == null) {
            return "";
        }
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return sdf.format(date);
    }

    /**
     * 生成完整的时间序列
     */
    private static List<Date> generateTimeSeries(Date start, Date end, long interval) {
        List<Date> timeSeries = new ArrayList<>();
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(start);

        // 确保开始时间对齐到时间间隔
        long startMillis = normalizeTime(start, interval);
        calendar.setTimeInMillis(startMillis);

        while (!calendar.getTime().after(end)) {
            timeSeries.add(calendar.getTime());
            calendar.setTimeInMillis(calendar.getTimeInMillis() + interval);
        }
        return timeSeries;
    }

    /**
     * 自动检测时间间隔
     */
    private static <T> long detectTimeInterval(List<T> list, Function<T, Date> timeExtractor) {
        if (list.size() < 2) {
            return 300000; // 默认5分钟
        }

        // 计算时间间隔的众数
        Map<Long, Integer> intervalCount = new HashMap<>();
        for (int i = 1; i < list.size(); i++) {
            long interval = timeExtractor.apply(list.get(i)).getTime() -
                    timeExtractor.apply(list.get(i - 1)).getTime();
            if (interval > 0) {
                intervalCount.merge(interval, 1, Integer::sum);
            }
        }

        // 如果没有有效间隔，使用默认值
        if (intervalCount.isEmpty()) {
            return 300000L;
        }

        return intervalCount.entrySet().stream()
                .max(Map.Entry.comparingByValue())
                .map(Map.Entry::getKey)
                .orElse(300000L);
    }

    /**
     * 时间标准化（对齐到时间间隔）
     */
    private static long normalizeTime(Date time, long interval) {
        long timeMillis = time.getTime();
        return (timeMillis / interval) * interval;
    }
    public static Map<String, String> sortInterfaceMap(Map<String, String> interfaceMap, String mainName, boolean hasSub) {
        List<Map.Entry<String, String>> list = new ArrayList<>(interfaceMap.entrySet());

        list.sort((a, b) -> {
            String ka = a.getKey(), kb = b.getKey();

            // 总流量优先
            if (hasSub) {
                if (ka.startsWith("total")) return -1;
                if (kb.startsWith("total")) return 1;
            }

            // 提取接口名
            String na = ka.replace("netInTraffic", "").replace("netOutTraffic", "");
            String nb = kb.replace("netInTraffic", "").replace("netOutTraffic", "");

            // 主接口优先
            if (na.equals(mainName) && !nb.equals(mainName)) return -1;
            if (!na.equals(mainName) && nb.equals(mainName)) return 1;

            // 点号数量排序
            int da = na.length() - na.replace(".", "").length();
            int db = nb.length() - nb.replace(".", "").length();
            if (da != db) return da - db;

            // 数字排序
            String[] sa = na.split("\\.");
            String[] sb = nb.split("\\.");
            for (int i = 0; i < Math.min(sa.length, sb.length); i++) {
                try {
                    int numa = Integer.parseInt(sa[i]);
                    int numb = Integer.parseInt(sb[i]);
                    if (numa != numb) return Integer.compare(numa, numb);
                } catch (Exception e) {
                    int cmp = sa[i].compareTo(sb[i]);
                    if (cmp != 0) return cmp;
                }
            }

            // 接口名相同，出站优先
            if (na.equals(nb)) {
                if (ka.contains("Out") && kb.contains("In")) return -1;  // 出站在前
                if (ka.contains("In") && kb.contains("Out")) return 1;   // 入站在后
            }

            return 0;
        });

        Map<String, String> result = new LinkedHashMap<>();
        list.forEach(e -> result.put(e.getKey(), e.getValue()));
        return result;
    }
}