package services

import (
	"encoding/json"
	"gauth-central/internal/database"
	"gauth-central/internal/models"
	"time"

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

type CacheService struct{}

func NewCacheService() *CacheService {
	return &CacheService{}
}

// User Cache
func (s *CacheService) SetUser(userID string, user *models.User, expiration time.Duration) error {
	userData, err := json.Marshal(user)
	if err != nil {
		return err
	}
	return database.Set("user:"+userID, userData, expiration)
}

func (s *CacheService) GetUser(userID string) (*models.User, error) {
	data, err := database.Get("user:" + userID)
	if err != nil {
		return nil, err
	}

	var user models.User
	err = json.Unmarshal([]byte(data), &user)
	if err != nil {
		return nil, err
	}

	return &user, nil
}

func (s *CacheService) DeleteUser(userID string) error {
	return database.Delete("user:" + userID)
}

// Session Management
func (s *CacheService) SetSession(token string, userID string, expiration time.Duration) error {
	return database.Set("session:"+token, userID, expiration)
}

func (s *CacheService) GetSession(token string) (string, error) {
	return database.Get("session:" + token)
}

func (s *CacheService) DeleteSession(token string) error {
	return database.Delete("session:" + token)
}

// Rate Limiting
func (s *CacheService) IncrementRateLimit(key string, expiration time.Duration) (int64, error) {
	count, err := database.Increment("ratelimit:" + key)
	if err != nil {
		return 0, err
	}

	// Set expiration only for first increment
	if count == 1 {
		database.Expire("ratelimit:"+key, expiration)
	}

	return count, nil
}

func (s *CacheService) GetRateLimit(key string) (string, error) {
	return database.Get("ratelimit:" + key)
}

// Token Blacklist (for logout)
func (s *CacheService) BlacklistToken(token string, expiration time.Duration) error {
	return database.Set("blacklist:"+token, "1", expiration)
}

func (s *CacheService) IsTokenBlacklisted(token string) (bool, error) {
	return database.Exists("blacklist:" + token)
}

// Email Verification Token Cache
func (s *CacheService) SetEmailVerification(email string, token string, expiration time.Duration) error {
	return database.Set("email_verify:"+email, token, expiration)
}

func (s *CacheService) GetEmailVerification(email string) (string, error) {
	return database.Get("email_verify:" + email)
}

func (s *CacheService) DeleteEmailVerification(email string) error {
	return database.Delete("email_verify:" + email)
}

// Password Reset Token Cache
func (s *CacheService) SetPasswordReset(email string, token string, expiration time.Duration) error {
	return database.Set("password_reset:"+email, token, expiration)
}

func (s *CacheService) GetPasswordReset(email string) (string, error) {
	return database.Get("password_reset:" + email)
}

func (s *CacheService) DeletePasswordReset(email string) error {
	return database.Delete("password_reset:" + email)
}

// CORS Whitelist Cache
func (s *CacheService) SetCorsWhitelist(origins []string, expiration time.Duration) error {
	data, err := json.Marshal(origins)
	if err != nil {
		return err
	}
	return database.Set("cors:whitelist", data, expiration)
}

func (s *CacheService) GetCorsWhitelist() ([]string, error) {
	data, err := database.Get("cors:whitelist")
	if err != nil {
		if err == redis.Nil {
			return nil, nil
		}
		return nil, err
	}

	var origins []string
	err = json.Unmarshal([]byte(data), &origins)
	if err != nil {
		return nil, err
	}

	return origins, nil
}

func (s *CacheService) InvalidateCorsWhitelist() error {
	return database.Delete("cors:whitelist")
}

// CORS Blacklist Cache
func (s *CacheService) SetCorsBlacklist(origins []string, expiration time.Duration) error {
	data, err := json.Marshal(origins)
	if err != nil {
		return err
	}
	return database.Set("cors:blacklist", data, expiration)
}

func (s *CacheService) GetCorsBlacklist() ([]string, error) {
	data, err := database.Get("cors:blacklist")
	if err != nil {
		if err == redis.Nil {
			return nil, nil
		}
		return nil, err
	}

	var origins []string
	err = json.Unmarshal([]byte(data), &origins)
	if err != nil {
		return nil, err
	}

	return origins, nil
}

func (s *CacheService) InvalidateCorsBlacklist() error {
	return database.Delete("cors:blacklist")
}

// Rate Limit Settings Cache
func (s *CacheService) SetRateLimitSettings(settings map[string]*models.RateLimitSetting, expiration time.Duration) error {
	data, err := json.Marshal(settings)
	if err != nil {
		return err
	}
	return database.Set("settings:ratelimit", data, expiration)
}

func (s *CacheService) GetRateLimitSettings() (map[string]*models.RateLimitSetting, error) {
	data, err := database.Get("settings:ratelimit")
	if err != nil {
		if err == redis.Nil {
			return nil, nil
		}
		return nil, err
	}

	var settings map[string]*models.RateLimitSetting
	err = json.Unmarshal([]byte(data), &settings)
	if err != nil {
		return nil, err
	}

	return settings, nil
}

func (s *CacheService) InvalidateRateLimitSettings() error {
	return database.Delete("settings:ratelimit")
}
