package com.pig4cloud.pig.marketing.api.util;

import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * JA4H指纹生成工具类
 * 基于HTTP请求的关键特征生成指纹，遵循JA4规范
 */
public class JA4HGeneratorUtil {

    // JA4H需要提取的关键HTTP头部（按规范定义的顺序）
    private static final List<String> KEY_HEADERS = Arrays.asList(
        "Accept",
        "Accept-Language",
        "Accept-Encoding",
        "User-Agent",
        "Connection",
        "Upgrade",
        "Content-Length",
        "Content-Type"
    );

    /**
     * 生成JA4H指纹
     * @param method HTTP方法（如GET、POST）
     * @param path 请求路径（不含查询参数）
     * @param httpVersion HTTP版本（如HTTP/1.1）
     * @param headers HTTP请求头部键值对
     * @return JA4H指纹（MD5哈希值）
     */
    public String generateJA4H(String method, String path, String httpVersion, Map<String, String> headers) {
        try {
            // 1. 规范化输入参数
            String normalizedMethod = normalizeMethod(method);
            String normalizedPath = normalizePath(path);
            String normalizedVersion = normalizeHttpVersion(httpVersion);
            
            // 2. 提取并规范化关键头部
            List<String> headerValues = extractAndNormalizeHeaders(headers);
            
            // 3. 按JA4H规则拼接原始字符串
            String rawJA4H = buildRawJA4HString(
                normalizedMethod,
                normalizedPath,
                normalizedVersion,
                headerValues
            );
            
            // 4. 计算MD5哈希作为最终指纹
            return computeMD5(rawJA4H);
            
        } catch (Exception e) {
            throw new RuntimeException("Failed to generate JA4H fingerprint", e);
        }
    }

    /**
     * 规范化HTTP方法（大写处理）
     */
    private String normalizeMethod(String method) {
        return method == null ? "" : method.trim().toUpperCase();
    }

    /**
     * 规范化请求路径（去除查询参数，保留基础路径）
     */
    private String normalizePath(String path) {
        if (path == null || path.trim().isEmpty()) {
            return "/";
        }
        // 移除查询参数（?后面的部分）
        int queryIndex = path.indexOf('?');
        return queryIndex != -1 ? path.substring(0, queryIndex).trim() : path.trim();
    }

    /**
     * 规范化HTTP版本
     */
    private String normalizeHttpVersion(String version) {
        if (version == null) {
            return "";
        }
        // 提取主版本（如HTTP/1.1 -> 1.1）
        String[] parts = version.trim().split("/");
        return parts.length > 1 ? parts[1] : version.trim();
    }

    /**
     * 提取并规范化关键头部
     * 按KEY_HEADERS定义的顺序提取，不存在的头部用空字符串表示
     */
    private List<String> extractAndNormalizeHeaders(Map<String, String> headers) {
        if (headers == null) {
            headers = Collections.emptyMap();
        }
        
        // 转换为小写键的映射，方便查找
        Map<String, String> lowerCaseHeaders = headers.entrySet().stream()
                .collect(Collectors.toMap(
                    entry -> entry.getKey().toLowerCase(),
                    entry -> normalizeHeaderValue(entry.getValue()),
                    (v1, v2) -> v1 // 处理重复头部，取第一个值
                ));
        
        // 按预设顺序提取头部值
        return KEY_HEADERS.stream()
                .map(header -> lowerCaseHeaders.getOrDefault(header.toLowerCase(), ""))
                .collect(Collectors.toList());
    }

    /**
     * 规范化头部值（去除首尾空格，多个值用逗号拼接）
     */
    private String normalizeHeaderValue(String value) {
        if (value == null) {
            return "";
        }
        // 处理多个值的情况（如Accept: text/html, application/json）
        return value.trim().replaceAll("\\s+,\\s+", ",").replaceAll("\\s+", " ");
    }

    /**
     * 构建JA4H原始字符串
     * 格式：method,path,version,header1,header2,...
     */
    private String buildRawJA4HString(String method, String path, String version, List<String> headers) {
        List<String> parts = new ArrayList<>();
        parts.add(method);
        parts.add(path);
        parts.add(version);
        parts.addAll(headers);
        // 用逗号分隔所有部分
        return String.join(",", parts);
    }

    /**
     * 计算字符串的MD5哈希
     */
    private String computeMD5(String input) throws NoSuchAlgorithmException {
        MessageDigest md = MessageDigest.getInstance("MD5");
        byte[] digest = md.digest(input.getBytes(StandardCharsets.UTF_8));
        
        // 转换为16进制字符串
        StringBuilder hexString = new StringBuilder();
        for (byte b : digest) {
            String hex = String.format("%02x", b);
            hexString.append(hex);
        }
        return hexString.toString();
    }

    // 示例用法
    public static void main(String[] args) {
        // 模拟一个HTTP请求
        String method = "GET";
        String path = "/api/data?param=123"; // 路径会自动去除查询参数
        String httpVersion = "HTTP/1.1";
        
        Map<String, String> headers = new HashMap<>();
        headers.put("Accept", "text/html, application/xhtml+xml");
        headers.put("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/114.0.0.0");
        headers.put("Accept-Encoding", "gzip, deflate, br");
        headers.put("Connection", "keep-alive");
        
        JA4HGeneratorUtil generator = new JA4HGeneratorUtil();
        String ja4h = generator.generateJA4H(method, path, httpVersion, headers);
        System.out.println("Generated JA4H fingerprint: " + ja4h);
    }
}
