package com.evobms.common.filter;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import org.springframework.web.util.ContentCachingRequestWrapper;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Enumeration;

/**
 * HTTP请求打印过滤器（调试用途）
 * - 打印请求方法、URL、查询参数、所有请求头以及前1KB的请求体
 * - 默认关闭，通过配置开启：debug.httpdump.enabled=true
 * - 注意：可能打印敏感信息（Authorization），已做部分掩码处理
 */
@Component
@ConditionalOnProperty(value = "debug.httpdump.enabled", havingValue = "true")
public class HttpDumpFilter extends OncePerRequestFilter {
    private static final Logger log = LoggerFactory.getLogger(HttpDumpFilter.class);

    @Value("${token.header:Authorization}")
    private String tokenHeader;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {
        // 包装请求以便在下游读取后能够回读缓存内容
        ContentCachingRequestWrapper wrapper = new ContentCachingRequestWrapper(request);
        try {
            filterChain.doFilter(wrapper, response);
        } finally {
            try {
                StringBuilder sb = new StringBuilder(2048);
                String method = request.getMethod();
                String uri = request.getRequestURI();
                String query = request.getQueryString();
                sb.append("HTTP Dump >>> ").append(method).append(' ').append(uri);
                if (query != null) sb.append('?').append(query);
                sb.append('\n');

                // 打印头部
                Enumeration<String> names = request.getHeaderNames();
                while (names != null && names.hasMoreElements()) {
                    String name = names.nextElement();
                    String value = request.getHeader(name);
                    if (value == null) value = "";
                    if ("Authorization".equalsIgnoreCase(name) || name.equalsIgnoreCase(tokenHeader)) {
                        value = maskToken(value);
                    }
                    sb.append(name).append(": ").append(value).append('\n');
                }

                // 打印体（最多1KB），同时输出HEX预览以确认原始字节
                byte[] body = wrapper.getContentAsByteArray();
                if (body != null && body.length > 0) {
                    int len = Math.min(body.length, 1024);
                    String raw = new String(body, 0, len, StandardCharsets.UTF_8);
                    sb.append("\nBody[" + body.length + " bytes, show " + len + "]: ").append(raw);
                    sb.append("\nHex [show " + len + "]: ").append(toHex(body, len));
                }
                log.info(sb.toString());
            } catch (Exception e) {
                log.debug("HTTP Dump失败: {}", e.getMessage());
            }
        }
    }

    private String maskToken(String v) {
        if (v == null) return null;
        String s = v.trim();
        // 去掉 Bearer 前缀
        if (s.toLowerCase().startsWith("bearer ")) {
            s = s.substring(7);
        }
        if (s.length() <= 8) return "***";
        return "Bearer " + s.substring(0, 4) + "***" + s.substring(s.length() - 4);
    }

    private String toHex(byte[] bytes, int len) {
        StringBuilder hex = new StringBuilder(len * 2);
        for (int i = 0; i < len; i++) {
            int b = bytes[i] & 0xFF;
            String h = Integer.toHexString(b);
            if (h.length() == 1) hex.append('0');
            hex.append(h);
        }
        return hex.toString();
    }
}