package com.saas.shared.interceptor;

import io.github.resilience4j.ratelimiter.RateLimiter;
import io.github.resilience4j.ratelimiter.RateLimiterRegistry;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

/**
 * Rate Limiting Interceptor using Resilience4j
 * 
 * Prevents DDoS attacks, brute-force attempts, and API abuse by limiting
 * requests per IP address.
 * 
 * Configuration in application-prod.yml:
 * - /auth/login: 5 requests per minute
 * - /api/admin, /api/tenant: 100 requests per minute
 * - Global: 1000 requests per minute
 */
@Component
@Slf4j
public class RateLimitInterceptor implements HandlerInterceptor {
    
    @Autowired
    private RateLimiterRegistry rateLimiterRegistry;
    
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, 
            Object handler) throws Exception {
        
        String path = request.getRequestURI();
        String clientIp = getClientIp(request);
        String method = request.getMethod();
        
        // Determine which rate limiter to use based on endpoint
        RateLimiter rateLimiter;
        if (path.contains("/auth/login") || path.contains("/auth/register")) {
            // Strict limit for auth endpoints (brute-force protection)
            rateLimiter = rateLimiterRegistry.rateLimiter("auth");
        } else if (path.contains("/admin") || path.contains("/tenant")) {
            // Standard limit for API endpoints
            rateLimiter = rateLimiterRegistry.rateLimiter("api");
        } else {
            // Default limit for other endpoints
            rateLimiter = rateLimiterRegistry.rateLimiter("global");
        }
        
        // Check if request is allowed
        if (!rateLimiter.acquirePermission()) {
            String message = String.format(
                "🚫 Rate limit exceeded: IP=%s, Path=%s, Method=%s",
                clientIp, path, method
            );
            log.warn(message);
            
            // Return 429 Too Many Requests
            response.setStatus(HttpStatus.TOO_MANY_REQUESTS.value());
            response.setContentType("application/json");
            response.setHeader("Retry-After", "60");
            response.getWriter().write(
                "{\"error\":\"Too many requests\",\"retryAfter\":60,\"message\":\"Rate limit exceeded\"}"
            );
            return false;
        }
        
        log.debug("✅ Rate limit OK: IP={}, Path={}, Method={}", clientIp, path, method);
        return true;
    }
    
    /**
     * Extract client IP from request, considering proxy headers
     * Order: X-Forwarded-For → X-Real-IP → remote address
     */
    private String getClientIp(HttpServletRequest request) {
        String ip = request.getHeader("X-Forwarded-For");
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("X-Real-IP");
        }
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        // Return first IP if multiple (X-Forwarded-For can contain multiple IPs)
        return ip.split(",")[0].trim();
    }
}
