package com.ruoyi.common.core.utils;

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

public class EchartsDataUtils {

    /**
     * 构建ECharts图表数据
     * @param list 原始数据列表
     * @param timeExtractor 时间字段提取函数
     * @param dataExtractors 数据提取器Map (key: 数据名称, value: 数据提取函数)
     * @param <T> 数据类型泛型
     * @return 包含xData和yData的Map
     */
    public static <T> Map<String, Object> buildEchartsData(
            List<T> list,
            Function<T, Date> timeExtractor,
            Map<String, Function<T, ?>> dataExtractors) {

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

        // 准备X轴数据
        List<String> xAxisData = sortedList.stream()
                .map(item -> DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss", timeExtractor.apply(item)))
                .collect(Collectors.toList());

        // 准备Y轴数据
        Map<String, Object> yData = new LinkedHashMap<>();
        dataExtractors.forEach((name, extractor) -> {
            yData.put(name, sortedList.stream().map(extractor).collect(Collectors.toList()));
        });

        // 构建返回结果
        Map<String, Object> result = new HashMap<>();
        result.put("xData", xAxisData);
        result.put("yData", yData);
        return result;
    }


    /**
     * 微秒转秒
     */
    public static double convertMicrosecondsToSeconds(long microseconds) {
        return Math.round(microseconds / 1_000_000.0 * 100.0) / 100.0;
    }
    /**
     * 构建ECharts图表数据（带时间补全和特殊值处理）
     * @param list 原始数据列表
     * @param timeExtractor 时间字段提取函数
     * @param dataExtractors 数据提取器Map
     * @param startTime 开始时间字符串（格式：yyyy-MM-dd HH:mm:ss）
     * @param endTime 结束时间字符串（格式：yyyy-MM-dd HH:mm:ss）
     * @param <T> 数据类型泛型
     * @return 包含xData和yData的Map
     */
    public static <T> Map<String, Object> buildEchartsDataAutoPadding(
            List<T> list,
            Function<T, Date> timeExtractor,
            Map<String, Function<T, ?>> dataExtractors,
            String startTime,
            String endTime) {

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

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

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

            if (list == null || list.isEmpty()) {
                return createEmptyResult(dataExtractors.keySet(), startTime, endTime);
            }

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

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

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

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

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

            // 初始化Y轴数据结构
            dataExtractors.keySet().forEach(name ->
                    yData.put(name, new ArrayList<>()));

            // 特殊处理：查找percentile95的固定值
            Object fixedPercentile95Value = findFixedValueForPercentile95(sortedList, dataExtractors);

            // 检测整个数据集中是否有真实数据
            boolean hasRealData = checkHasRealData(sortedList, dataExtractors);

            // 记录当前处理的时间点索引
            int timeIndex = 0;

            for (Date time : fullTimeSeries) {
                // X轴数据
                xAxisData.add(parseDateToStr(time));

                // Y轴数据
                Long normalizedTime = normalizeTime(time, timeInterval);
                T item = timeDataMap.get(normalizedTime);

                for (Map.Entry<String, Function<T, ?>> entry : dataExtractors.entrySet()) {
                    String name = entry.getKey();
                    Function<T, ?> extractor = entry.getValue();

                    @SuppressWarnings("unchecked")
                    List<Object> seriesData = (List<Object>) yData.get(name);

                    if (item != null) {
                        Object value = extractor.apply(item);
                        seriesData.add(value != null ? value : getDefaultValue(name, fixedPercentile95Value, timeIndex, hasRealData));
                    } else {
                        // 智能数据补全
                        seriesData.add(getDefaultValue(name, fixedPercentile95Value, timeIndex, hasRealData));
                    }
                }

                timeIndex++;
            }

            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 createEmptyResult(dataExtractors.keySet(), startTime, endTime);
        }
    }

    /**
     * 检测整个数据集中是否有真实数据（非null）
     */
    private static <T> boolean checkHasRealData(List<T> list, Map<String, Function<T, ?>> dataExtractors) {
        for (T item : list) {
            for (Map.Entry<String, Function<T, ?>> entry : dataExtractors.entrySet()) {
                String name = entry.getKey();
                Function<T, ?> extractor = entry.getValue();

                Object value = extractor.apply(item);
                if (value != null) {
                    return true; // 发现至少一个真实数据
                }
            }
        }
        return false; // 没有发现任何真实数据
    }

    /**
     * 判断值是否为0（支持多种数值类型）
     */
    private static boolean isZeroValue(Object value) {
        if (value == null) return true;

        if (value instanceof Number) {
            return ((Number) value).doubleValue() == 0.0;
        }
        if (value instanceof BigDecimal) {
            return ((BigDecimal) value).compareTo(BigDecimal.ZERO) == 0;
        }
        if (value instanceof String) {
            try {
                return new BigDecimal(value.toString()).compareTo(BigDecimal.ZERO) == 0;
            } catch (Exception e) {
                return false;
            }
        }
        return false;
    }

    /**
     * 智能获取默认值
     * 策略：
     * 1. 如果整个数据集有真实数据：所有缺失点都补null
     * 2. 如果整个数据集没有真实数据：第一个点补0，其他点补null
     * 3. percentile95特殊处理：使用固定值
     */
    private static Object getDefaultValue(String metricName, Object fixedPercentile95Value,
                                          int timeIndex, boolean hasRealData) {

        // percentile95特殊处理
        if ("percentile95".equals(metricName) && !fixedPercentile95Value.equals(0)) {
            return fixedPercentile95Value;
        }

        // 智能补全策略
        if (hasRealData) {
            // 数据集中有真实数据：所有缺失点都补null
            return null;
        } else {
            // 数据集中没有真实数据：第一个点补0，其他点补null
            if (timeIndex == 0) {
                return 0;
            } else {
                return null;
            }
        }
    }

    /**
     * 创建空结果（智能补全策略）
     */
    private static Map<String, Object> createEmptyResult(Set<String> dataNames, 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 defaultInterval = 300000L; // 5分钟
                List<Date> fullTimeSeries = generateTimeSeries(startDate, endDate, defaultInterval);

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

                // 构建y轴数据（空数据集：第一个点补0，其他点补null）
                Map<String, Object> yData = new LinkedHashMap<>();
                int dataSize = xAxisData.size();
                dataNames.forEach(name -> {
                    List<Object> seriesData = new ArrayList<>();
                    for (int i = 0; i < dataSize; i++) {
                        if (i == 0) {
                            // 第一个点补0
                            seriesData.add(0);
                        } else {
                            // 其他点补null
                            seriesData.add(null);
                        }
                    }
                    yData.put(name, seriesData);
                });
                result.put("yData", yData);

            } else {
                // 时间解析失败时返回空数据
                result.put("xData", new ArrayList<>());
                Map<String, Object> yData = new LinkedHashMap<>();
                dataNames.forEach(name -> yData.put(name, new ArrayList<>()));
                result.put("yData", yData);
            }

        } catch (Exception e) {
            // 异常时返回空数据
            result.put("xData", new ArrayList<>());
            Map<String, Object> yData = new LinkedHashMap<>();
            dataNames.forEach(name -> yData.put(name, new ArrayList<>()));
            result.put("yData", yData);
        }

        return result;
    }

    /**
     * 查找percentile95的固定值（第一个非零值）
     */
    private static <T> Object findFixedValueForPercentile95(List<T> list, Map<String, Function<T, ?>> dataExtractors) {
        if (!dataExtractors.containsKey("percentile95")) {
            return 0;
        }

        Function<T, ?> extractor = dataExtractors.get("percentile95");
        for (T item : list) {
            Object value = extractor.apply(item);
            if (value != null) {
                return value;
            }
        }
        return 0;
    }

    /**
     * 字符串转日期
     */
    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;
    }

}