package com.gnx.telemedicine.security;

import com.gnx.telemedicine.service.RateLimitingService;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;

@Component
@RequiredArgsConstructor
public class RateLimitingFilter extends OncePerRequestFilter {

    private final RateLimitingService rateLimitingService;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {
        
        String endpoint = request.getRequestURI();
        String method = request.getMethod();
        
        // Get user identifier
        String userIdentifier = getUserIdentifier(request);
        
        // Check rate limit and get remaining requests
        RateLimitingService.RateLimitResult rateLimitResult = rateLimitingService.checkRateLimit(userIdentifier, endpoint, method);
        
        if (!rateLimitResult.isAllowed()) {
            response.setStatus(HttpStatus.TOO_MANY_REQUESTS.value());
            response.setContentType("application/json");
            response.setHeader("X-RateLimit-Limit", String.valueOf(rateLimitResult.getLimit()));
            response.setHeader("X-RateLimit-Remaining", "0");
            response.setHeader("X-RateLimit-Reset", String.valueOf(rateLimitResult.getResetTime()));
            response.getWriter().write("{\"error\":\"Too many requests. Please try again later.\",\"retryAfter\":" + rateLimitResult.getResetTime() + "}");
            return;
        }
        
        // Add rate limit headers to response
        response.setHeader("X-RateLimit-Limit", String.valueOf(rateLimitResult.getLimit()));
        response.setHeader("X-RateLimit-Remaining", String.valueOf(rateLimitResult.getRemaining()));
        response.setHeader("X-RateLimit-Reset", String.valueOf(rateLimitResult.getResetTime()));
        
        filterChain.doFilter(request, response);
    }

    private String getUserIdentifier(HttpServletRequest request) {
        // Try to get authenticated user first
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (authentication != null && authentication.isAuthenticated() && !"anonymousUser".equals(authentication.getName())) {
            return "user:" + authentication.getName();
        }
        
        // Fall back to IP address
        String ipAddress = getClientIpAddress(request);
        return "ip:" + ipAddress;
    }

    private String getClientIpAddress(HttpServletRequest request) {
        String ipAddress = request.getHeader("X-Forwarded-For");
        if (ipAddress == null || ipAddress.isEmpty() || "unknown".equalsIgnoreCase(ipAddress)) {
            ipAddress = request.getHeader("Proxy-Client-IP");
        }
        if (ipAddress == null || ipAddress.isEmpty() || "unknown".equalsIgnoreCase(ipAddress)) {
            ipAddress = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ipAddress == null || ipAddress.isEmpty() || "unknown".equalsIgnoreCase(ipAddress)) {
            ipAddress = request.getRemoteAddr();
        }
        if (ipAddress != null && ipAddress.contains(",")) {
            ipAddress = ipAddress.split(",")[0].trim();
        }
        return ipAddress != null ? ipAddress : "unknown";
    }

    @Override
    protected boolean shouldNotFilter(HttpServletRequest request) {
        // Skip rate limiting for public endpoints
        String path = request.getRequestURI();
        return path.startsWith("/swagger-ui") || 
               path.startsWith("/v3/api-docs") ||
               path.equals("/swagger-ui.html");
    }
}

