package com.clx.performance.aspect;

import cn.hutool.json.JSONUtil;
import com.clx.performance.annotation.ResetPassword;
import com.clx.performance.constant.RedisConstants;
import com.clx.performance.enums.PerformanceResultEnum;
import com.clx.performance.param.app.CheckMobileParam;
import com.clx.performance.param.app.InformationParam;
import com.msl.common.exception.ServiceSystemException;
import com.msl.common.result.Result;
import org.apache.commons.lang3.StringUtils;
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.core.DefaultParameterNameDiscoverer;
import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Component
@Aspect
public class ResetPasswordAnnotationAop {

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Pointcut("@annotation(com.clx.performance.annotation.ResetPassword)")
    private void annotationPointCut() {
    }

    @Around("annotationPointCut()")
    public Object annotationAround(ProceedingJoinPoint jp) throws Throwable {
        //获取方法
        Method method = ((MethodSignature) jp.getSignature()).getMethod();
        // 获取AspectAnnotation注解
        ResetPassword aspectAnnotation = method.getAnnotation(ResetPassword.class);
        String mobile = "";
        if (aspectAnnotation.name().equals("checkMobile")) {
            CheckMobileParam bean = JSONUtil.toBean(JSONUtil.parse(jp.getArgs()[0]).toString(), CheckMobileParam.class);
            mobile = JSONUtil.parse(jp.getArgs()[0]).getByPath("mobile").toString();
            String token = bean.getToken();
            String redisVal = redisTemplate.opsForValue().get(RedisConstants.MESSAGE_RESET_PASSWORD_TOKEN + mobile);
            if (!StringUtils.equals(token, redisVal)) {
                throw new RuntimeException("抛异常");
            }


        } else if (aspectAnnotation.name().equals("sendMobileCaptcha")) {
            mobile = JSONUtil.parse(jp.getArgs()[0]).getByPath("mobile").toString();
            String content = redisTemplate.opsForValue().get(RedisConstants.MESSAGE_CAPTCHA_ID + mobile);
            if (StringUtils.isNoneBlank(content)) {
                String token = UUID.randomUUID().toString();
                redisTemplate.opsForValue().set(RedisConstants.MESSAGE_RESET_PASSWORD_TOKEN + mobile, token);
                redisTemplate.expire(RedisConstants.MESSAGE_RESET_PASSWORD_TOKEN + mobile, 60, TimeUnit.SECONDS);

                return token;
            }

            String count = redisTemplate.opsForValue().get(RedisConstants.MESSAGE_CAPTCHA_MOBILE_COUNT + mobile);
            if (StringUtils.isNotBlank(content) && Integer.parseInt(count) >= 10) {
                throw new ServiceSystemException(PerformanceResultEnum.CAPTCHA_MORE_COUNT);
            }

        } else if (aspectAnnotation.name().equals("checkBusinessLicenseNumber")) {
            InformationParam bean = JSONUtil.toBean(JSONUtil.parse(jp.getArgs()[0]).toString(), InformationParam.class);
            mobile = JSONUtil.parse(jp.getArgs()[0]).getByPath("mobile").toString();
            String token = bean.getToken();
            String redisVal = redisTemplate.opsForValue().get(RedisConstants.MESSAGE_RESET_PASSWORD_TOKEN + mobile);
            if (!StringUtils.equals(token, redisVal)) {
                throw new RuntimeException("抛异常");
            }
        }

        //执行方法前
        Object returnVal = null;

        returnVal = jp.proceed();
        Result result = JSONUtil.toBean(JSONUtil.parse(returnVal).toString(), Result.class);
        if (aspectAnnotation.name().equals("sendMobileCaptcha")) {
            //执行方法后
            redisTemplate.opsForValue().increment(RedisConstants.MESSAGE_CAPTCHA_MOBILE_COUNT + mobile);
            redisTemplate.expire(RedisConstants.MESSAGE_CAPTCHA_MOBILE_COUNT + mobile, 60, TimeUnit.SECONDS);
        }

        redisTemplate.opsForValue().set(RedisConstants.MESSAGE_RESET_PASSWORD_TOKEN + mobile, result.getData().toString());
        redisTemplate.expire(RedisConstants.MESSAGE_RESET_PASSWORD_TOKEN + mobile, 60, TimeUnit.SECONDS);

        return returnVal;
    }

    private static Map<String, Object> getFieldsName(ProceedingJoinPoint joinPoint) {

        Object[] args = joinPoint.getArgs();
        ParameterNameDiscoverer pnd = new DefaultParameterNameDiscoverer();
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        String[] parameterNames = pnd.getParameterNames(method);
        Map<String, Object> paramMap = new HashMap<>(8);
        for (int i = 0; i < parameterNames.length; i++) {
            paramMap.put(parameterNames[i], args[i]);
        }
        return paramMap;
    }

}
