package cache

import (
	"fmt"
	"time"
)

// Key prefixes for different data types
const (
	PrefixSession        = "session"
	PrefixUser           = "user"
	PrefixCatalog        = "catalog"
	PrefixDownload       = "download"
	PrefixRateLimit      = "ratelimit"
	PrefixLock           = "lock"
	PrefixSearch         = "search"
	PrefixRecommendation = "recommendation"
)

// TTL constants
const (
	TTLSession        = 24 * time.Hour
	TTLUser           = 15 * time.Minute
	TTLCatalog        = 5 * time.Minute
	TTLDownload       = 30 * time.Second
	TTLRateLimit      = 1 * time.Minute
	TTLLock           = 30 * time.Second
	TTLSearch         = 10 * time.Minute
	TTLRecommendation = 1 * time.Hour
)

// KeyBuilder provides methods to build cache keys
type KeyBuilder struct {
	namespace string
}

// NewKeyBuilder creates a new key builder with a namespace
func NewKeyBuilder(namespace string) *KeyBuilder {
	return &KeyBuilder{namespace: namespace}
}

// Build creates a cache key from parts
func (kb *KeyBuilder) Build(parts ...string) string {
	if kb.namespace == "" {
		return join(parts...)
	}
	return join(append([]string{kb.namespace}, parts...)...)
}

// SessionKey builds a key for session data
func (kb *KeyBuilder) SessionKey(sessionID string) string {
	return kb.Build(PrefixSession, sessionID)
}

// UserKey builds a key for user data
func (kb *KeyBuilder) UserKey(userID string) string {
	return kb.Build(PrefixUser, userID)
}

// UserProfileKey builds a key for user profile data
func (kb *KeyBuilder) UserProfileKey(userID string) string {
	return kb.Build(PrefixUser, userID, "profile")
}

// CatalogDashboardKey builds a key for dashboard data
func (kb *KeyBuilder) CatalogDashboardKey(userID string) string {
	return kb.Build(PrefixCatalog, "dashboard", userID)
}

// CatalogDiscoverKey builds a key for discover sections
func (kb *KeyBuilder) CatalogDiscoverKey(genre, mediaType string, page int) string {
	return kb.Build(PrefixCatalog, "discover", genre, mediaType, fmt.Sprintf("page:%d", page))
}

// CatalogSearchKey builds a key for search results
func (kb *KeyBuilder) CatalogSearchKey(query, genre, mediaType string) string {
	return kb.Build(PrefixSearch, query, genre, mediaType)
}

// DownloadJobKey builds a key for download job data
func (kb *KeyBuilder) DownloadJobKey(jobID string) string {
	return kb.Build(PrefixDownload, "job", jobID)
}

// DownloadListKey builds a key for user's download list
func (kb *KeyBuilder) DownloadListKey(userID string, status string) string {
	return kb.Build(PrefixDownload, "list", userID, status)
}

// RateLimitKey builds a key for rate limiting
func (kb *KeyBuilder) RateLimitKey(identifier, action string) string {
	return kb.Build(PrefixRateLimit, identifier, action)
}

// LockKey builds a key for distributed locks
func (kb *KeyBuilder) LockKey(resource string) string {
	return kb.Build(PrefixLock, resource)
}

// RecommendationKey builds a key for user recommendations
func (kb *KeyBuilder) RecommendationKey(userID string) string {
	return kb.Build(PrefixRecommendation, userID)
}

// WatchLaterKey builds a key for watch later list
func (kb *KeyBuilder) WatchLaterKey(userID string) string {
	return kb.Build(PrefixCatalog, "watchlater", userID)
}

// ContinueWatchingKey builds a key for continue watching list
func (kb *KeyBuilder) ContinueWatchingKey(userID string) string {
	return kb.Build(PrefixCatalog, "continue", userID)
}

// join concatenates strings with a colon separator
func join(parts ...string) string {
	if len(parts) == 0 {
		return ""
	}

	result := parts[0]
	for i := 1; i < len(parts); i++ {
		if parts[i] != "" {
			result += ":" + parts[i]
		}
	}

	return result
}
