package com.test.bijihoudaun.interceptor;

import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HtmlUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.test.bijihoudaun.common.response.R;
import com.test.bijihoudaun.common.response.ResultCode;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.servlet.HandlerInterceptor;

import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Set;

/**
 * XSS 过滤拦截器
 * 过滤请求参数和请求头中的 XSS 内容
 * 注意：此拦截器只能过滤 URL 参数和表单数据，无法过滤 @RequestBody 的 JSON 数据
 * JSON 数据的 XSS 过滤由 XssStringDeserializer 处理
 */
@Slf4j
public class XSSInterceptor implements HandlerInterceptor {

    // 修复：添加不需要检查的请求头白名单（浏览器标准请求头）
    private static final Set<String> HEADER_WHITELIST = new HashSet<>(Arrays.asList(
        "sec-ch-ua",
        "sec-ch-ua-mobile",
        "sec-ch-ua-platform",
        "sec-fetch-dest",
        "sec-fetch-mode",
        "sec-fetch-site",
        "sec-fetch-user",
        "user-agent",
        "accept",
        "accept-encoding",
        "accept-language",
        "cache-control",
        "connection",
        "host",
        "referer",
        "upgrade-insecure-requests",
        "content-type",
        "content-length",
        "origin"
    ));

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 过滤请求头，发现 XSS 攻击则拒绝请求
        if (!filterHeaders(request, response)) {
            return false;
        }

        // 过滤请求参数（URL 参数和表单数据）
        filterParameters(request);

        return true;
    }

    /**
     * 过滤请求头
     * @return true-通过，false-拒绝请求
     */
    private boolean filterHeaders(HttpServletRequest request, HttpServletResponse response) throws Exception {
        Enumeration<String> headerNames = request.getHeaderNames();
        if (headerNames == null) {
            return true;
        }

        while (headerNames.hasMoreElements()) {
            String headerName = headerNames.nextElement();
            // 修复：跳过白名单中的请求头
            if (HEADER_WHITELIST.contains(headerName.toLowerCase())) {
                continue;
            }
            String headerValue = request.getHeader(headerName);
            if (StrUtil.isNotBlank(headerValue)) {
                String filteredValue = HtmlUtil.filter(headerValue);
                // 发现 XSS 内容，记录日志并拒绝请求
                if (!headerValue.equals(filteredValue)) {
                    log.warn("检测到XSS攻击，请求头：{}，原始值：{}", headerName, headerValue);
                    writeErrorResponse(response, "检测到恶意内容，请求被拒绝");
                    return false;
                }
            }
        }
        return true;
    }

    /**
     * 过滤请求参数
     */
    private void filterParameters(HttpServletRequest request) {
        java.util.Map<String, String[]> parameterMap = request.getParameterMap();
        for (java.util.Map.Entry<String, String[]> entry : parameterMap.entrySet()) {
            String[] values = entry.getValue();
            if (values != null) {
                for (int i = 0; i < values.length; i++) {
                    if (StrUtil.isNotBlank(values[i])) {
                        values[i] = HtmlUtil.filter(values[i]);
                    }
                }
            }
        }
    }

    /**
     * 写入错误响应
     */
    private void writeErrorResponse(HttpServletResponse response, String message) throws Exception {
        response.setContentType("application/json;charset=UTF-8");
        response.setStatus(400);
        ObjectMapper mapper = new ObjectMapper();
        // 修复：使用 try-with-resources 确保 PrintWriter 关闭
        try (PrintWriter writer = response.getWriter()) {
            writer.write(mapper.writeValueAsString(
                    R.fail(ResultCode.FAILED.getCode(), message)
            ));
            writer.flush();
        }
    }
}
