package com.sckw.core.aspect;

import com.sckw.core.annotation.RepeatSubmit;
import com.sckw.core.exception.SystemException;
import com.sckw.core.model.constant.Global;
import com.sckw.core.utils.StringUtils;
import com.sckw.core.web.context.LoginUserHolder;
import com.sckw.redis.utils.RedissonUtils;
import jakarta.servlet.http.HttpServletRequest;
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.reflect.MethodSignature;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.lang.reflect.Method;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * @author czh
 * @desc 防重复提交
 * @date 2023/9/1
 */
@Aspect
@Slf4j
public class NoRepeatSubmitAspect {

    @Around("@annotation(com.sckw.core.annotation.RepeatSubmit)")
    public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) requestAttributes;
        HttpServletRequest request = servletRequestAttributes.getRequest();
        String url = request.getRequestURI();
        Long userId = LoginUserHolder.getUserId();
        if (Objects.isNull(userId)) {
            return pjp.proceed();
        }

        String key = Global.getRepeatSubmitKey(userId, url);
        String res = RedissonUtils.getString(key);
        MethodSignature signature = (MethodSignature) pjp.getSignature();
        Method method = signature.getMethod();
        RepeatSubmit annotation = method.getAnnotation(RepeatSubmit.class);
        long interval = annotation.interval();
        if (StringUtils.isNotBlank(res)) {
            if (System.currentTimeMillis() - Long.parseLong(res) < interval) {
                throw new SystemException(annotation.message());
            }
            return pjp.proceed();
        }

        RedissonUtils.putString(key, String.valueOf(System.currentTimeMillis()), interval, TimeUnit.MILLISECONDS);
        return pjp.proceed();
    }
}
