package gateway

import (
	"sync"
	"time"
)

// InMemoryRateLimiter is a simple in-memory rate limiter
// In production, use Redis for distributed rate limiting
type InMemoryRateLimiter struct {
	limits map[string]*limitEntry
	mu     sync.RWMutex
	config RateLimitConfig
}

// RateLimitConfig defines rate limit configuration
type RateLimitConfig struct {
	RequestsPerSecond int
	RequestsPerMinute int
	BurstSize         int
}

// limitEntry tracks rate limit state for a key
type limitEntry struct {
	count     int
	resetAt   time.Time
	lastReset time.Time
}

// NewInMemoryRateLimiter creates a new in-memory rate limiter
func NewInMemoryRateLimiter(config RateLimitConfig) *InMemoryRateLimiter {
	return &InMemoryRateLimiter{
		limits: make(map[string]*limitEntry),
		config: config,
	}
}

// Allow checks if a request is allowed for the given key
func (rl *InMemoryRateLimiter) Allow(key string) bool {
	rl.mu.Lock()
	defer rl.mu.Unlock()

	now := time.Now()
	entry, exists := rl.limits[key]

	if !exists {
		rl.limits[key] = &limitEntry{
			count:     1,
			resetAt:   now.Add(time.Minute),
			lastReset: now,
		}
		return true
	}

	// Reset if minute has passed
	if now.After(entry.resetAt) {
		entry.count = 1
		entry.resetAt = now.Add(time.Minute)
		entry.lastReset = now
		return true
	}

	// Check limits
	if entry.count >= rl.config.RequestsPerMinute {
		return false
	}

	entry.count++
	return true
}

// Cleanup removes old entries (call periodically)
func (rl *InMemoryRateLimiter) Cleanup() {
	rl.mu.Lock()
	defer rl.mu.Unlock()

	now := time.Now()
	for key, entry := range rl.limits {
		if now.After(entry.resetAt.Add(5 * time.Minute)) {
			delete(rl.limits, key)
		}
	}
}
