package de.oaa.xxx.config;

import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

@Component
public class RateLimitFilter extends OncePerRequestFilter {

    private static final int MAX_REQUESTS = 10;
    private static final long WINDOW_MS = 60_000;

    private static final String[] RATE_LIMITED_PATHS = {
        "/login", "/registration", "/password-reset"
    };

    private record Window(AtomicInteger count, long startMs) {}
    private final Map<String, Window> windows = new ConcurrentHashMap<>();

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
            throws ServletException, IOException {
        String path = request.getRequestURI();
        boolean isRateLimited = false;
        if ("POST".equals(request.getMethod())) {
            for (String p : RATE_LIMITED_PATHS) {
                if (path.equals(p) || path.startsWith(p + "/")) {
                    isRateLimited = true;
                    break;
                }
            }
        }

        if (isRateLimited) {
            String ip = getClientIp(request);
            String key = ip + ":" + path;
            long now = System.currentTimeMillis();

            Window window = windows.compute(key, (k, w) -> {
                if (w == null || now - w.startMs() > WINDOW_MS) {
                    return new Window(new AtomicInteger(1), now);
                }
                w.count().incrementAndGet();
                return w;
            });

            if (window.count().get() > MAX_REQUESTS) {
                response.setStatus(429);
                response.getWriter().write("Too many requests");
                return;
            }
        }

        chain.doFilter(request, response);
    }

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