package cn.meowrain.aioj.backend.framework.security.utils;

import cn.meowrain.aioj.backend.framework.security.properties.JwtPropertiesConfiguration;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.security.Keys;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;

import javax.crypto.SecretKey;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@RequiredArgsConstructor
public class JwtUtil {

	private final JwtPropertiesConfiguration jwtConfig;

	private SecretKey getSigningKey() {
		return Keys.hmacShaKeyFor(jwtConfig.getSecret().getBytes());
	}

	/**
	 * 生成 Access Token
	 * @param userId 用户ID
	 * @param additionalClaims 额外的声明（如 userName, role 等）
	 */
	public String generateAccessToken(Long userId, Map<String, Object> additionalClaims) {
		long now = System.currentTimeMillis();

		Map<String, Object> claims = new HashMap<>();
		if (additionalClaims != null) {
			claims.putAll(additionalClaims);
		}

		return Jwts.builder()
			.subject(String.valueOf(userId))
			.issuedAt(new Date(now))
			.expiration(new Date(now + jwtConfig.getAccessExpire()))
			.claims(claims)
			.signWith(getSigningKey(), Jwts.SIG.HS256)
			.compact();
	}

	/** 生成 Refresh Token（只含 userId） */
	public String generateRefreshToken(Long userId) {
		long now = System.currentTimeMillis();

		return Jwts.builder()
			.subject(String.valueOf(userId))
			.issuedAt(new Date(now))
			.expiration(new Date(now + jwtConfig.getRefreshExpire()))
			.signWith(getSigningKey(), Jwts.SIG.HS256)
			.compact();
	}

	/** 解析 Token */
	public Claims parseClaims(String token) {
		return Jwts.parser().verifyWith(getSigningKey()).build().parseSignedClaims(token).getPayload();
	}

	/** 校验 Token 是否过期 */
	public boolean isTokenValid(String token) {
		try {
			Claims claims = parseClaims(token);
			return claims.getExpiration().after(new Date());
		}
		catch (Exception ignored) {
			return false;
		}
	}

	/**
	 * 从 Token 中获取用户ID
	 */
	public Long getUserIdFromToken(String token) {
		Claims claims = parseClaims(token);
		return Long.parseLong(claims.getSubject());
	}

}
