package com.reading.platform.common.config;

import com.reading.platform.common.util.RateLimiter;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.servlet.HandlerInterceptor;

import java.io.IOException;
import java.util.List;

/**
 * 限流拦截器
 * 基于配置文件中的限流规则进行拦截
 * 优先级低于注解限流
 */
@Slf4j
@Component
public class RateLimitInterceptor implements HandlerInterceptor {

    private final RateLimiter rateLimiter;
    private final RateLimitProperties rateLimitProperties;
    private final AntPathMatcher antPathMatcher = new AntPathMatcher();

    public RateLimitInterceptor(RateLimiter rateLimiter, RateLimitProperties rateLimitProperties) {
        this.rateLimiter = rateLimiter;
        this.rateLimitProperties = rateLimitProperties;
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        // 如果限流未启用，直接放行
        if (!rateLimitProperties.isEnabled()) {
            return true;
        }

        String requestURI = request.getRequestURI();

        // 检查是否在排除列表中
        List<String> excludePatterns = rateLimitProperties.getExcludePatterns();
        if (excludePatterns != null) {
            for (String pattern : excludePatterns) {
                if (antPathMatcher.match(pattern, requestURI)) {
                    log.debug("请求在排除列表中，跳过限流：{}", requestURI);
                    return true;
                }
            }
        }

        // 查找匹配的限流规则
        RateLimitProperties.RateLimitRule matchedRule = findMatchedRule(requestURI);
        if (matchedRule == null) {
            // 没有匹配的规则，使用默认限流配置
            applyDefaultRateLimit(request, response, requestURI);
            return true;
        }

        // 应用匹配的限流规则
        return applyRateLimitRule(request, response, requestURI, matchedRule);
    }

    /**
     * 查找匹配的限流规则
     */
    private RateLimitProperties.RateLimitRule findMatchedRule(String requestURI) {
        List<RateLimitProperties.RateLimitRule> rules = rateLimitProperties.getRules();
        if (rules == null || rules.isEmpty()) {
            return null;
        }

        for (RateLimitProperties.RateLimitRule rule : rules) {
            if (antPathMatcher.match(rule.getPattern(), requestURI)) {
                log.debug("请求匹配限流规则：pattern={}, timeWindow={}, maxRequests={}",
                        rule.getPattern(), rule.getTimeWindow(), rule.getMaxRequests());
                return rule;
            }
        }

        return null;
    }

    /**
     * 应用匹配的限流规则
     */
    private boolean applyRateLimitRule(HttpServletRequest request, HttpServletResponse response, String requestURI,
                                        RateLimitProperties.RateLimitRule rule) {
        String key = buildRateLimitKey(request, rule.getPattern());

        boolean allowed = rateLimiter.tryAcquire(
                key,
                rule.getMaxRequests(),
                rule.getTimeWindow(),
                java.util.concurrent.TimeUnit.SECONDS
        );

        if (!allowed) {
            log.warn("请求被限流拦截：URI={}, 规则={}, 最大请求数={}", requestURI, rule.getPattern(), rule.getMaxRequests());
            sendRateLimitResponse(response);
            return false;
        }

        log.debug("请求通过限流检查：URI={}, 规则={}", requestURI, rule.getPattern());
        return true;
    }

    /**
     * 应用默认限流配置
     */
    private void applyDefaultRateLimit(HttpServletRequest request, HttpServletResponse response, String requestURI) {
        String key = buildRateLimitKey(request, "default");

        boolean allowed = rateLimiter.tryAcquire(
                key,
                rateLimitProperties.getDefaultMaxRequests(),
                rateLimitProperties.getDefaultTimeWindow(),
                java.util.concurrent.TimeUnit.SECONDS
        );

        if (!allowed) {
            log.warn("请求被默认限流拦截：URI={}, 最大请求数={}", requestURI, rateLimitProperties.getDefaultMaxRequests());
            sendRateLimitResponse(response);
        }
    }

    /**
     * 构建限流键
     * 格式：IP:Pattern
     */
    private String buildRateLimitKey(HttpServletRequest request, String pattern) {
        String clientIp = getClientIp(request);
        return clientIp + ":" + pattern;
    }

    /**
     * 获取客户端 IP 地址
     */
    private String getClientIp(HttpServletRequest request) {
        String xForwardedFor = request.getHeader("X-Forwarded-For");
        if (xForwardedFor != null && !xForwardedFor.isEmpty()) {
            return xForwardedFor.split(",")[0].trim();
        }

        String xRealIp = request.getHeader("X-Real-IP");
        if (xRealIp != null && !xRealIp.isEmpty()) {
            return xRealIp;
        }

        return request.getRemoteAddr();
    }

    /**
     * 发送限流响应
     */
    private void sendRateLimitResponse(HttpServletResponse response) {
        response.setStatus(429);
        response.setContentType(MediaType.APPLICATION_JSON_VALUE);
        response.setCharacterEncoding("UTF-8");

        // 添加限流响应头
        response.setHeader("X-RateLimit-Limit", "1");
        response.setHeader("X-RateLimit-Remaining", "0");
        response.setHeader("Retry-After", "60");

        try {
            String jsonResponse = "{\"code\":5001,\"message\":\"请求过于频繁，请稍后再试\",\"data\":null}";
            response.getWriter().write(jsonResponse);
        } catch (IOException e) {
            log.error("发送限流响应失败", e);
        }
    }
}
