package com.xinelu.framework.aspectj;

import com.xinelu.common.constant.Constants;
import com.xinelu.common.exception.ServiceException;
import io.jsonwebtoken.Jwts;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Objects;

/**
 * @Description 移动端接口校验处理
 * @Author 纪寒
 * @Date 2022-12-09 10:55:53
 * @Version 1.0
 */
@Slf4j
@Aspect
@Component
public class MobileRequestAuthorizationAspect {

    /**
     * 令牌秘钥标识
     */
    @Value("${token.secret}")
    private String secret;

    /**
     * 令牌自定义标识
     */
    @Value("${token.header}")
    private String header;

    /**
     * 移动端令牌前缀
     */
    private static final String TOKEN_PREFIX = "Bearer ";

    /**
     * 移动端令牌前缀
     */
    private static final Integer ERROR_CODE = 9999;

    @Resource
    private RedisTemplate<String, String> redisTemplate;

    @Pointcut("execution(@com.xinelu.common.annotation.MobileRequestAuthorization * *(..))")
    private void judgeTokenInfo() {
    }

    @Before("judgeTokenInfo()")
    public void doJudgeTokenInfo() {
        HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
        String requestHeader = request.getHeader(header);
        if (StringUtils.isBlank(requestHeader)) {
            log.warn("获取请求头中的Authorization令牌头部信息失败！");
            throw new ServiceException("验证签名错误，请重新登录！", ERROR_CODE);
        }
        try {
            String token = request.getHeader(header).replaceAll(TOKEN_PREFIX, "");
            if (StringUtils.isBlank(token)) {
                log.warn("获取请求头中的Authorization令牌信息为空！");
                throw new ServiceException("验证签名错误，请重新登录！", ERROR_CODE);
            }
            String uuid = (String) Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody().get(Constants.MOBILE_AUTHORIZATION_PREFIX);
            String tokenString = redisTemplate.opsForValue().get(Constants.MOBILE_AUTHORIZATION_KEY + uuid);
            if (StringUtils.isBlank(tokenString) || !StringUtils.equals(token, tokenString)) {
                log.warn("Redis中的令牌信息已失效或者为空！");
                throw new ServiceException("验证签名错误，请重新登录！", ERROR_CODE);
            }
        } catch (Exception e) {
            log.error("移动端验证签名异常，异常信息为=====>{}", e.getMessage());
            throw new ServiceException("验证签名错误，请重新登录！", ERROR_CODE);
        }
    }
}
