package com.yushu.common.utils;

import com.yushu.common.utils.ip.IpUtils;
import com.yushu.common.utils.spring.SpringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import jakarta.servlet.http.HttpServletRequest;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Consumer;

/**
 * 错误日志工具类
 * 用于在全局异常处理器中记录错误
 * 
 * @author yushu
 */
public class ErrorLogUtils {
    
    private static final Logger log = LoggerFactory.getLogger(ErrorLogUtils.class);
    
    // 错误日志记录器（由具体实现注入）
    private static Consumer<Map<String, Object>> errorRecorder;

    /**
     * 设置错误记录器
     */
    public static void setErrorRecorder(Consumer<Map<String, Object>> recorder) {
        errorRecorder = recorder;
    }

    /**
     * 记录错误
     * 
     * @param e 异常
     * @param request HTTP请求
     * @param errorType 错误类型
     * @param errorLevel 错误级别
     */
    public static void recordError(Exception e, HttpServletRequest request, String errorType, String errorLevel) {
        if (errorRecorder == null) {
            log.warn("错误记录器未初始化，无法记录错误日志");
            return;
        }
        
        try {
            Map<String, Object> errorInfo = new HashMap<>();
            
            // 错误信息
            errorInfo.put("errorType", errorType);
            errorInfo.put("errorLevel", errorLevel);
            errorInfo.put("errorMessage", e.getMessage());
            errorInfo.put("errorDetail", getStackTrace(e));
            
            // 请求信息
            if (request != null) {
                errorInfo.put("requestUrl", request.getRequestURI());
                errorInfo.put("requestMethod", request.getMethod());
                errorInfo.put("requestParams", getRequestParams(request));
                errorInfo.put("requestIp", IpUtils.getIpAddr(request));
                errorInfo.put("userAgent", request.getHeader("User-Agent"));
            }
            
            // 用户信息
            try {
                errorInfo.put("userName", SecurityUtils.getUsername());
                errorInfo.put("userId", SecurityUtils.getUserId());
            } catch (Exception ex) {
                // 未登录用户
            }
            
            // 来源信息
            StackTraceElement[] stackTrace = e.getStackTrace();
            if (stackTrace != null && stackTrace.length > 0) {
                StackTraceElement element = stackTrace[0];
                errorInfo.put("sourceClass", element.getClassName());
                errorInfo.put("sourceMethod", element.getMethodName());
                errorInfo.put("sourceLine", element.getLineNumber());
            }
            
            // 异步记录
            errorRecorder.accept(errorInfo);
        } catch (Exception ex) {
            log.error("记录错误日志失败", ex);
        }
    }

    /**
     * 记录系统错误
     */
    public static void recordSystemError(Exception e, HttpServletRequest request) {
        recordError(e, request, "SYSTEM", "ERROR");
    }

    /**
     * 记录业务错误
     */
    public static void recordBusinessError(Exception e, HttpServletRequest request) {
        recordError(e, request, "BUSINESS", "WARN");
    }

    /**
     * 记录API错误
     */
    public static void recordApiError(Exception e, HttpServletRequest request) {
        recordError(e, request, "API", "ERROR");
    }

    /**
     * 获取异常堆栈信息
     */
    private static String getStackTrace(Exception e) {
        StringWriter sw = new StringWriter();
        e.printStackTrace(new PrintWriter(sw, true));
        String stackTrace = sw.toString();
        // 限制长度
        if (stackTrace.length() > 4000) {
            stackTrace = stackTrace.substring(0, 4000) + "...";
        }
        return stackTrace;
    }

    /**
     * 获取请求参数（包括URL参数和JSON Body）
     */
    private static String getRequestParams(HttpServletRequest request) {
        try {
            StringBuilder sb = new StringBuilder();
            
            // 1. URL查询参数
            Map<String, String[]> paramMap = request.getParameterMap();
            if (!paramMap.isEmpty()) {
                sb.append("[Query] ");
                paramMap.forEach((key, values) -> {
                    sb.append(key).append("=").append(String.join(",", values)).append("&");
                });
            }
            
            // 2. 尝试获取JSON Body（需要使用可重复读取的Request）
            try {
                String body = getRequestBody(request);
                if (body != null && !body.isEmpty()) {
                    if (sb.length() > 0) sb.append(" ");
                    sb.append("[Body] ").append(body);
                }
            } catch (Exception ignored) {
            }
            
            String params = sb.toString();
            if (params.isEmpty()) {
                return null;
            }
            if (params.length() > 4000) {
                params = params.substring(0, 4000) + "...";
            }
            return params;
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 获取请求体
     */
    private static String getRequestBody(HttpServletRequest request) {
        try {
            // 若依框架使用了 RepeatableFilter，可以重复读取
            if (request instanceof com.yushu.common.filter.RepeatedlyRequestWrapper) {
                java.io.BufferedReader reader = request.getReader();
                StringBuilder sb = new StringBuilder();
                String line;
                while ((line = reader.readLine()) != null) {
                    sb.append(line);
                }
                return sb.toString();
            }
        } catch (Exception ignored) {
        }
        return null;
    }
}
