package middleware

import (
	"log"
	"net/http"

	"github.com/gin-gonic/gin"

	"switchboard-core/store"
)

// RateLimiter implements per-IP rate limiting backed by a shared store.
// v0.32.0: replaces in-memory token bucket for cross-pod consistency.
//
// Fail-open: if the store is unavailable (PG down), requests are allowed.
// Auth endpoints have their own protections (bcrypt, lockout); blocking
// legitimate logins due to a rate-limit DB failure is worse than a brief burst.
type RateLimiter struct {
	store store.RateLimitStore
	rate  float64
	burst int
}

// NewRateLimiter creates a rate limiter backed by the given store.
// rate is requests per second, burst is max requests per window.
func NewRateLimiter(s store.RateLimitStore, rate float64, burst int) *RateLimiter {
	return &RateLimiter{store: s, rate: rate, burst: burst}
}

// Limit returns a Gin middleware that enforces the rate limit.
func (rl *RateLimiter) Limit() gin.HandlerFunc {
	return func(c *gin.Context) {
		key := "auth:" + c.ClientIP()

		allowed, err := rl.store.Allow(c.Request.Context(), key, rl.rate, rl.burst)
		if err != nil {
			// Fail open — don't block auth on rate limit DB failure.
			log.Printf("[ratelimit] store error (allowing request): %v", err)
			c.Next()
			return
		}

		if !allowed {
			c.Header("Retry-After", "1")
			c.AbortWithStatusJSON(http.StatusTooManyRequests, gin.H{
				"error": "rate limit exceeded",
			})
			return
		}

		c.Next()
	}
}
