package service

import (
	"context"
	"crypto/md5"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"strings"
	"time"

	cfg "github.com/korap/korap-mcp/config"
	"github.com/korap/korap-mcp/logger"
	"github.com/maypok86/otter"
	"github.com/rs/zerolog"
)

// CacheEntry represents a cached API response
type CacheEntry struct {
	Data      []byte        `json:"data"`
	Timestamp time.Time     `json:"timestamp"`
	TTL       time.Duration `json:"ttl"`
}

// IsExpired checks if the cache entry has expired
func (ce *CacheEntry) IsExpired() bool {
	return time.Since(ce.Timestamp) > ce.TTL
}

// Cache represents the response cache system
type Cache struct {
	cache  *otter.Cache[string, *CacheEntry]
	logger zerolog.Logger
	config CacheConfig
}

// CacheConfig configures the cache behavior
type CacheConfig struct {
	// Enabled controls whether caching is active
	Enabled bool
	// DefaultTTL is the default time-to-live for cache entries
	DefaultTTL time.Duration
	// SearchTTL is the TTL for search results
	SearchTTL time.Duration
	// MetadataTTL is the TTL for metadata and corpus information
	MetadataTTL time.Duration
	// MaxSize is the maximum number of cache entries
	MaxSize int
}

// DefaultCacheConfig returns a default cache configuration
func DefaultCacheConfig() CacheConfig {
	return CacheConfig{
		Enabled:     true,
		DefaultTTL:  5 * time.Minute,
		SearchTTL:   2 * time.Minute,  // Search results change less frequently
		MetadataTTL: 15 * time.Minute, // Metadata is more stable
		MaxSize:     1000,
	}
}

// NewCache creates a new cache instance
func NewCache(config CacheConfig) (*Cache, error) {
	// Create default logging config for cache
	logConfig := &cfg.LoggingConfig{
		Level:  "info",
		Format: "text",
	}

	if !config.Enabled {
		return &Cache{
			cache:  nil,
			logger: logger.GetLogger(logConfig),
			config: config,
		}, nil
	}

	// Create otter cache with specified capacity
	cache, err := otter.MustBuilder[string, *CacheEntry](config.MaxSize).
		CollectStats().
		WithTTL(config.DefaultTTL).
		Build()
	if err != nil {
		return nil, fmt.Errorf("failed to create cache: %w", err)
	}

	return &Cache{
		cache:  &cache,
		logger: logger.GetLogger(logConfig),
		config: config,
	}, nil
}

// generateCacheKey creates a unique cache key for a request
func (c *Cache) generateCacheKey(method, endpoint string, params map[string]any) string {
	// Create a deterministic key by combining method, endpoint, and parameters
	var keyParts []string
	keyParts = append(keyParts, method, endpoint)

	// Add sorted parameters to ensure deterministic cache keys
	// Note: json.Marshal automatically sorts map keys lexicographically,
	// providing deterministic JSON output regardless of map iteration order
	if params != nil {
		paramsJSON, _ := json.Marshal(params)
		keyParts = append(keyParts, string(paramsJSON))
	}

	key := strings.Join(keyParts, "|")

	// Hash the key to keep it reasonable length and provide privacy
	hash := md5.Sum([]byte(key))
	return hex.EncodeToString(hash[:])
}

// Get retrieves a cached response
func (c *Cache) Get(ctx context.Context, key string) ([]byte, bool) {
	if !c.config.Enabled || c.cache == nil {
		return nil, false
	}

	entry, found := (*c.cache).Get(key)
	if !found {
		c.logger.Debug().Str("key", key).Msg("Cache miss")
		return nil, false
	}

	// Check if entry has expired
	if entry.IsExpired() {
		c.logger.Debug().Str("key", key).Msg("Cache entry expired")
		(*c.cache).Delete(key)
		return nil, false
	}

	c.logger.Debug().Str("key", key).Msg("Cache hit")
	return entry.Data, true
}

// Set stores a response in the cache
func (c *Cache) Set(ctx context.Context, key string, data []byte, ttl time.Duration) {
	if !c.config.Enabled || c.cache == nil {
		return
	}

	entry := &CacheEntry{
		Data:      data,
		Timestamp: time.Now(),
		TTL:       ttl,
	}

	(*c.cache).Set(key, entry)
	c.logger.Debug().Str("key", key).Dur("ttl", ttl).Msg("Cache entry stored")
}

// Delete removes an entry from the cache
func (c *Cache) Delete(ctx context.Context, key string) {
	if !c.config.Enabled || c.cache == nil {
		return
	}

	(*c.cache).Delete(key)
	c.logger.Debug().Str("key", key).Msg("Cache entry deleted")
}

// Clear removes all entries from the cache
func (c *Cache) Clear() {
	if !c.config.Enabled || c.cache == nil {
		return
	}

	(*c.cache).Clear()
	c.logger.Debug().Msg("Cache cleared")
}

// Stats returns cache statistics
func (c *Cache) Stats() map[string]interface{} {
	if !c.config.Enabled || c.cache == nil {
		return map[string]interface{}{
			"enabled": false,
		}
	}

	stats := (*c.cache).Stats()
	return map[string]interface{}{
		"enabled":      true,
		"size":         (*c.cache).Size(),
		"hits":         stats.Hits(),
		"misses":       stats.Misses(),
		"hit_ratio":    stats.Ratio(),
		"evictions":    stats.EvictedCount(),
		"max_size":     c.config.MaxSize,
		"default_ttl":  c.config.DefaultTTL.String(),
		"search_ttl":   c.config.SearchTTL.String(),
		"metadata_ttl": c.config.MetadataTTL.String(),
	}
}

// GetTTLForEndpoint returns the appropriate TTL for a given endpoint
func (c *Cache) GetTTLForEndpoint(endpoint string) time.Duration {
	endpoint = strings.ToLower(endpoint)

	// Search endpoints get shorter TTL
	if strings.Contains(endpoint, "search") || strings.Contains(endpoint, "query") {
		return c.config.SearchTTL
	}

	// Metadata and corpus endpoints get longer TTL
	if strings.Contains(endpoint, "corpus") || strings.Contains(endpoint, "metadata") ||
		strings.Contains(endpoint, "statistics") || strings.Contains(endpoint, "info") {
		return c.config.MetadataTTL
	}

	// Default TTL for other endpoints
	return c.config.DefaultTTL
}

// Close closes the cache and cleans up resources
func (c *Cache) Close() error {
	if c.cache != nil {
		(*c.cache).Clear()
		(*c.cache).Close()
	}
	return nil
}
