package org.springblade.common.aspect;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springblade.common.utils.IPUtil;
import org.springblade.core.log.exception.ServiceException;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.concurrent.TimeUnit;

/**
 * Author pangqijun
 * Date 2022/4/14
 * Description
 */
@Slf4j
@Aspect
@Component
public class IPLimitAspect {

	@Resource
	private RedisTemplate<String, Integer> redisTemplate;
	@Resource
	private HttpServletRequest request;

	@Pointcut("@annotation(org.springblade.common.aspect.IPLimit)")
	public void pointCut() {
	}

	@Before("pointCut()")
	public void requestLimit(final JoinPoint joinPoint) {
		try {
			MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
			Method method = methodSignature.getMethod();
			IPLimit limit = method.getAnnotation(IPLimit.class);
			if (request != null) {
				String ipAddr = IPUtil.getIpAddr(request);
				String url = request.getRequestURL().toString();
				String key = "ip:limit:" + url + ":" + ipAddr;
				Integer count = redisTemplate.opsForValue().get(key);
				Long expire = redisTemplate.getExpire(key, TimeUnit.MILLISECONDS);
				System.out.println("expire1 " + expire);
				if (count == null) {
					redisTemplate.opsForValue().set(key, limit.count(), limit.time(), TimeUnit.MILLISECONDS);
//					redisTemplate.expire(key, limit.time(), TimeUnit.MILLISECONDS);
					System.out.println("expire2 " + redisTemplate.getExpire(key, TimeUnit.MILLISECONDS));
				} else {
					if (count < 1) {
						throw new ServiceException("系统繁忙，请稍后再试(request limit)");
					} else {
						redisTemplate.opsForValue().set(key, count - 1, expire, TimeUnit.MILLISECONDS);
//						redisTemplate.opsForValue().decrement(key);
					}
				}
			}
		} catch (ServiceException e) {
			throw e;
		} catch (Exception e) {
			log.error("限流异常_" + e.getMessage(), e);
		}

	}
}
