package services

import (
	"sync"
	"time"
)

// cacheItem 캐시 항목
type cacheItem struct {
	value     interface{}
	expiresAt time.Time
}

// CacheService 인메모리 TTL 캐시
type CacheService struct {
	mu    sync.RWMutex
	items map[string]*cacheItem
}

var cacheSvc *CacheService
var cacheOnce sync.Once

// GetCacheService 캐시 서비스 싱글턴 반환
func GetCacheService() *CacheService {
	cacheOnce.Do(func() {
		c := &CacheService{items: make(map[string]*cacheItem)}
		go c.cleanup() // 만료 항목 주기적 정리
		cacheSvc = c
	})
	return cacheSvc
}

// Set 캐시에 값 저장 (ttl: 유효기간)
func (c *CacheService) Set(key string, value interface{}, ttl time.Duration) {
	c.mu.Lock()
	defer c.mu.Unlock()
	c.items[key] = &cacheItem{
		value:     value,
		expiresAt: time.Now().Add(ttl),
	}
}

// Get 캐시에서 값 조회. 없거나 만료됐으면 nil, false 반환
func (c *CacheService) Get(key string) (interface{}, bool) {
	c.mu.RLock()
	defer c.mu.RUnlock()
	item, ok := c.items[key]
	if !ok || time.Now().After(item.expiresAt) {
		return nil, false
	}
	return item.value, true
}

// cleanup 만료된 캐시 항목을 주기적으로 삭제 (메모리 누수 방지)
func (c *CacheService) cleanup() {
	ticker := time.NewTicker(30 * time.Second)
	defer ticker.Stop()
	for range ticker.C {
		c.mu.Lock()
		now := time.Now()
		for key, item := range c.items {
			if now.After(item.expiresAt) {
				delete(c.items, key)
			}
		}
		c.mu.Unlock()
	}
}
