package com.usoftchina.bi.server.aspect;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.usoftchina.bi.core.base.BaseContextHolder;
import com.usoftchina.bi.core.exception.MyException;
import com.usoftchina.bi.server.model.po.TokenData;
import com.usoftchina.bi.server.model.po.User;
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.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.io.UnsupportedEncodingException;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

@Aspect
@Component
public class JwtTokenAspect {
    //公共密钥
    public static String SECRET = "YouRuanKeJiBi";

    @Pointcut("@annotation(com.usoftchina.bi.server.model.pojo.annotation.CheckToken)")
    public void CheckToken() {

    }

    public TokenData createToke(User user) {
        //签发时间
        Date iaDate = new Date();
        //过期时间
        Calendar nowTime = Calendar.getInstance();
        nowTime.add(Calendar.MINUTE, 120);
        Date expiresDate = nowTime.getTime();

        //转换成时间戳
        String res;
        long ts = expiresDate.getTime();
        res = String.valueOf(ts);

        //设置header信息
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("alg", "HS256");
        map.put("typ", "JWT");
        String token = "";

        try {
            token = JWT.create()
                    .withHeader(map)
                    .withClaim("id", String.valueOf(user.getId()))
                    .withClaim("name", user.getName())
                    .withClaim("department", user.getDepartment())
                    .withClaim("post", user.getPost())
                    .withClaim("role", user.getRole())
                    .withExpiresAt(expiresDate)
                    .withIssuedAt(iaDate)
                    .sign(Algorithm.HMAC256(SECRET));
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        TokenData tokenData = new TokenData();
        tokenData.setToken(token);
        tokenData.setTimes(res);
        return tokenData;
    }

    //解密
    @Before("CheckToken()")
    @Order(1)
    public static Map<String, Claim> verifyToken(JoinPoint joinPoint) {
        DecodedJWT jwt = null;

        Object[] arg = joinPoint.getArgs();
        String token = (String) arg[0];

        JWTVerifier verifier = null;
        try {
            verifier = JWT.require(Algorithm.HMAC256(SECRET)).build();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        try {
            jwt = verifier.verify(token);
        } catch (MyException e) {
            throw new MyException(-505, "token过期");
        }

        Lock lock = new ReentrantLock();
        lock.lock();
        try {
            BaseContextHolder.setUserId(Integer.valueOf(jwt.getClaim("id").asString()));
            BaseContextHolder.setUserName(jwt.getClaim("name").asString());
            BaseContextHolder.setRole(jwt.getClaim("role").asString());
        } finally {
            lock.unlock();
        }

        return jwt.getClaims();
    }
}
