package com.ruoyi.credit.interceptor;

import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.uuid.IdUtils;

/**
 * API调用日志拦截器
 * 
 * 记录API调用的详细信息，包括请求参数、响应状态、执行时间等
 * 
 * @author ruoyi
 * @date 2025-12-19
 */
@Component
public class ApiLoggingInterceptor implements HandlerInterceptor {

    private static final Logger logger = LoggerFactory.getLogger(ApiLoggingInterceptor.class);
    private static final Logger apiLogger = LoggerFactory.getLogger("API_CALL_LOG");

    private static final String REQUEST_START_TIME = "REQUEST_START_TIME";
    private static final String REQUEST_ID = "REQUEST_ID";

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 生成请求ID
        String requestId = IdUtils.fastSimpleUUID();
        request.setAttribute(REQUEST_ID, requestId);
        
        // 设置MDC用于日志追踪
        MDC.put("requestId", requestId);
        
        // 记录请求开始时间
        long startTime = System.currentTimeMillis();
        request.setAttribute(REQUEST_START_TIME, startTime);

        // 记录请求信息
        logRequestInfo(request, requestId);

        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        // 在视图渲染前记录响应信息
        logResponseInfo(request, response);
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        try {
            // 计算请求处理时间
            Long startTime = (Long) request.getAttribute(REQUEST_START_TIME);
            long endTime = System.currentTimeMillis();
            long duration = startTime != null ? endTime - startTime : 0;

            // 记录完整的API调用日志
            logApiCall(request, response, duration, ex);

        } finally {
            // 清理MDC
            MDC.clear();
        }
    }

    /**
     * 记录请求信息
     */
    private void logRequestInfo(HttpServletRequest request, String requestId) {
        try {
            String method = request.getMethod();
            String uri = request.getRequestURI();
            String queryString = request.getQueryString();
            String clientIp = getClientIpAddress(request);
            String userAgent = request.getHeader("User-Agent");

            logger.info("API请求开始 - RequestId: {}, Method: {}, URI: {}, Query: {}, IP: {}, UserAgent: {}", 
                       requestId, method, uri, queryString, clientIp, userAgent);

            // 记录请求头（敏感信息脱敏）
            Map<String, String> headers = getRequestHeaders(request);
            if (!headers.isEmpty()) {
                logger.debug("请求头 - RequestId: {}, Headers: {}", requestId, headers);
            }

        } catch (Exception e) {
            logger.warn("记录请求信息失败", e);
        }
    }

    /**
     * 记录响应信息
     */
    private void logResponseInfo(HttpServletRequest request, HttpServletResponse response) {
        try {
            String requestId = (String) request.getAttribute(REQUEST_ID);
            int status = response.getStatus();
            String contentType = response.getContentType();

            logger.info("API响应 - RequestId: {}, Status: {}, ContentType: {}", 
                       requestId, status, contentType);

        } catch (Exception e) {
            logger.warn("记录响应信息失败", e);
        }
    }

    /**
     * 记录完整的API调用日志
     */
    private void logApiCall(HttpServletRequest request, HttpServletResponse response, long duration, Exception ex) {
        try {
            String requestId = (String) request.getAttribute(REQUEST_ID);
            String method = request.getMethod();
            String uri = request.getRequestURI();
            String queryString = request.getQueryString();
            String clientIp = getClientIpAddress(request);
            int status = response.getStatus();
            String userAgent = request.getHeader("User-Agent");

            // 构建日志消息
            StringBuilder logMessage = new StringBuilder();
            logMessage.append("API调用完成 - ");
            logMessage.append("RequestId: ").append(requestId).append(", ");
            logMessage.append("Method: ").append(method).append(", ");
            logMessage.append("URI: ").append(uri);
            
            if (StringUtils.isNotEmpty(queryString)) {
                logMessage.append("?").append(queryString);
            }
            
            logMessage.append(", Status: ").append(status).append(", ");
            logMessage.append("Duration: ").append(duration).append("ms, ");
            logMessage.append("IP: ").append(clientIp);

            if (ex != null) {
                logMessage.append(", Exception: ").append(ex.getClass().getSimpleName())
                          .append(" - ").append(ex.getMessage());
                logger.error(logMessage.toString(), ex);
            } else {
                if (status >= 400) {
                    logger.warn(logMessage.toString());
                } else {
                    logger.info(logMessage.toString());
                }
            }

            // 记录到专门的API调用日志
            apiLogger.info("{}|{}|{}|{}|{}|{}|{}|{}", 
                          requestId, method, uri, status, duration, clientIp, 
                          StringUtils.isNotEmpty(userAgent) ? userAgent : "Unknown",
                          ex != null ? ex.getClass().getSimpleName() : "Success");

        } catch (Exception e) {
            logger.warn("记录API调用日志失败", e);
        }
    }

    /**
     * 获取请求头信息（敏感信息脱敏）
     */
    private Map<String, String> getRequestHeaders(HttpServletRequest request) {
        Map<String, String> headers = new HashMap<>();
        
        Enumeration<String> headerNames = request.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String headerName = headerNames.nextElement();
            String headerValue = request.getHeader(headerName);
            
            // 敏感信息脱敏
            if (isSensitiveHeader(headerName)) {
                headerValue = maskSensitiveValue(headerValue);
            }
            
            headers.put(headerName, headerValue);
        }
        
        return headers;
    }

    /**
     * 检查是否为敏感请求头
     */
    private boolean isSensitiveHeader(String headerName) {
        if (headerName == null) {
            return false;
        }
        
        String lowerCaseName = headerName.toLowerCase();
        return lowerCaseName.contains("authorization") ||
               lowerCaseName.contains("token") ||
               lowerCaseName.contains("password") ||
               lowerCaseName.contains("secret") ||
               lowerCaseName.contains("key");
    }

    /**
     * 脱敏敏感值
     */
    private String maskSensitiveValue(String value) {
        if (StringUtils.isEmpty(value)) {
            return value;
        }
        
        if (value.length() <= 8) {
            return "****";
        }
        
        return value.substring(0, 4) + "****" + value.substring(value.length() - 4);
    }

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

        String xRealIp = request.getHeader("X-Real-IP");
        if (StringUtils.isNotEmpty(xRealIp)) {
            return xRealIp.trim();
        }

        return request.getRemoteAddr();
    }
}