package com.skr.mdm.util;

import com.skr.mdm.authentication.TokenExpireException;
import com.skr.mdm.dto.LoginAdminDTO;
import com.skr.mdm.enums.ResultCodeEnum;
import com.skr.mdm.service.impl.AdminTokenServiceJWTImpl;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.SignatureException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;

import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;
import java.security.Key;
import java.util.Date;
import java.util.Map;

/**
 * @author nfq
 * @date 2020/7/9 19:00
 */
@Slf4j
public class JwtAdminUtil {
    /**
     * jwt加密私钥
     */
    private static final String JWT_SECRET = "mdmCrypto2022614";

    private static Key KEY = null;
    private static final String LOGIN_USER_KEY = "LOGIN_USER_KEY";
    private static final String LOGIN_USER = "LOGIN_USER";
    private static final String LOGIN_USER_PASSWORD = "LOGIN_USER_PASSWORD";

    /**
     * 生成jwt
     *
     * @param loginAdminDTO
     * @return
     */
    public static String createJWTToken(LoginAdminDTO loginAdminDTO) {
        String jwtToken = Jwts.builder()
                .setExpiration(new Date(loginAdminDTO.getTokenExpireTime()))
                .setIssuedAt(new Date(loginAdminDTO.getLoginTime()))
                .claim(LOGIN_USER_KEY, loginAdminDTO.getToken())
                .claim(LOGIN_USER, loginAdminDTO.getAdminName())
                .claim(LOGIN_USER_PASSWORD, loginAdminDTO.getPassword())
                .signWith(SignatureAlgorithm.HS512, getKeyInstance()).compact();
        return jwtToken;
    }

    public static String getUUIDFromJWT(String jwtToken) {
        String nullVal = "null";
        if (nullVal.equals(jwtToken) || StringUtils.isBlank(jwtToken)) {
            return null;
        }
        try {
            Map<String, Object> jwtClaims = Jwts.parser().setSigningKey(getKeyInstance()).parseClaimsJws(jwtToken).getBody();
            return MapUtils.getString(jwtClaims, LOGIN_USER_KEY);
        } catch (ExpiredJwtException e) {
//            log.warn("JWT已过期：{}", jwtToken);
            throw new TokenExpireException(ResultCodeEnum.TOKEN_EXPIRE.getCode(), ResultCodeEnum.TOKEN_EXPIRE.getMsg());
        } catch (SignatureException e) {
            log.error("JWT签名认证失败：", e);
            throw new TokenExpireException(ResultCodeEnum.TOKEN_ILLEGAL.getCode(), ResultCodeEnum.TOKEN_ILLEGAL.getMsg());
        }
    }

    private static Key getKeyInstance() {
        if (KEY == null) {
            synchronized (AdminTokenServiceJWTImpl.class) {
                // 双重锁
                if (KEY == null) {
                    byte[] apiKeySecretBytes = DatatypeConverter.parseBase64Binary(JWT_SECRET);
                    KEY = new SecretKeySpec(apiKeySecretBytes, SignatureAlgorithm.HS512.getJcaName());
                }
            }
        }
        return KEY;
    }
}
