package com.njzscloud.common.security.support;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.util.IdUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.alibaba.fastjson2.annotation.JSONField;
import com.njzscloud.common.core.fastjson.serializer.DictObjectDeserializer;
import com.njzscloud.common.core.fastjson.serializer.DictObjectSerializer;
import com.njzscloud.common.security.config.WebSecurityProperties;
import com.njzscloud.common.security.contant.AuthWay;
import com.njzscloud.common.security.contant.Constants;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.Setter;


/**
 * Token
 */
@Getter
@Setter
@EqualsAndHashCode
@RequiredArgsConstructor
public final class Token {
    /**
     * 用户 Id
     */
    private final long userId;
    /**
     * 账号 Id
     */
    private final long accountId;
    /**
     * TOKEN Id
     */
    private final String tid;
    /**
     * 签发时间（时间戳）
     */
    private final long iat;
    /**
     * 过期时间（时间戳）
     */
    private final long exp;

    /**
     * 登录方式
     */
    @JSONField(serializeUsing = DictObjectSerializer.class, deserializeUsing = DictObjectDeserializer.class)
    private final AuthWay authWay;

    /**
     * 创建 TOKEN
     *
     * @param userId    用户 Id
     * @param accountId 账号 Id
     * @param authWay   登陆方式
     * @return Token 对象
     */
    public static Token create(long userId, long accountId, AuthWay authWay) {
        WebSecurityProperties webSecurityProperties = SpringUtil.getBean(WebSecurityProperties.class);
        long iat = System.currentTimeMillis();
        String tid = IdUtil.fastSimpleUUID();
        long tokenExp = webSecurityProperties.getTokenExp().getSeconds() * 1000;
        long exp = tokenExp > 0 ? iat + tokenExp : 0;
        return new Token(userId, accountId, tid, iat, exp, authWay);
    }

    /**
     * 创建 TOKEN
     *
     * @param token 字符串形式的 TOKEN
     * @return Token 对象
     */
    public static Token create(String token) {
        token = Base64.decodeStr(token);
        String[] tokenSection = token.split(Constants.TOKEN_STR_SEPARATOR);
        long userId = Long.parseLong(tokenSection[0]);
        long accountId = Long.parseLong(tokenSection[1]);
        String tid = tokenSection[2];
        long iat = Long.parseLong(tokenSection[3]);
        long exp = Long.parseLong(tokenSection[4]);
        AuthWay authWay = AuthWay.valueOf(tokenSection[5]);
        return new Token(userId, accountId, tid, iat, exp, authWay);
    }

    /**
     * 字符串输出
     * <p>由 6 段组成，每段逗号分隔，再取 Base64</p>
     * <p>userId,accountId,tid,iat,exp,authWay（枚举名称）</p>
     */
    @Override
    public String toString() {
        return Base64.encode(userId + Constants.TOKEN_STR_SEPARATOR +
                accountId + Constants.TOKEN_STR_SEPARATOR +
                tid + Constants.TOKEN_STR_SEPARATOR +
                iat + Constants.TOKEN_STR_SEPARATOR +
                exp + Constants.TOKEN_STR_SEPARATOR +
                authWay);
    }

    /**
     * 是否过期
     */
    public boolean isExpired() {
        return exp > 0 && exp < System.currentTimeMillis() - 10 * 1000;
    }
}
