package cache

import (
	"context"
	"errors"
	"github.com/go-redis/redis/v8"
	"os"
	"time"
)

func newRedisCache() Manager {
	redisClient := redis.NewClient(&redis.Options{
		Addr:     os.Getenv("REDIS_URL"),
		Username: os.Getenv("REDIS_USERNAME"),
		Password: os.Getenv("REDIS_PASSWORD"),
	})
	return &redisCache{redisClient}
}

type redisCache struct {
	client *redis.Client
}

func (r *redisCache) Set(key, value string, expiration time.Duration) error {
	ctx, cancel := context.WithTimeout(context.Background(), 1 * time.Second)
	defer cancel()
	return r.client.Set(ctx, key, value, expiration).Err()
}
func (r *redisCache) Get(key string) (string, error) {
	ctx, cancel := context.WithTimeout(context.Background(), 1 * time.Second)
	defer cancel()
	cacheValue := r.client.Get(ctx, key)
	return cacheValue.Val(), cacheValue.Err()
}
func (r *redisCache) Remove(key string) {
	ctx, cancel := context.WithTimeout(context.Background(), 1 * time.Second)
	defer cancel()
	r.client.Del(ctx, key)
}

func newInMemCache() Manager {
	return &inMemCache{make(map[string]inMemEntry)}
}

type inMemEntry struct {
	value string
	expiration time.Time
}

type inMemCache struct {
	entries map[string]inMemEntry
}

func (i *inMemCache) Set(key, value string, expiration time.Duration) error {
	i.entries[key] = inMemEntry{
		value:      value,
		expiration: time.Now().Add(expiration),
	}
	return nil
}
func (i *inMemCache) Get(key string) (string, error) {
	if val, exists := i.entries[key]; exists {
		if val.expiration.Before(time.Now()) {
			delete(i.entries, key)
		} else {
			return val.value, nil
		}
	}
	return "", errors.New("no value for given key")
}
func (i *inMemCache) Remove(key string) {
	delete(i.entries, key)
}
