package com.mvc.interceptor;

import com.mvc.model.ErrorMap;
import com.mvc.model.ResultGeekerModel;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.concurrent.ConcurrentHashMap;

@Aspect
@Component
public class DebounceAspect {
    // 内存缓存：记录最后一次请求时间戳
    private final ConcurrentHashMap<String, Long> requestCache = new ConcurrentHashMap<>();

    @Around("@annotation(debounce)") // 绑定Debounce注解
    public Object around(ProceedingJoinPoint joinPoint, Debounce debounce) throws Throwable {
        String key = generateKey(joinPoint);
        long currentTime = System.currentTimeMillis();

        if (requestCache.containsKey(key) && (currentTime - requestCache.get(key) < debounce.interval())) {
            // 获取方法签名
            MethodSignature signature = (MethodSignature) joinPoint.getSignature();
            // 获取目标方法的 Method 对象
            Method method = signature.getMethod();
            // 获取返回类型
            Class<?> returnType = method.getReturnType();
            //由于返回类型不同(旧Map,新ResultGeekerModel)，这里需要判断返回类型，并返回对应的错误信息
            if(returnType == ErrorMap.class){
                return new ErrorMap("操作过于频繁，请稍后再试");
            }else if(returnType == ResultGeekerModel.class){
                return new ResultGeekerModel("操作过于频繁，请稍后再试");
            }else {
                throw new RepeatSubmitException("操作过于频繁，请稍后再试");
            }
        }

        requestCache.put(key, currentTime);
        return joinPoint.proceed();
    }

    // 生成唯一Key的方法
    private String generateKey(ProceedingJoinPoint joinPoint) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        String methodName = signature.getDeclaringTypeName() + "#" + signature.getName();
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String token = request.getHeader("Authorization");
        //System.out.println(methodName + ":" + token);
        return methodName + ":" + token;
    }
}
