package middleware

import (
	"net/http"
	"sync"
	"time"

	"github.com/labstack/echo/v5"
)

// RateLimiterConfig defines rate limiting configuration
type RateLimiterConfig struct {
	Enabled           bool
	RequestsPerMinute int
	CleanupInterval   time.Duration
}

// DefaultRateLimiterConfig returns sensible defaults
func DefaultRateLimiterConfig() RateLimiterConfig {
	return RateLimiterConfig{
		Enabled:           true,
		RequestsPerMinute: 10,
		CleanupInterval:   5 * time.Minute,
	}
}

// RateLimiter tracks request counts per IP
type RateLimiter struct {
	mu       sync.RWMutex
	requests map[string][]time.Time
	config   RateLimiterConfig
}

// NewRateLimiter creates a new rate limiter
func NewRateLimiter(config RateLimiterConfig) *RateLimiter {
	rl := &RateLimiter{
		requests: make(map[string][]time.Time),
		config:   config,
	}

	// Start cleanup goroutine
	go rl.cleanup()

	return rl
}

// cleanup removes old request records
func (rl *RateLimiter) cleanup() {
	ticker := time.NewTicker(rl.config.CleanupInterval)
	defer ticker.Stop()

	for range ticker.C {
		rl.mu.Lock()
		now := time.Now()
		for ip, requests := range rl.requests {
			// Remove requests older than 1 minute
			var valid []time.Time
			for _, reqTime := range requests {
				if now.Sub(reqTime) < time.Minute {
					valid = append(valid, reqTime)
				}
			}
			if len(valid) == 0 {
				delete(rl.requests, ip)
			} else {
				rl.requests[ip] = valid
			}
		}
		rl.mu.Unlock()
	}
}

// Allow checks if a request from the given IP should be allowed
func (rl *RateLimiter) Allow(ip string) bool {
	rl.mu.Lock()
	defer rl.mu.Unlock()

	now := time.Now()

	// Clean old requests for this IP
	var valid []time.Time
	for _, reqTime := range rl.requests[ip] {
		if now.Sub(reqTime) < time.Minute {
			valid = append(valid, reqTime)
		}
	}
	rl.requests[ip] = valid

	// Check if limit exceeded
	if len(rl.requests[ip]) >= rl.config.RequestsPerMinute {
		return false
	}

	// Add this request
	rl.requests[ip] = append(rl.requests[ip], now)
	return true
}

// RateLimiterMiddleware returns echo middleware for rate limiting
func RateLimiterMiddleware(rl *RateLimiter) echo.MiddlewareFunc {
	return func(next echo.HandlerFunc) echo.HandlerFunc {
		return func(c *echo.Context) error {
			// If rate limiting is disabled, skip checks
			if !rl.config.Enabled {
				return next(c)
			}

			// Get client IP
			ip := c.RealIP()
			if ip == "" {
				ip = c.Request().RemoteAddr
			}

			if !rl.Allow(ip) {
				return c.JSON(http.StatusTooManyRequests, map[string]string{
					"error": "too many requests, please try again later",
				})
			}

			return next(c)
		}
	}
}
