package helper

import (
	"fmt"
	"time"

	"github.com/bytedance/sonic"
	"github.com/go-redis/redis/v8"
)

// CacheFunction 通用缓存装饰器，支持任意函数类型
func CacheFunctionExpire[T any](fn func(args ...any) (T, error), keyPrefix string, ttl time.Duration) func(args ...any) (T, error) {
	return func(args ...any) (T, error) {
		// 创建缓存键，基于函数名和参数
		cacheKey := fmt.Sprintf("%s:%v", keyPrefix, args)

		// 尝试从 Redis 获取缓存
		cachedData, err := DefaultRedis.GetString(cacheKey)
		var zeroT T // 用于返回零值
		if err == redis.Nil {
			// 缓存不存在，调用实际函数
			result, err := fn(args...)
			if err != nil {
				return zeroT, err
			}

			// 将结果序列化并存入 Redis
			jsonData, err := sonic.Marshal(result)
			if err != nil {
				return zeroT, err
			}

			err = DefaultRedis.SetStringExpire(cacheKey, string(jsonData), ttl)
			if err != nil {
				return zeroT, err
			}

			return result, nil
		} else if err != nil {
			return zeroT, err
		}

		// 缓存命中，反序列化结果
		var result T
		err = sonic.Unmarshal([]byte(cachedData), &result)
		if err != nil {
			return zeroT, err
		}

		return result, nil
	}
}

// CacheFunction 通用缓存装饰器，支持任意函数类型
func CacheFunctionNoArgsExpire[T any](fn func() (T, error), keyPrefix string, ttl time.Duration) func() (T, error) {
	return func() (T, error) {
		// 创建缓存键，基于函数名和参数
		cacheKey := keyPrefix

		// 尝试从 Redis 获取缓存
		cachedData, err := DefaultRedis.GetString(cacheKey)
		var zeroT T // 用于返回零值
		if err == redis.Nil {
			// 缓存不存在，调用实际函数
			result, err := fn()
			if err != nil {
				return zeroT, err
			}

			// 将结果序列化并存入 Redis
			jsonData, err := sonic.Marshal(result)
			if err != nil {
				return zeroT, err
			}

			err = DefaultRedis.SetStringExpire(cacheKey, string(jsonData), ttl)
			if err != nil {
				return zeroT, err
			}

			return result, nil
		} else if err != nil {
			return zeroT, err
		}

		// 缓存命中，反序列化结果
		var result T
		err = sonic.Unmarshal([]byte(cachedData), &result)
		if err != nil {
			return zeroT, err
		}

		return result, nil
	}
}

// DeleteCacheFunction 通用删除缓存装饰器
func DeleteCacheFunction[T any](fn func(args ...any) (T, error), keyPrefix string) func(args ...any) (T, error) {
	return func(args ...any) (T, error) {
		// 调用实际函数
		result, err := fn(args...)
		if err != nil {
			return result, err
		}

		// 创建缓存键，基于函数名和参数
		cacheKey := fmt.Sprintf("%s:%v", keyPrefix, args)

		// 从 Redis 删除缓存
		err = DefaultRedis.DeleteString(cacheKey)
		if err != nil {
			return result, fmt.Errorf("failed to delete cache: %w", err)
		}

		return result, nil
	}
}

// DeleteCacheFunction 通用删除缓存装饰器
func DeleteCacheNoArgsFunction[T any](fn func() (T, error), keyPrefix string) func() (T, error) {
	return func() (T, error) {
		// 调用实际函数
		result, err := fn()
		if err != nil {
			return result, err
		}

		// 创建缓存键，基于函数名和参数
		cacheKey := keyPrefix

		// 从 Redis 删除缓存
		err = DefaultRedis.DeleteString(cacheKey)
		if err != nil {
			return result, fmt.Errorf("failed to delete cache: %w", err)
		}

		return result, nil
	}
}
