package checks

import (
	"sync"
	"time"
)

// cacheEntry holds cached disk space information with TTL
type cacheEntry struct {
	check     *DiskSpaceCheck
	timestamp time.Time
}

// DiskSpaceCache provides thread-safe caching of disk space checks with TTL
type DiskSpaceCache struct {
	cache    map[string]*cacheEntry
	cacheTTL time.Duration
	mu       sync.RWMutex
}

// NewDiskSpaceCache creates a new disk space cache with specified TTL
func NewDiskSpaceCache(ttl time.Duration) *DiskSpaceCache {
	if ttl <= 0 {
		ttl = 30 * time.Second // Default 30 second cache
	}

	return &DiskSpaceCache{
		cache:    make(map[string]*cacheEntry),
		cacheTTL: ttl,
	}
}

// Get retrieves cached disk space check or performs new check if cache miss/expired
func (c *DiskSpaceCache) Get(path string) *DiskSpaceCheck {
	c.mu.RLock()
	if entry, exists := c.cache[path]; exists {
		if time.Since(entry.timestamp) < c.cacheTTL {
			c.mu.RUnlock()
			return entry.check
		}
	}
	c.mu.RUnlock()

	// Cache miss or expired - perform new check
	check := CheckDiskSpace(path)

	c.mu.Lock()
	c.cache[path] = &cacheEntry{
		check:     check,
		timestamp: time.Now(),
	}
	c.mu.Unlock()

	return check
}

// Clear removes all cached entries
func (c *DiskSpaceCache) Clear() {
	c.mu.Lock()
	defer c.mu.Unlock()
	c.cache = make(map[string]*cacheEntry)
}

// Cleanup removes expired entries (call periodically)
func (c *DiskSpaceCache) Cleanup() {
	c.mu.Lock()
	defer c.mu.Unlock()

	now := time.Now()
	for path, entry := range c.cache {
		if now.Sub(entry.timestamp) >= c.cacheTTL {
			delete(c.cache, path)
		}
	}
}

// Global cache instance with 30-second TTL
var globalDiskCache = NewDiskSpaceCache(30 * time.Second)

// CheckDiskSpaceCached performs cached disk space check
func CheckDiskSpaceCached(path string) *DiskSpaceCheck {
	return globalDiskCache.Get(path)
}
