package com.jiayue.ipfcst.common.core.util;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTCreationException;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.interfaces.DecodedJWT;
import lombok.experimental.UtilityClass;

/**
 * JwtToken
 *
 * @author L.ym
 * @version 3.0
 **/
@UtilityClass
public class JwtUtil {

    public static final String TOKEN_AUTHORIZATION_HEADER = "Authorization";
    public static final String TOKEN_INNER_HEADER = "X-Token";
    public static final String TOKEN_PREFIX = "Bearer ";

    private final String SECRET = "!@#xwexe3@!#ds123";
    private final String ISSUER = "jiayue";

    private final String ROLE_CLAIMS = "role";

    /**
     * @Description: 单位秒，即过期时间是24个小时
     */
    private final long EXPIRATION = 24 * 60 * 60L;

    /**
     * @Description: 生成 token
     * @param: [username]
     * @return: java.lang.String
     * @Author: Liyiming
     * @Date: 2019/1/10
     */
    public String generateToken(String username) throws IllegalArgumentException, JWTCreationException {
        Algorithm algorithm = Algorithm.HMAC256(SECRET);
        String token = JWT.create().withJWTId(IdUtil.fastSimpleUUID())
                .withSubject(username)
                .withIssuer(ISSUER)
                .withIssuedAt(DateUtil.date())
                .withExpiresAt(DateUtil.date(System.currentTimeMillis() + EXPIRATION * 1000))
                // 创建一个新的JWT，并使用给定的算法进行标记
                .sign(algorithm);
        return TOKEN_PREFIX + token;
    }

    /**
     * @Description: 校验 token 是否正确
     * @param: [token, username]
     * @return: boolean
     * @Author: Liyiming
     * @Date: 2019/1/10
     */
    public boolean verify(String token, String username) throws JWTVerificationException {
        token = tokenToJwt(token);
        Algorithm algorithm = Algorithm.HMAC256(SECRET);
        // 在token中附带了username信息
        JWTVerifier verifier = JWT.require(algorithm).withSubject(username).withIssuer(ISSUER).build();
        // 验证 token
        verifier.verify(token);
        return true;
    }

    /**
     * @Description: 校验 token 是否过期
     * @param: [token]
     * @return: boolean
     * @Author: Liyiming
     * @Date: 2019/1/13
     */
    public boolean isTokenExpired(String token) throws JWTDecodeException {
        token = tokenToJwt(token);
        DecodedJWT jwt = JWT.decode(token);
        return jwt.getExpiresAt().before(DateUtil.date());
    }

    /**
     * @Description: 获得token中的信息，无需secret解密也能获得
     * @param: [token]
     * @return: java.lang.String
     * @Author: Liyiming
     * @Date: 2019/1/10
     */
    public String getUsername(String token) throws JWTDecodeException {
        token = tokenToJwt(token);
        DecodedJWT jwt = JWT.decode(token);
        return jwt.getSubject();
    }

    /**
     * @Description: 获取JWT ID
     * @param: [token]
     * @return: java.lang.String
     * @Author: Liyiming
     * @Date: 2019/1/10
     */
    public String getJwtId(String token) throws JWTDecodeException {
        token = tokenToJwt(token);
        DecodedJWT jwt = JWT.decode(token);
        return jwt.getId();
    }

    /**
     * @Description: 获取JWT
     * @param: [token]
     * @return: java.lang.String
     * @Author: Liyiming
     * @Date: 2019/1/14
     */
    public String tokenToJwt(String token) {
        return StrUtil.removePrefix(token, TOKEN_PREFIX);
    }
}
