package handler

import (
	"fmt"
	"sort"
	"strconv"
	"strings"
	"time"

	"github.com/monitor/backend/internal/storage"
)

// MetricData 处理后的监控数据
type MetricData struct {
	Time  time.Time `json:"time"`
	Value float64   `json:"value"`
}

// ParseInterval 解析时间区间字符串，返回秒数
// 支持的格式：10s, 1m, 5m, 1h, 1d等
func ParseInterval(intervalStr string) (int, error) {
	if intervalStr == "" {
		return 10, nil // 默认10秒
	}

	intervalStr = strings.ToLower(intervalStr)
	var multiplier int

	// 解析时间单位
	switch {
	case strings.HasSuffix(intervalStr, "s"):
		multiplier = 1
		intervalStr = strings.TrimSuffix(intervalStr, "s")
	case strings.HasSuffix(intervalStr, "m"):
		multiplier = 60
		intervalStr = strings.TrimSuffix(intervalStr, "m")
	case strings.HasSuffix(intervalStr, "h"):
		multiplier = 3600
		intervalStr = strings.TrimSuffix(intervalStr, "h")
	case strings.HasSuffix(intervalStr, "d"):
		multiplier = 86400
		intervalStr = strings.TrimSuffix(intervalStr, "d")
	default:
		return 0, fmt.Errorf("unsupported interval format: %s", intervalStr)
	}

	// 解析数字部分
	value, err := strconv.Atoi(intervalStr)
	if err != nil {
		return 0, fmt.Errorf("invalid interval value: %s", intervalStr)
	}

	return value * multiplier, nil
}

// FormatTimeByInterval 根据时间区间格式化时间
func FormatTimeByInterval(t time.Time, intervalSeconds int) string {
	// 按指定秒数对齐时间
	rounded := t.Truncate(time.Duration(intervalSeconds) * time.Second)

	// 根据区间长度选择不同的格式化字符串
	if intervalSeconds < 60 {
		// 秒级，显示到秒
		return rounded.Format("2006-01-02 15:04:05")
	} else if intervalSeconds < 3600 {
		// 分钟级，显示到分钟
		return rounded.Format("2006-01-02 15:04:00")
	} else {
		// 小时级，显示到小时
		return rounded.Format("2006-01-02 15:00:00")
	}
}

// ProcessMetrics 处理监控数据，支持动态时间区间
func ProcessMetrics(points []storage.MetricPoint, aggregation string, intervalStr string, startTime, endTime string) []MetricData {
	// 解析时间区间
	intervalSeconds, err := ParseInterval(intervalStr)
	if err != nil {
		// 解析失败，使用默认值10秒
		intervalSeconds = 10
	}

	// 解析开始和结束时间
	var start, end time.Time
	var parseErr error

	// 解析开始时间
	if strings.HasPrefix(startTime, "-") || startTime == "now()" {
		// 相对时间，使用当前时间作为基准
		now := time.Now()
		if startTime == "now()" {
			start = now
		} else {
			// 相对时间，如-24h
			relDuration, parseErr := time.ParseDuration(startTime)
			if parseErr == nil {
				start = now.Add(relDuration)
			} else {
				// 解析失败，使用默认时间
				start = now.Add(-24 * time.Hour)
			}
		}
	} else {
		// 绝对时间，尝试解析
		start, parseErr = time.Parse(time.RFC3339, startTime)
		if parseErr != nil {
			// 尝试其他格式
			start, parseErr = time.Parse("2006-01-02T15:04", startTime)
			if parseErr != nil {
				// 尝试YYYY-MM-DD HH:MM格式
				start, parseErr = time.Parse("2006-01-02 15:04", startTime)
				if parseErr != nil {
					// 解析失败，使用默认时间
					start = time.Now().Add(-24 * time.Hour)
				}
			}
		}
	}

	// 解析结束时间
	if endTime == "now()" {
		end = time.Now()
	} else if strings.HasPrefix(endTime, "-") {
		// 相对时间，使用当前时间作为基准
		now := time.Now()
		relDuration, parseErr := time.ParseDuration(endTime)
		if parseErr == nil {
			end = now.Add(relDuration)
		} else {
			// 解析失败，使用当前时间
			end = now
		}
	} else {
		// 绝对时间，尝试解析
		end, parseErr = time.Parse(time.RFC3339, endTime)
		if parseErr != nil {
			// 尝试其他格式
			end, parseErr = time.Parse("2006-01-02T15:04", endTime)
			if parseErr != nil {
				// 尝试YYYY-MM-DD HH:MM格式
				end, parseErr = time.Parse("2006-01-02 15:04", endTime)
				if parseErr != nil {
					// 解析失败，使用当前时间
					end = time.Now()
				}
			}
		}
	}

	// 如果没有数据点，生成覆盖整个时间范围的空数据点
	if len(points) == 0 {
		// 生成空数据点，确保覆盖整个时间范围
		result := make([]MetricData, 0)
		currentTime := start

		// 循环生成数据点，直到超过结束时间
		for currentTime.Before(end) {
			result = append(result, MetricData{
				Time:  currentTime,
				Value: 0, // 使用0表示无数据
			})
			currentTime = currentTime.Add(time.Duration(intervalSeconds) * time.Second)
		}

		return result
	}

	// 根据时间区段精细程度自动调整聚合策略
	// 如果时间区段精细程度为1s，显示全部数据（去重后）
	// 如果时间区段精细程度>1s，根据聚合类型进行聚合
	if intervalSeconds == 1 {
		// 1秒时间区段，返回全部原始数据（去重后）
		return processRawData(points)
	} else {
		// 大于1秒时间区段，根据聚合类型处理
		switch aggregation {
		case "raw":
			// 对于raw聚合类型，返回去重后的原始数据
			return processRawData(points)
		case "average":
			return processAverageData(points, intervalSeconds, start, end)
		case "max":
			return processMaxData(points, intervalSeconds, start, end)
		case "min":
			return processMinData(points, intervalSeconds, start, end)
		case "sum":
			return processSumData(points, intervalSeconds, start, end)
		default:
			// 默认返回平均值
			return processAverageData(points, intervalSeconds, start, end)
		}
	}
}

// processRawData 处理原始数据，添加去重逻辑
func processRawData(points []storage.MetricPoint) []MetricData {
	// 使用map进行去重，key为时间戳（精确到秒）+值的组合
	deduplicated := make(map[string]storage.MetricPoint)

	for _, point := range points {
		// 精确到秒的时间戳
		key := fmt.Sprintf("%d_%.2f", point.Time.Unix(), point.Value)
		deduplicated[key] = point
	}

	// 将去重后的数据转换为切片
	result := make([]MetricData, 0, len(deduplicated))
	for _, point := range deduplicated {
		result = append(result, MetricData{
			Time:  point.Time,
			Value: point.Value,
		})
	}

	// 按时间排序
	sort.Slice(result, func(i, j int) bool {
		return result[i].Time.Before(result[j].Time)
	})

	return result
}

// processAverageData 处理平均值数据
func processAverageData(points []storage.MetricPoint, intervalSeconds int, start, end time.Time) []MetricData {
	// 按指定时间区间聚合的平均值

	// 按指定区间分组，保留UTC时区信息
	intervalData := make(map[string][]float64)

	for _, point := range points {
		// 使用UTC时间，按指定区间对齐
		utcTime := point.Time.UTC()
		// 格式化时间键
		intervalKey := FormatTimeByInterval(utcTime, intervalSeconds)
		value := point.Value
		intervalData[intervalKey] = append(intervalData[intervalKey], value)
	}

	// 生成覆盖整个请求时间范围的完整时间序列
	result := make([]MetricData, 0)
	currentTime := start.Truncate(time.Duration(intervalSeconds) * time.Second)

	// 循环生成每个时间区间的数据点
	for currentTime.Before(end.Add(time.Duration(intervalSeconds) * time.Second)) {
		// 格式化当前时间为区间键
		intervalKey := FormatTimeByInterval(currentTime, intervalSeconds)

		// 计算当前区间的平均值
		var value float64 = 0
		if values, exists := intervalData[intervalKey]; exists && len(values) > 0 {
			// 计算平均值
			sum := 0.0
			for _, v := range values {
				sum += v
			}
			value = sum / float64(len(values))
		}

		// 添加到结果
		result = append(result, MetricData{
			Time:  currentTime,
			Value: value,
		})

		// 移动到下一个时间区间
		currentTime = currentTime.Add(time.Duration(intervalSeconds) * time.Second)
	}

	return result
}

// processMaxData 处理最大值数据
func processMaxData(points []storage.MetricPoint, intervalSeconds int, start, end time.Time) []MetricData {
	// 按指定时间区间聚合的最大值

	// 按指定区间分组，保留UTC时区信息
	intervalData := make(map[string][]float64)

	for _, point := range points {
		// 使用UTC时间，按指定区间对齐
		utcTime := point.Time.UTC()
		// 格式化时间键
		intervalKey := FormatTimeByInterval(utcTime, intervalSeconds)
		value := point.Value
		intervalData[intervalKey] = append(intervalData[intervalKey], value)
	}

	// 生成覆盖整个请求时间范围的完整时间序列
	result := make([]MetricData, 0)
	currentTime := start.Truncate(time.Duration(intervalSeconds) * time.Second)

	// 循环生成每个时间区间的数据点
	for currentTime.Before(end.Add(time.Duration(intervalSeconds) * time.Second)) {
		// 格式化当前时间为区间键
		intervalKey := FormatTimeByInterval(currentTime, intervalSeconds)

		// 计算当前区间的最大值
		var value float64 = 0
		if values, exists := intervalData[intervalKey]; exists && len(values) > 0 {
			// 计算最大值
			max := values[0]
			for _, v := range values {
				if v > max {
					max = v
				}
			}
			value = max
		}

		// 添加到结果
		result = append(result, MetricData{
			Time:  currentTime,
			Value: value,
		})

		// 移动到下一个时间区间
		currentTime = currentTime.Add(time.Duration(intervalSeconds) * time.Second)
	}

	return result
}

// processMinData 处理最小值数据
func processMinData(points []storage.MetricPoint, intervalSeconds int, start, end time.Time) []MetricData {
	// 按指定时间区间聚合的最小值

	// 按指定区间分组，保留UTC时区信息
	intervalData := make(map[string][]float64)

	for _, point := range points {
		// 使用UTC时间，按指定区间对齐
		utcTime := point.Time.UTC()
		// 格式化时间键
		intervalKey := FormatTimeByInterval(utcTime, intervalSeconds)
		value := point.Value
		intervalData[intervalKey] = append(intervalData[intervalKey], value)
	}

	// 生成覆盖整个请求时间范围的完整时间序列
	result := make([]MetricData, 0)
	currentTime := start.Truncate(time.Duration(intervalSeconds) * time.Second)

	// 循环生成每个时间区间的数据点
	for currentTime.Before(end.Add(time.Duration(intervalSeconds) * time.Second)) {
		// 格式化当前时间为区间键
		intervalKey := FormatTimeByInterval(currentTime, intervalSeconds)

		// 计算当前区间的最小值
		var value float64 = 0
		if values, exists := intervalData[intervalKey]; exists && len(values) > 0 {
			// 计算最小值
			min := values[0]
			for _, v := range values {
				if v < min {
					min = v
				}
			}
			value = min
		}

		// 添加到结果
		result = append(result, MetricData{
			Time:  currentTime,
			Value: value,
		})

		// 移动到下一个时间区间
		currentTime = currentTime.Add(time.Duration(intervalSeconds) * time.Second)
	}

	return result
}

// processSumData 处理总和数据
func processSumData(points []storage.MetricPoint, intervalSeconds int, start, end time.Time) []MetricData {
	// 按指定时间区间聚合的总和

	// 按指定区间分组，保留UTC时区信息
	intervalData := make(map[string][]storage.MetricPoint)

	for _, point := range points {
		// 使用UTC时间，按指定区间对齐
		utcTime := point.Time.UTC()
		// 格式化时间键
		intervalKey := FormatTimeByInterval(utcTime, intervalSeconds)
		intervalData[intervalKey] = append(intervalData[intervalKey], point)
	}

	// 生成覆盖整个请求时间范围的完整时间序列
	result := make([]MetricData, 0)
	currentTime := start.Truncate(time.Duration(intervalSeconds) * time.Second)

	// 循环生成每个时间区间的数据点
	for currentTime.Before(end.Add(time.Duration(intervalSeconds) * time.Second)) {
		// 格式化当前时间为区间键
		intervalKey := FormatTimeByInterval(currentTime, intervalSeconds)

		// 计算当前区间的总和
		sum := 0.0
		if intervalPoints, exists := intervalData[intervalKey]; exists {
			// 如果数据点数量小于2，直接返回第一个数据点的值
			if len(intervalPoints) < 2 {
				if len(intervalPoints) > 0 {
					sum = intervalPoints[0].Value
				}
			} else {
				// 按时间排序
				sort.Slice(intervalPoints, func(i, j int) bool {
					return intervalPoints[i].Time.Before(intervalPoints[j].Time)
				})
				for i := 1; i < len(intervalPoints); i++ {
					// 计算时间差（秒）
					timeDiff := intervalPoints[i].Time.Sub(intervalPoints[i-1].Time).Seconds()
					if timeDiff > 0 {
						// 计算这个时间段的平均速率
						averageRate := (intervalPoints[i].Value + intervalPoints[i-1].Value) / 2
						// 计算这个时间段的流量
						flow := averageRate * timeDiff
						// 累加到总和
						sum += flow
					}
				}
			}
		}

		// 添加到结果
		result = append(result, MetricData{
			Time:  currentTime,
			Value: sum,
		})

		// 移动到下一个时间区间
		currentTime = currentTime.Add(time.Duration(intervalSeconds) * time.Second)
	}

	return result
}
