package com.srs.common.utils.sign;

import javax.servlet.http.HttpServletRequest;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.Base64;

/**
 * 图片签名工具类
 * 用于生成和验证图片访问签名URL
 */
public class ImageSignUtils {

    private static final String SECRET_KEY = "srs-stamp-secret-key-2024";
    private static final long DEFAULT_EXPIRE_TIME = 3 * 60_000; // 3分钟

    /**
     * 生成签名
     */
    public static String generateSign(String fileName, long expireTime) {
        String raw = fileName + "-" + expireTime + "-" + SECRET_KEY;
        return md5(raw);
    }

    /**
     * 生成带签名的URL
     */
    public static String generateSignedUrl(String fileName) {
        long expireTime = System.currentTimeMillis() + DEFAULT_EXPIRE_TIME;
        String sign = generateSign(fileName, expireTime);
        return String.format("/common/stamp/%s?expire=%d&sign=%s", 
            encodeFileName(fileName), expireTime, sign);
    }

    /**
     * 验证签名是否有效
     */
    public static boolean validateSign(String fileName, long expireTime, String sign) {
        if (System.currentTimeMillis() > expireTime) {
            return false; // 已过期
        }
        String expectedSign = generateSign(fileName, expireTime);
        return expectedSign.equals(sign);
    }

    /**
     * 从请求中提取文件名
     */
    public static String extractFileName(HttpServletRequest request) {
        String uri = request.getRequestURI();
        String fileName = uri.substring(uri.lastIndexOf("/common/stamp/") + 14);
        int paramIndex = fileName.indexOf("?");
        if (paramIndex > 0) {
            fileName = fileName.substring(0, paramIndex);
        }
        return decodeFileName(fileName);
    }

    /**
     * 验证请求签名
     */
    public static boolean validateRequest(HttpServletRequest request) {
        String fileName = extractFileName(request);
        String expireStr = request.getParameter("expire");
        String sign = request.getParameter("sign");
        
        if (fileName == null || expireStr == null || sign == null) {
            return false;
        }
        
        try {
            long expireTime = Long.parseLong(expireStr);
            return validateSign(fileName, expireTime, sign);
        } catch (NumberFormatException e) {
            return false;
        }
    }

    private static String encodeFileName(String fileName) {
        return Base64.getUrlEncoder().encodeToString(fileName.getBytes(StandardCharsets.UTF_8));
    }

    private static String decodeFileName(String encoded) {
        return new String(Base64.getUrlDecoder().decode(encoded), StandardCharsets.UTF_8);
    }

    private static String md5(String input) {
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            byte[] digest = md.digest(input.getBytes(StandardCharsets.UTF_8));
            StringBuilder sb = new StringBuilder();
            for (byte b : digest) {
                sb.append(String.format("%02x", b));
            }
            return sb.toString();
        } catch (Exception e) {
            throw new RuntimeException("MD5 calculation failed", e);
        }
    }
}
