package com.petshop.backend.security;

import com.petshop.backend.exception.ApiErrorResponder;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.http.HttpStatus;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;
import java.time.Duration;
import java.util.Map;

@Component
public class RateLimitFilter extends OncePerRequestFilter {

    private static final Map<String, int[]> RULES = Map.of(
            "/api/v1/auth/login",            new int[]{10, 15},
            "/api/v1/auth/register",         new int[]{5,  60},
            "/api/v1/auth/forgot-password",  new int[]{3,  10},
            "/api/v1/auth/reset-password",   new int[]{10, 15}
    );

    private final RateLimiterService rateLimiterService;
    private final ApiErrorResponder apiErrorResponder;

    public RateLimitFilter(RateLimiterService rateLimiterService, ApiErrorResponder apiErrorResponder) {
        this.rateLimiterService = rateLimiterService;
        this.apiErrorResponder = apiErrorResponder;
    }

    @Override
    protected void doFilterInternal(@NonNull HttpServletRequest request,
                                    @NonNull HttpServletResponse response,
                                    @NonNull FilterChain filterChain) throws ServletException, IOException {
        String path = request.getRequestURI();
        int[] rule = RULES.get(path);

        if (rule != null) {
            String ip = extractIp(request);
            String key = path + ":" + ip;
            if (!rateLimiterService.isAllowed(key, rule[0], Duration.ofMinutes(rule[1]))) {
                apiErrorResponder.write(response, HttpStatus.TOO_MANY_REQUESTS,
                        "Too many requests. Please try again later.", null, path);
                return;
            }
        }

        filterChain.doFilter(request, response);
    }

    private String extractIp(HttpServletRequest request) {
        String forwarded = request.getHeader("X-Forwarded-For");
        if (forwarded != null && !forwarded.isBlank()) {
            return forwarded.split(",")[0].trim();
        }
        return request.getRemoteAddr();
    }
}
