package com.gxwebsoft.common.core.utils;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

/**
 * 日志分析工具类
 * 用于收集和分析请求相关信息
 * 
 * @author WebSoft
 * @since 2025-01-20
 */
@Slf4j
@Component
public class LogAnalysisUtil {

    /**
     * 记录请求详细信息
     */
    public static void logRequestDetails(HttpServletRequest request, String operation) {
        try {
            Map<String, Object> requestInfo = new HashMap<>();
            
            // 基本请求信息
            requestInfo.put("operation", operation);
            requestInfo.put("method", request.getMethod());
            requestInfo.put("requestURL", request.getRequestURL().toString());
            requestInfo.put("requestURI", request.getRequestURI());
            requestInfo.put("queryString", request.getQueryString());
            requestInfo.put("remoteAddr", request.getRemoteAddr());
            requestInfo.put("userAgent", request.getHeader("User-Agent"));
            
            // 请求头信息
            Map<String, String> headers = new HashMap<>();
            Enumeration<String> headerNames = request.getHeaderNames();
            while (headerNames.hasMoreElements()) {
                String headerName = headerNames.nextElement();
                // 过滤敏感信息
                if (!isSensitiveHeader(headerName)) {
                    headers.put(headerName, request.getHeader(headerName));
                }
            }
            requestInfo.put("headers", headers);
            
            // 参数信息
            Map<String, String[]> parameters = request.getParameterMap();
            Map<String, Object> params = new HashMap<>();
            parameters.forEach((key, values) -> {
                if (!isSensitiveParameter(key)) {
                    params.put(key, values.length == 1 ? values[0] : values);
                }
            });
            requestInfo.put("parameters", params);
            
            log.info("请求详情: {}", requestInfo);
            
        } catch (Exception e) {
            log.error("记录请求详情失败", e);
        }
    }

    /**
     * 记录异常详细信息
     */
    public static void logExceptionDetails(Exception exception, String context) {
        try {
            Map<String, Object> exceptionInfo = new HashMap<>();
            
            exceptionInfo.put("context", context);
            exceptionInfo.put("exceptionType", exception.getClass().getSimpleName());
            exceptionInfo.put("message", exception.getMessage());
            exceptionInfo.put("timestamp", System.currentTimeMillis());
            
            // 堆栈跟踪
            StackTraceElement[] stackTrace = exception.getStackTrace();
            if (stackTrace.length > 0) {
                StackTraceElement firstElement = stackTrace[0];
                exceptionInfo.put("errorLocation", 
                    firstElement.getClassName() + "." + firstElement.getMethodName() + 
                    "(" + firstElement.getFileName() + ":" + firstElement.getLineNumber() + ")");
            }
            
            // 根异常
            Throwable rootCause = getRootCause(exception);
            if (rootCause != exception) {
                exceptionInfo.put("rootCause", rootCause.getClass().getSimpleName());
                exceptionInfo.put("rootCauseMessage", rootCause.getMessage());
            }
            
            log.error("异常详情: {}", exceptionInfo, exception);
            
        } catch (Exception e) {
            log.error("记录异常详情失败", e);
        }
    }

    /**
     * 记录性能信息
     */
    public static void logPerformanceInfo(String operation, long startTime, long endTime) {
        try {
            long duration = endTime - startTime;
            Map<String, Object> performanceInfo = new HashMap<>();
            
            performanceInfo.put("operation", operation);
            performanceInfo.put("startTime", startTime);
            performanceInfo.put("endTime", endTime);
            performanceInfo.put("duration", duration + "ms");
            
            // 性能级别判断
            String level = "INFO";
            if (duration > 5000) {
                level = "WARN";
            } else if (duration > 10000) {
                level = "ERROR";
            }
            performanceInfo.put("performanceLevel", level);
            
            if ("ERROR".equals(level)) {
                log.error("性能异常: {}", performanceInfo);
            } else if ("WARN".equals(level)) {
                log.warn("性能告警: {}", performanceInfo);
            } else {
                log.info("性能信息: {}", performanceInfo);
            }
            
        } catch (Exception e) {
            log.error("记录性能信息失败", e);
        }
    }

    /**
     * 检查是否为敏感请求头
     */
    private static boolean isSensitiveHeader(String headerName) {
        String lowerName = headerName.toLowerCase();
        return lowerName.contains("password") || 
               lowerName.contains("token") || 
               lowerName.contains("authorization") ||
               lowerName.contains("cookie");
    }

    /**
     * 检查是否为敏感参数
     */
    private static boolean isSensitiveParameter(String paramName) {
        String lowerName = paramName.toLowerCase();
        return lowerName.contains("password") || 
               lowerName.contains("token") || 
               lowerName.contains("secret") ||
               lowerName.contains("key");
    }

    /**
     * 获取根异常
     */
    private static Throwable getRootCause(Throwable throwable) {
        Throwable rootCause = throwable;
        while (rootCause.getCause() != null && rootCause.getCause() != rootCause) {
            rootCause = rootCause.getCause();
        }
        return rootCause;
    }

    /**
     * 记录安全相关日志
     */
    public static void logSecurityEvent(String event, String username, String details, HttpServletRequest request) {
        try {
            Map<String, Object> securityInfo = new HashMap<>();
            
            securityInfo.put("event", event);
            securityInfo.put("username", username);
            securityInfo.put("details", details);
            securityInfo.put("timestamp", System.currentTimeMillis());
            securityInfo.put("remoteAddr", request != null ? request.getRemoteAddr() : "unknown");
            securityInfo.put("userAgent", request != null ? request.getHeader("User-Agent") : "unknown");
            
            log.warn("安全事件: {}", securityInfo);
            
        } catch (Exception e) {
            log.error("记录安全事件失败", e);
        }
    }
}