package cache

import (
	"sync"
	"time"
)

const (
	// maxItems 是L1Cache的最大条目数
	// 超过此限制后将淘汰最久未使用的条目
	maxItems = 10000
)

// CacheItem 缓存项
type CacheItem struct {
	Value      interface{}
	Expiration int64
}

// Expired 判断缓存项是否过期
func (item *CacheItem) Expired() bool {
	return item.Expiration > 0 && time.Now().UnixNano() > item.Expiration
}

// L1Cache L1本地缓存（支持LRU淘汰策略）
type L1Cache struct {
	items map[string]*CacheItem
	mu    sync.RWMutex
	// accessOrder 记录key的访问顺序，用于LRU淘汰
	// 第一个是最久未使用的，最后一个是最近使用的
	accessOrder []string
}

// NewL1Cache 创建L1缓存
func NewL1Cache() *L1Cache {
	return &L1Cache{
		items: make(map[string]*CacheItem),
	}
}

// Set 设置缓存
func (c *L1Cache) Set(key string, value interface{}, ttl time.Duration) {
	c.mu.Lock()
	defer c.mu.Unlock()

	var expiration int64
	if ttl > 0 {
		expiration = time.Now().Add(ttl).UnixNano()
	}

	// 如果key已存在，更新访问顺序
	if _, exists := c.items[key]; exists {
		c.items[key] = &CacheItem{
			Value:      value,
			Expiration: expiration,
		}
		c.updateAccessOrder(key)
		return
	}

	// 检查是否超过最大容量，进行LRU淘汰
	if len(c.items) >= maxItems {
		c.evictLRU()
	}

	c.items[key] = &CacheItem{
		Value:      value,
		Expiration: expiration,
	}
	c.accessOrder = append(c.accessOrder, key)
}

// evictLRU 淘汰最久未使用的条目
func (c *L1Cache) evictLRU() {
	if len(c.accessOrder) == 0 {
		return
	}
	// 淘汰最久未使用的（第一个）
	oldest := c.accessOrder[0]
	delete(c.items, oldest)
	c.accessOrder = c.accessOrder[1:]
}

// removeFromAccessOrder 从访问顺序中移除key
func (c *L1Cache) removeFromAccessOrder(key string) {
	for i, k := range c.accessOrder {
		if k == key {
			c.accessOrder = append(c.accessOrder[:i], c.accessOrder[i+1:]...)
			return
		}
	}
}

// updateAccessOrder 更新访问顺序，将key移到最后（最近使用）
func (c *L1Cache) updateAccessOrder(key string) {
	for i, k := range c.accessOrder {
		if k == key {
			// 移除当前位置
			c.accessOrder = append(c.accessOrder[:i], c.accessOrder[i+1:]...)
			// 添加到末尾
			c.accessOrder = append(c.accessOrder, key)
			return
		}
	}
}

// Get 获取缓存
func (c *L1Cache) Get(key string) (interface{}, bool) {
	c.mu.Lock()
	defer c.mu.Unlock()

	item, ok := c.items[key]
	if !ok {
		return nil, false
	}

	if item.Expired() {
		delete(c.items, key)
		c.removeFromAccessOrder(key)
		return nil, false
	}

	// 更新访问顺序
	c.updateAccessOrder(key)

	return item.Value, true
}

// Delete 删除缓存
func (c *L1Cache) Delete(key string) {
	c.mu.Lock()
	defer c.mu.Unlock()

	delete(c.items, key)
	c.removeFromAccessOrder(key)
}

// Clear 清空缓存
func (c *L1Cache) Clear() {
	c.mu.Lock()
	defer c.mu.Unlock()

	c.items = make(map[string]*CacheItem)
	c.accessOrder = make([]string, 0)
}

// Size 获取缓存大小
func (c *L1Cache) Size() int {
	c.mu.RLock()
	defer c.mu.RUnlock()

	return len(c.items)
}

// Cleanup 清理过期缓存
func (c *L1Cache) Cleanup() {
	c.mu.Lock()
	defer c.mu.Unlock()

	now := time.Now().UnixNano()
	keysToDelete := make([]string, 0)
	for key, item := range c.items {
		if item.Expiration > 0 && now > item.Expiration {
			keysToDelete = append(keysToDelete, key)
		}
	}
	for _, key := range keysToDelete {
		delete(c.items, key)
		c.removeFromAccessOrder(key)
	}
}
