package gateway

import (
	"context"
	"os"
	"time"

	"github.com/redis/go-redis/v9"
)

// RedisCache is a Redis-based cache implementation
// Use this in production for distributed caching
type RedisCache struct {
	client *redis.Client
	ctx    context.Context
}

// NewRedisCache creates a new Redis cache
func NewRedisCache(redisURL string) (*RedisCache, error) {
	opts, err := redis.ParseURL(redisURL)
	if err != nil {
		return nil, err
	}

	client := redis.NewClient(opts)
	ctx := context.Background()

	// Test connection
	if err := client.Ping(ctx).Err(); err != nil {
		return nil, err
	}

	return &RedisCache{
		client: client,
		ctx:    ctx,
	}, nil
}

// NewRedisCacheFromClient creates a new Redis cache from an existing client
func NewRedisCacheFromClient(client *redis.Client) *RedisCache {
	return &RedisCache{
		client: client,
		ctx:    context.Background(),
	}
}

// Get retrieves a value from cache
func (c *RedisCache) Get(key string) ([]byte, error) {
	val, err := c.client.Get(c.ctx, key).Bytes()
	if err == redis.Nil {
		return nil, ErrCacheMiss
	}
	if err != nil {
		return nil, err
	}
	return val, nil
}

// Set stores a value in cache with TTL
func (c *RedisCache) Set(key string, value []byte, ttl time.Duration) error {
	return c.client.Set(c.ctx, key, value, ttl).Err()
}

// Delete removes a key from cache
func (c *RedisCache) Delete(key string) error {
	return c.client.Del(c.ctx, key).Err()
}

// Clear clears all cache keys (use with caution)
func (c *RedisCache) Clear() error {
	return c.client.FlushDB(c.ctx).Err()
}

// Close closes the Redis connection
func (c *RedisCache) Close() error {
	return c.client.Close()
}

// NewCache creates a cache based on environment
// Returns Redis cache if REDIS_URL is set, otherwise in-memory cache
func NewCache() (Cache, error) {
	redisURL := os.Getenv("REDIS_URL")
	if redisURL != "" {
		return NewRedisCache(redisURL)
	}
	return NewInMemoryCache(), nil
}

