package com.fs.app.utils;

import com.fs.app.annotation.NoRepeatSubmit;
import com.fs.common.utils.StringUtils;
import io.jsonwebtoken.Claims;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;

/**
 * 防重复提交Key生成器
 */
public class RepeatSubmitKeyGenerator {

    private static JwtUtils jwtUtils;

    /**
     * 设置JwtUtils（通过静态方法注入）
     */
    public static void setJwtUtils(JwtUtils jwtUtils) {
        RepeatSubmitKeyGenerator.jwtUtils = jwtUtils;
    }

    /**
     * 生成防重复提交的key
     * @param joinPoint 切点
     * @return key
     */
    public static String generateKey(ProceedingJoinPoint joinPoint) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();

        // 获取当前请求对象
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (attributes == null) {
            throw new RuntimeException("无法获取请求信息");
        }

        HttpServletRequest request = attributes.getRequest();

        // 获取用户ID（使用项目中的方式）
        String userId = getUserId(request);
        if (StringUtils.isEmpty(userId)) {
            userId = "anonymous";
        }

        // 获取请求URI
        String uri = request.getRequestURI();

        // 获取请求参数
        String params = getParamsString(joinPoint.getArgs());

        // 组合Key：前缀:userId:uri:参数哈希
        String key = "no_repeat:" + userId + ":" + uri;

        // 如果不锁定用户所有请求，则加上方法签名和参数
        NoRepeatSubmit annotation = method.getAnnotation(NoRepeatSubmit.class);
        if (annotation != null && !annotation.lockUser()) {
            // 加上方法名和参数的哈希值
            String methodInfo = method.getDeclaringClass().getName() + "." + method.getName();
            String paramHash = Integer.toHexString(params.hashCode());
            key = key + ":" + methodInfo + ":" + paramHash;
        }

        return key;
    }

    /**
     * 获取用户ID - 适配项目中的方式
     */
    private static String getUserId(HttpServletRequest request) {
        try {
            // 从Header中获取APPToken
            String token = request.getHeader("APPToken");
            if (StringUtils.isNotEmpty(token) && jwtUtils != null) {
                Claims claims = jwtUtils.getClaimByToken(token);
                if (claims != null) {
                    return claims.getSubject();
                }
            }
        } catch (Exception e) {
            // 忽略异常，返回null
        }
        return null;
    }

    /**
     * 将参数数组转换为字符串
     */
    private static String getParamsString(Object[] args) {
        if (args == null || args.length == 0) {
            return "";
        }

        StringBuilder sb = new StringBuilder();
        for (Object arg : args) {
            if (arg != null) {
                sb.append(arg.toString()).append(",");
            } else {
                sb.append("null,");
            }
        }
        return sb.toString();
    }
}