package com.liquidnet.commons.lang.core;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.util.Date;
import java.util.Map;
import java.util.UUID;

@Data
@Component("jwtValidator")
@ConfigurationProperties(prefix = "jwt")
public class JwtValidator {
    private String ssoRedisKey = "adam:identity:sso:";
    /** 用户会话：adam:session:{jti} = uid */
    private String sessionRedisKey = "adam:session:";
    /** 用户下活跃 jti 集合：adam:session:user:{uid} = {jti,...}，用于按人踢线 */
    private String userSessionsRedisKey = "adam:session:user:";
    private String msoRedisKey = "adam:identity:mso:";
    private String secret;
    // 分钟
    private Long expireTtl;
    private Long refreshTtl;
    private Long blacklistGracePeriod;

//    private static final long EXPIRE_TIME = 15 * 60 * 1000;
//    private static final String TOKEN_SECRET = "qZHglvNP0n0aOOckHiQXq5JMD468J4eG";

    private SecretKey secretKey;

    private SecretKey initSecretKey(String secret) {
        if (null == this.secretKey) {
            this.secretKey = new SecretKeySpec(secret.getBytes(), SignatureAlgorithm.HS256.getJcaName());
        }
        return this.secretKey;
    }

    /**
     * 用户登录成功后生成Jwt token
     * 使用Hs256算法
     *
     * @param claimsMap 保存在Payload（有效载荷）中的内容
     * @return token字符串
     */
    public String create(Map<String, Object> claimsMap) {
        return create(claimsMap, generateJti());
    }

    public String create(Map<String, Object> claimsMap, String jti) {
        long nowMillis = System.currentTimeMillis();
        long expMillis = nowMillis + expireTtl * 60000;

        return Jwts.builder()
                .setClaims(claimsMap)
                .setId(jti)
                .setIssuedAt(new Date(nowMillis))
                .setExpiration(new Date(expMillis))
                .signWith(SignatureAlgorithm.HS256, this.initSecretKey(this.secret))
                .compact();
    }

    public String generateJti() {
        return UUID.randomUUID().toString().replace("-", "");
    }

    public String sessionKey(String jti) {
        return sessionRedisKey.concat(jti);
    }

    public String userSessionsKey(String uid) {
        return userSessionsRedisKey.concat(uid);
    }

    /**
     * 解析token，获取到Payload（有效载荷）中的内容，包括验证签名，判断是否过期
     *
     * @param token 令牌
     * @return
     */
    public Claims parse(String token) {
        return Jwts.parser()
                .setSigningKey(this.initSecretKey(this.secret))
                .parseClaimsJws(token).getBody();
    }
}
