package middleware

import (
	"fmt"
	"net/http"

	"github.com/getsentry/sentry-go"
	"github.com/gin-gonic/gin"
	"github.com/google/uuid"
	"github.com/warmbly/warmbly/internal/models"
)

// RateLimitMiddleware checks rate limits for a given category
func (h *Handler) RateLimitMiddleware(category models.RateLimitCategory) gin.HandlerFunc {
	return func(c *gin.Context) {
		// Skip if no rate limit service
		if h.RateLimitService == nil {
			c.Next()
			return
		}

		userIDStr := GetUserID(c)
		if userIDStr == "" {
			c.Next()
			return
		}

		userID, err := uuid.Parse(userIDStr)
		if err != nil {
			c.Next()
			return
		}

		// Check and record the request atomically
		status, err := h.RateLimitService.CheckAndRecord(c.Request.Context(), userID, category)
		if err != nil {
			// Log error but allow request (fail open)
			sentry.CaptureException(err)
			c.Next()
			return
		}

		// Set rate limit headers
		c.Header("X-RateLimit-Limit", fmt.Sprintf("%d", status.Limit))
		c.Header("X-RateLimit-Remaining", fmt.Sprintf("%d", status.Remaining))
		c.Header("X-RateLimit-Reset", fmt.Sprintf("%d", status.ResetAt.Unix()))

		// Check if rate limited
		if status.Remaining <= 0 && status.RetryAfterMs != nil {
			c.Header("Retry-After", fmt.Sprintf("%d", *status.RetryAfterMs/1000))
			c.JSON(http.StatusTooManyRequests, gin.H{
				"error":          "rate_limit_exceeded",
				"message":        fmt.Sprintf("Rate limit exceeded for %s operations", category),
				"retry_after_ms": status.RetryAfterMs,
			})
			c.Abort()
			return
		}

		c.Next()
	}
}

// RateLimitRead is a convenience wrapper for read operations
func (h *Handler) RateLimitRead() gin.HandlerFunc {
	return h.RateLimitMiddleware(models.RateLimitRead)
}

// RateLimitWrite is a convenience wrapper for write operations
func (h *Handler) RateLimitWrite() gin.HandlerFunc {
	return h.RateLimitMiddleware(models.RateLimitWrite)
}

// RateLimitBulk is a convenience wrapper for bulk operations
func (h *Handler) RateLimitBulk() gin.HandlerFunc {
	return h.RateLimitMiddleware(models.RateLimitBulk)
}

// RateLimitUnibox is a convenience wrapper for unibox operations
func (h *Handler) RateLimitUnibox() gin.HandlerFunc {
	return h.RateLimitMiddleware(models.RateLimitUnibox)
}

// RateLimitAnalytics is a convenience wrapper for analytics operations
func (h *Handler) RateLimitAnalytics() gin.HandlerFunc {
	return h.RateLimitMiddleware(models.RateLimitAnalytics)
}
