package com.storlead.framework.auth.jwt;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.JSONObject;
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;

import java.util.*;

/**
 * @program: storlead-storlead-mail-platform
 * @description:
 * @author: chenkq
 * @create: 2025-07-09 14:53
 */
public class JwtUtil {

    /**
     * 失效时间： 1 天 =24*3600*1000 ms
     */
    public static final long  EFFECTIVE_TIME = 1 * 24 * 3600 * 1000;
    /**
     * 私钥
     */
    public static final String APP_SECRET = "sp_user_2012";
    /**
     * token 前缀
     */
    public static final String APP_KEY = "sp_APP_KEY";
    public static final String CLAIMS_KEY = "sp_CLAIMS_KEY";
    /**
     * 用户登录成功后生成Jwt
     * 使用Hs256算法  私匙使用用户密码
     *
     * @param jsonInfo
     * @param subjectKey
     * @return
     */
    public static String createJWT(String jsonInfo,String subjectKey) {

        //指定签名的时候使用的签名算法，也就是header那部分，jjwt已经将这部分内容封装好了。
        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;

        long nowMillis = System.currentTimeMillis();
        Date now = new Date(nowMillis);
        //创建payload的私有声明（根据特定的业务需要添加，如果要拿这个做验证，一般是需要和jwt的接收方提前沟通好验证方式的）
        //EntityUtils.entityToMap(user)

        Map<String, Object> claims = new HashMap<>();
        claims.put(CLAIMS_KEY, JSONObject.toJSON(jsonInfo));
        //生成签发人
        String subject = subjectKey;
        //下面就是在为payload添加各种标准声明和私有声明了 JwtBuilder
        //这里其实就是new一个JwtBuilder，设置jwt的body
        JwtBuilder builder = Jwts.builder()
                //如果有私有声明，一定要先设置这个自己创建的私有的声明，这个是给builder的claim赋值，一旦写在标准的声明赋值之后，就是覆盖了那些标准的声明的
                .setClaims(claims)
                //设置jti(JWT ID)：是JWT的唯一标识，根据业务需要，这个可以设置为一个不重复的值，主要用来作为一次性token,从而回避重放攻击。
                .setId(UUID.randomUUID().toString())
                //iat: jwt的签发时间
                .setIssuedAt(now)
                //代表这个JWT的主体，即它的所有人，这个是一个json格式的字符串，可以存放什么userid，roldid之类的，作为什么用户的唯一标志。
                .setSubject(subject)
                //设置签名使用的签名算法和签名使用的秘钥Algorithm
                .signWith(signatureAlgorithm, APP_KEY);

        return builder.compact();
    }


    /**
     * Token的解密
     * @param jwtToken 加密后的token
     * @return
     */
    public static String parseJWT(String jwtToken) {
        //签名秘钥，和生成的签名的秘钥一模一样
        Claims claims = Jwts.parser()
                //设置签名的秘钥
                .setSigningKey(APP_KEY)
                //设置需要解析的jwt
                .parseClaimsJws(jwtToken).getBody();
        LinkedHashMap linkedHashMap = (LinkedHashMap)claims.get(CLAIMS_KEY);
        String json =JSONObject.toJSONString(linkedHashMap);
        return json;
    }



    //设置token的密钥
//    private final static String SECRET = "token123";

    public static String getGptToken(String apiKey) {
        String[] apiKeySet = apiKey.split("\\.");
        String apiKeyId = apiKeySet[0];

        Date signDate = new Date();
        Date date = new Date(System.currentTimeMillis() + EFFECTIVE_TIME);//过期时间
        Algorithm algorithm = Algorithm.HMAC256(apiKeySet[1]);//进行加密算法

        //token的Header信息
        Map<String, Object> map = new HashMap<>();
        map.put("alg", "HS256");
        map.put("sign_type", "SIGN");

        String token= JWT.create()
                //(token的Header信息)
                .withHeader(map)
                //设置当前签发时间(token的Payload信息)
                .withClaim("timestamp",signDate)

                //设置token过期时间(token的Payload信息)
                .withClaim("exp",date)
                //自定义存放用户id在tokne中(token的自定义Payload信息)
                .withClaim("api_key", apiKeyId)
                //自定义存放用户名在token中(token的自定义Payload信息)
//                .withClaim("username", user.getName())
                //(token的Signature信息)
                .sign(algorithm);
        return token;
    }


    public static void main(String[] args) {
        String apiKey = "89934b295eb37f5d5750643ba2b18dae.nnR0vfmj3rgMOgD6";

        System.out.println(getGptToken(apiKey));
    }
}
