package camel_oil

import (
	"context"
	"encoding/json"
	"fmt"
	"github.com/gogf/gf/v2/errors/gcode"
	"slices"
	"time"

	v1 "kami/api/camel_oil/v1"
	"kami/utility/cache"

	"github.com/gogf/gf/v2/errors/gerror"
	"github.com/gogf/gf/v2/os/glog"
	"github.com/gogf/gf/v2/os/gtime"
)

// GetPrefetchOrderLogs 获取预拉取订单日志
func (s *sCamelOil) GetPrefetchOrderLogs(ctx context.Context, req *v1.GetPrefetchOrderLogsReq) (res *v1.GetPrefetchOrderLogsRes, err error) {
	// 计算时间范围跨度
	duration := req.EndTime.Time.Sub(req.StartTime.Time)
	if duration <= 0 {
		return nil, gerror.NewCode(gcode.CodeInvalidParameter, "结束时间必须大于开始时间")
	}

	// Redis key 前缀
	redisKeyPrefix := "camel_oil:prefetch:logs:"

	var logs []v1.PrefetchOrderLogItem

	//只展示 1000条
	maxLogCount := 1000
	logCount := 0

	// 用于跟踪实际查询到的时间范围
	var actualStartTime, actualEndTime *gtime.Time

	// 遍历时间范围内的每一分钟
	currentTime := req.EndTime.StartOfMinute()
	actualEndTime = currentTime.EndOfMinute()
	actualStartTime = currentTime
	for currentTime.After(req.StartTime) || currentTime.Equal(req.StartTime) {
		if logCount >= maxLogCount {
			break
		}
		redisKey := redisKeyPrefix + currentTime.Layout("2006-01-02T15:04")

		// 从Redis获取日志数据
		logData, err2 := cache.NewCache().Get(ctx, redisKey)
		if err2 != nil {
			glog.Warningf(ctx, "获取Redis日志失败，key: %s, error: %v", redisKey, err)
			currentTime = currentTime.Add(-gtime.M)
			continue
		}

		if logData.IsEmpty() {
			currentTime = currentTime.Add(-gtime.M)
			continue
		}

		// 解析日志数据
		var minuteLogs []map[string]interface{}
		if err := json.Unmarshal([]byte(logData.String()), &minuteLogs); err != nil {
			glog.Warningf(ctx, "解析日志数据失败，key: %s, error: %v", redisKey, err)
			currentTime = currentTime.Add(-gtime.M)
			continue
		}

		tmpLogs := make([]v1.PrefetchOrderLogItem, 0)
		// 处理每条日志
		for _, log := range minuteLogs {
			// 提取时间戳
			timestamp, ok := log["timestamp"].(string)
			if !ok {
				continue
			}

			// 提取响应数据
			respStr, ok := log["resp_str"].(string)
			if !ok {
				respStr = ""
			}

			// 添加到结果列表，只包含时间戳和响应数据
			tmpLogs = append(tmpLogs, v1.PrefetchOrderLogItem{
				Timestamp:    timestamp,
				ResponseData: respStr,
			})
			logCount++
		}
		slices.Reverse(tmpLogs)
		logs = append(logs, tmpLogs...)
		actualStartTime = currentTime
		currentTime = currentTime.Add(-gtime.M)
	}

	// 返回结果
	res = &v1.GetPrefetchOrderLogsRes{
		Logs:            logs,
		ActualStartTime: actualStartTime,
		ActualEndTime:   actualEndTime,
	}

	return res, nil
}

// SavePrefetchOrderLog 保存预拉取订单请求日志到Redis
func (s *sCamelOil) SavePrefetchOrderLog(ctx context.Context, respStr string) {
	// 构建日志数据
	logEntry := map[string]interface{}{
		"timestamp": gtime.Now().Format("Y-m-d H:i:s"),
		"resp_str":  respStr, // 保存响应数据
	}

	// 将日志数据序列化为JSON
	logData, jsonErr := json.Marshal(logEntry)
	if jsonErr != nil {
		glog.Errorf(ctx, "序列化预拉取订单日志失败: %v", jsonErr)
		return
	}

	// 生成Redis key (按分钟级别)
	redisKey := fmt.Sprintf("camel_oil:prefetch:logs:%s", gtime.Now().Layout("2006-01-02T15:04"))

	// 获取当前分钟已有的日志
	var logs []map[string]interface{}
	existingData, cacheErr := cache.NewCache().Get(ctx, redisKey)
	if cacheErr == nil && !existingData.IsEmpty() {
		if err := json.Unmarshal([]byte(existingData.String()), &logs); err != nil {
			// 如果解析失败，创建新的日志数组
			logs = []map[string]interface{}{}
		}
	}

	// 添加新的日志
	var newLog map[string]interface{}
	if err := json.Unmarshal(logData, &newLog); err == nil {
		logs = append(logs, newLog)
	}

	// 重新序列化并保存到Redis，设置1小时过期时间
	updatedLogData, marshalErr := json.Marshal(logs)
	if marshalErr != nil {
		glog.Errorf(ctx, "重新序列化日志失败: %v", marshalErr)
		return
	}

	// 使用cache包保存到Redis
	if cacheErr := cache.NewCache().Set(ctx, redisKey, string(updatedLogData), time.Hour); cacheErr != nil {
		glog.Errorf(ctx, "保存预拉取订单日志到Redis失败: %v", cacheErr)
		return
	}
}
