package tools

import (
	"sync"
	"time"
)

// RateLimiter tracks tool call counts per key (typically roomID) using a
// sliding window. It is safe for concurrent use.
type RateLimiter struct {
	maxCalls int
	window   time.Duration
	mu       sync.Mutex
	buckets  map[string][]time.Time
}

// NewRateLimiter creates a rate limiter that allows maxCalls per window per key.
func NewRateLimiter(maxCalls int, window time.Duration) *RateLimiter {
	return &RateLimiter{
		maxCalls: maxCalls,
		window:   window,
		buckets:  make(map[string][]time.Time),
	}
}

// Allow checks whether a call for the given key is within the rate limit.
// If allowed, it records the call and returns true. Otherwise returns false.
func (rl *RateLimiter) Allow(key string) bool {
	rl.mu.Lock()
	defer rl.mu.Unlock()

	now := time.Now()
	cutoff := now.Add(-rl.window)

	// Trim expired entries
	calls := rl.buckets[key]
	start := 0
	for start < len(calls) && calls[start].Before(cutoff) {
		start++
	}
	calls = calls[start:]

	if len(calls) >= rl.maxCalls {
		rl.buckets[key] = calls
		return false
	}

	rl.buckets[key] = append(calls, now)
	return true
}

// Cleanup removes stale entries for keys that have no recent calls.
// Should be called periodically to prevent memory growth.
func (rl *RateLimiter) Cleanup() {
	rl.mu.Lock()
	defer rl.mu.Unlock()

	cutoff := time.Now().Add(-rl.window)
	for key, calls := range rl.buckets {
		start := 0
		for start < len(calls) && calls[start].Before(cutoff) {
			start++
		}
		if start >= len(calls) {
			delete(rl.buckets, key)
		} else {
			rl.buckets[key] = calls[start:]
		}
	}
}
