package com.fdkankan.ucenter.aop;

import com.alibaba.fastjson.JSONObject;
import com.fdkankan.redis.util.RedisUtil;
import com.fdkankan.sign.RsaUtils;
import com.fdkankan.sign.SignUtils;
import com.fdkankan.ucenter.annotation.VerifySign;
import com.fdkankan.ucenter.common.constants.ResultCode;
import com.fdkankan.ucenter.entity.AppSecret;
import com.fdkankan.ucenter.exception.BusinessException;
import com.fdkankan.ucenter.service.IAppSecretService;
import lombok.extern.slf4j.Slf4j;
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.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.util.*;

@Aspect
@Component
@Slf4j
public class SignVerifyAspect {

    @Autowired
    IAppSecretService appSecretService;
    @Autowired
    RedisUtil redisUtil;

    @Around("@annotation(verifySign)")
    public Object verifySign(ProceedingJoinPoint joinPoint, VerifySign verifySign) throws Throwable {
        if (!verifySign.enabled()) {
            return joinPoint.proceed();
        }
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String header = request.getHeader("X-UA");
        if(StringUtils.isNotBlank(header)){
            return joinPoint.proceed();
        }
        String sign = request.getHeader(verifySign.signParam().toLowerCase());
        String appId = request.getHeader(verifySign.appId().toLowerCase());

        if(StringUtils.isBlank(sign) || StringUtils.isBlank(appId)){
            log.info("verifySign--requestPath:{},sign:{},appId:{}",request.getRequestURL(),sign,appId);
            throw new BusinessException(ResultCode.SIGN_ERROR);
        }
        AppSecret byAppId = null;
        if(redisUtil.hasKey("ucenter:sign:appid:"+appId)){
            byAppId = JSONObject.parseObject(redisUtil.get("ucenter:sign:appid:"+appId),AppSecret.class);
        }else {
            byAppId = appSecretService.getByAppId(appId);
        }
        if(byAppId == null){
            log.info("verifySign--requestPath:{},sign:{},appId:{}",request.getRequestURL(),sign,appId);
            throw new BusinessException(ResultCode.SIGN_ERROR);
        }
        if(!SignUtils.checkSign(sign,appId,byAppId.getPrivateKey())){
            log.info("verifySign-checkSign-error-requestPath:{},sign:{},appId:{}",request.getRequestURL(),sign,appId);
            throw new BusinessException(ResultCode.SIGN_ERROR);
        }
        if(!redisUtil.hasKey("ucenter:sign:appid:"+appId)){
            redisUtil.set("ucenter:sign:appid:"+appId, JSONObject.toJSONString(byAppId),60 *60 *2);
        }
        return joinPoint.proceed();
    }


    public static Boolean checkSign(String sign,String appIdValue,String privateKey) {
        try {
            if(StringUtils.isBlank(sign)){
                return false;
            }
            String deTxt = RsaUtils.decipher(sign, privateKey);
            if(StringUtils.isBlank(deTxt)){
                return false;
            }
            org.json.JSONObject jsonObject = new org.json.JSONObject(deTxt);
            String appId = jsonObject.getString("appId");
            Long timestamp = jsonObject.getLong("timestamp");
            if(StringUtils.isBlank(appId) || timestamp == null){
                return false;
            }
            if(!appId.equals(appIdValue)){
                return false;
            }
            Long time = new Date().getTime();
            //app获取时间存在误差，前后五分钟失败
            if(Math.abs(time -timestamp) >1000 * 60 *5){
                return false;
            }
            return true;
        }catch (Exception e){
            return false;
        }
    }
}
