package service

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

	"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 *config.CacheConfig
}

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

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

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

	return &Cache{
		cache:  &cache,
		logger: logger.GetLogger(logConfig),
		config: cacheConfig,
	}, 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,
		"search_ttl":   c.config.SearchTTL,
		"metadata_ttl": c.config.MetadataTTL,
	}
}

// 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.GetSearchTTL()
	}

	// 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.GetMetadataTTL()
	}

	// Default TTL for other endpoints
	return c.config.GetDefaultTTL()
}

// 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
}
