package com.ruoyi.framework.interceptor.impl;

import java.lang.reflect.Method;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.HandlerMapping;
import com.ruoyi.framework.manager.AsyncManager;
import com.ruoyi.framework.manager.factory.AsyncFactory;

/**
 * 接口调用统计拦截器。
 * <p>
 * 目标：记录"哪些接口被调用 + 调用次数 + 耗时"，用于后续重构分析。
 * <p>
 * - 只统计能匹配到 {@link HandlerMethod} 的请求（自动跳过 404、静态资源、CORS 预检等）。
 * - 在 {@code preHandle} 记录开始时间到 request attribute。
 * - 在 {@code afterCompletion} 计算耗时，异步写库。
 * - 所有异常吞掉仅记 log，保证绝不影响主业务请求。
 *
 * @author ruoyi
 */
@Component
public class ApiCallStatsInterceptor implements HandlerInterceptor
{
    private static final Logger log = LoggerFactory.getLogger(ApiCallStatsInterceptor.class);

    /** 请求开始时间的 request attribute key */
    private static final String START_TIME_ATTR = "__api_call_stats_start__";

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
    {
        if (handler instanceof HandlerMethod)
        {
            request.setAttribute(START_TIME_ATTR, System.currentTimeMillis());
        }
        return true;
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
    {
        if (!(handler instanceof HandlerMethod))
        {
            return;
        }
        try
        {
            Object startAttr = request.getAttribute(START_TIME_ATTR);
            long start = startAttr instanceof Long ? (Long) startAttr : System.currentTimeMillis();
            long cost = System.currentTimeMillis() - start;

            HandlerMethod handlerMethod = (HandlerMethod) handler;
            Method method = handlerMethod.getMethod();
            String handlerClass = method.getDeclaringClass().getName();
            String handlerMethodName = method.getName();

            String httpMethod = request.getMethod();
            String urlPattern = resolveUrlPattern(request);

            boolean isError = ex != null || response.getStatus() >= 500;

            AsyncManager.me().execute(
                    AsyncFactory.recordApiCallStats(httpMethod, urlPattern, handlerClass, handlerMethodName,
                            cost, isError));
        }
        catch (Exception e)
        {
            log.warn("[ApiCallStats] record failed: {}", e.getMessage());
        }
    }

    /**
     * 优先使用 Spring 匹配到的 URL pattern（如 /xxx/{id}），
     * 匹配不到则回退到原始 requestURI。
     */
    private String resolveUrlPattern(HttpServletRequest request)
    {
        Object best = request.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE);
        if (best instanceof String && !((String) best).isEmpty())
        {
            return (String) best;
        }
        return request.getRequestURI();
    }
}
