package roomapi

import (
	"strconv"
	"sync"
	"time"

	"hyapp/pkg/appcode"
)

type roomGiftPanelConfig struct {
	GiftTypes []giftTypeConfigData
	Gifts     []giftConfigData
}

type roomGiftPanelConfigCache struct {
	mu    sync.RWMutex
	ttl   time.Duration
	items map[string]roomGiftPanelConfigCacheEntry
}

type roomGiftPanelConfigCacheEntry struct {
	config    roomGiftPanelConfig
	version   int64
	expiresAt time.Time
}

func newRoomGiftPanelConfigCache(ttl time.Duration) *roomGiftPanelConfigCache {
	if ttl <= 0 {
		ttl = 45 * time.Second
	}
	return &roomGiftPanelConfigCache{
		ttl:   ttl,
		items: make(map[string]roomGiftPanelConfigCacheEntry),
	}
}

func (c *roomGiftPanelConfigCache) Get(appCode string, regionID int64, version int64, now time.Time) (roomGiftPanelConfig, bool) {
	if c == nil {
		return roomGiftPanelConfig{}, false
	}
	key := roomGiftPanelConfigCacheKey(appCode, regionID)
	c.mu.RLock()
	entry, ok := c.items[key]
	c.mu.RUnlock()
	if !ok || entry.version != version || !now.Before(entry.expiresAt) {
		if ok {
			c.mu.Lock()
			// 过期或版本漂移时只清理当前 key，避免低频区域为了维护缓存状态引入后台 goroutine。
			if current, exists := c.items[key]; exists && (current.version != version || !now.Before(current.expiresAt)) {
				delete(c.items, key)
			}
			c.mu.Unlock()
		}
		return roomGiftPanelConfig{}, false
	}
	return cloneRoomGiftPanelConfig(entry.config), true
}

func (c *roomGiftPanelConfigCache) Set(appCode string, regionID int64, version int64, config roomGiftPanelConfig, now time.Time) {
	if c == nil {
		return
	}
	c.mu.Lock()
	defer c.mu.Unlock()
	// 写入时复制一次，读取时再复制一次；缓存只保存配置快照，不让请求级背包礼物追加影响下一次命中。
	c.items[roomGiftPanelConfigCacheKey(appCode, regionID)] = roomGiftPanelConfigCacheEntry{
		config:    cloneRoomGiftPanelConfig(config),
		version:   version,
		expiresAt: now.Add(c.ttl),
	}
}

func roomGiftPanelConfigCacheKey(appCode string, regionID int64) string {
	return appcode.Normalize(appCode) + ":" + strconv.FormatInt(regionID, 10)
}

func cloneRoomGiftPanelConfig(config roomGiftPanelConfig) roomGiftPanelConfig {
	return roomGiftPanelConfig{
		GiftTypes: append([]giftTypeConfigData(nil), config.GiftTypes...),
		Gifts:     cloneGiftConfigDataSlice(config.Gifts),
	}
}

func cloneGiftConfigDataSlice(gifts []giftConfigData) []giftConfigData {
	out := make([]giftConfigData, 0, len(gifts))
	for _, gift := range gifts {
		out = append(out, cloneGiftConfigData(gift))
	}
	return out
}

func cloneGiftConfigData(gift giftConfigData) giftConfigData {
	gift.Resource.UsageScopes = append([]string(nil), gift.Resource.UsageScopes...)
	gift.EffectTypes = append([]string(nil), gift.EffectTypes...)
	gift.RegionIDs = append([]int64(nil), gift.RegionIDs...)
	return gift
}
