package com.bonus.common.security.aspect;

import com.alibaba.fastjson2.JSON;
import com.bonus.common.redis.service.RedisService;
import com.bonus.common.security.annotation.PreventRepeatSubmit;
import com.bonus.common.security.enums.HttpCodeEnum;
import com.bonus.common.security.exception.BusinessException;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
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.concurrent.TimeUnit;

@Aspect
@Component
@Slf4j
public class PreventRepeatSubmitAspect {
    private static final String header = "Authorization";

    @Autowired
    private RedisService redisCache;

    // 定义一个切入点，待测试使用
    @Pointcut("@annotation(com.bonus.common.security.annotation.PreventRepeatSubmit)")
    public void preventRepeatSubmit() {
        log.debug("进入preventRepeatSubmit切面");
    }
    @Around("preventRepeatSubmit()")
    public Object checkPrs(ProceedingJoinPoint pjp) throws Throwable {
        log.debug("进入preventRepeatSubmit切面");
        //得到request对象
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String requestURI = request.getRequestURI();
        log.debug("防重复提交的请求地址：{} ,请求方式：{}",requestURI,request.getMethod());
        log.debug("防重复提交拦截到的类名：{} ,方法：{}",pjp.getTarget().getClass().getSimpleName(),pjp.getSignature().getName());

        //获取请求参数
        Object[] args = pjp.getArgs();
        String argStr = JSON.toJSONString(args);
        //这里替换是为了在redis可视化工具中方便查看
        argStr=argStr.replace(":","#");
        // 唯一值（没有消息头则使用请求地址）
        String submitKey = request.getHeader(header).trim();
        // 唯一标识（指定key + url +参数+token）
        String cacheRepeatKey = "repeat_submit:" + requestURI+":" +argStr+":"+ submitKey;
        MethodSignature ms = (MethodSignature) pjp.getSignature();
        Method method=ms.getMethod();
        PreventRepeatSubmit preventRepeatSubmit=method.getAnnotation(PreventRepeatSubmit.class);
        int interval = preventRepeatSubmit.interval();
        log.debug("获取到preventRepeatSubmit的有效期时间"+interval);
        //redis分布式锁
       // Boolean aBoolean = redisCache.setCacheObject(cacheRepeatKey, 1, preventRepeatSubmit.interval(), TimeUnit.SECONDS);
        Boolean aBoolean = redisCache.setNxCacheObject(cacheRepeatKey, 1, preventRepeatSubmit.interval(), TimeUnit.SECONDS);
        //aBoolean为true则证明没有重复提交
        if(!aBoolean){
            log.debug("重复提交，请稍后重试");
            throw new BusinessException(HttpCodeEnum.REPEATE_ERROR);
        }
        return pjp.proceed();
    }

}
