package com.chinaweal.aiccs.common.util;

import java.security.SecureRandom;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.Base64;
import java.util.UUID;

/**
 * OAuth令牌工具类
 *
 * @author lroyia
 * @since 2025/11/21
 */
public class OAuthTokenUtils {

    private static final SecureRandom SECURE_RANDOM = new SecureRandom();
    private static final int DEFAULT_ACCESS_TOKEN_VALIDITY_SECONDS = 3600; // 1小时
    private static final int DEFAULT_REFRESH_TOKEN_VALIDITY_SECONDS = 2592000; // 30天
    private static final int AUTHORIZATION_CODE_VALIDITY_SECONDS = 600; // 10分钟

    /**
     * 生成访问令牌
     */
    public static String generateAccessToken() {
        return generateRandomToken(32);
    }

    /**
     * 生成刷新令牌
     */
    public static String generateRefreshToken() {
        return generateRandomToken(48);
    }

    /**
     * 生成授权码
     */
    public static String generateAuthorizationCode() {
        return Base64.getUrlEncoder().withoutPadding()
                .encodeToString(UUID.randomUUID().toString().getBytes());
    }

    /**
     * 生成随机令牌
     */
    private static String generateRandomToken(int length) {
        byte[] bytes = new byte[length];
        SECURE_RANDOM.nextBytes(bytes);
        return Base64.getUrlEncoder().withoutPadding().encodeToString(bytes);
    }

    /**
     * 计算访问令牌过期时间
     */
    public static LocalDateTime calculateAccessTokenExpiry(Integer validitySeconds) {
        int seconds = validitySeconds != null ? validitySeconds : DEFAULT_ACCESS_TOKEN_VALIDITY_SECONDS;
        return LocalDateTime.now().plus(seconds, ChronoUnit.SECONDS);
    }

    /**
     * 计算刷新令牌过期时间
     */
    public static LocalDateTime calculateRefreshTokenExpiry(Integer validitySeconds) {
        int seconds = validitySeconds != null ? validitySeconds : DEFAULT_REFRESH_TOKEN_VALIDITY_SECONDS;
        return LocalDateTime.now().plus(seconds, ChronoUnit.SECONDS);
    }

    /**
     * 计算授权码过期时间
     */
    public static LocalDateTime calculateAuthorizationCodeExpiry() {
        return LocalDateTime.now().plus(AUTHORIZATION_CODE_VALIDITY_SECONDS, ChronoUnit.SECONDS);
    }

    /**
     * 检查令牌是否过期
     */
    public static boolean isTokenExpired(LocalDateTime expiryTime) {
        return expiryTime == null || LocalDateTime.now().isAfter(expiryTime);
    }

    /**
     * 验证客户端ID格式
     */
    public static boolean isValidClientId(String clientId) {
        return clientId != null && !clientId.trim().isEmpty() && clientId.matches("^[a-zA-Z0-9._-]+$");
    }

    /**
     * 验证重定向URI格式
     */
    public static boolean isValidRedirectUri(String redirectUri) {
        if (redirectUri == null || redirectUri.trim().isEmpty()) {
            return false;
        }
        try {
            new java.net.URL(redirectUri);
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 验证授权范围格式
     */
    public static boolean isValidScope(String scope) {
        if (scope == null || scope.trim().isEmpty()) {
            return false;
        }
        String[] scopes = scope.split("\\s+");
        for (String s : scopes) {
            if (!s.matches("^[a-zA-Z0-9._-]+$")) {
                return false;
            }
        }
        return true;
    }

    /**
     * 验证响应类型
     */
    public static boolean isValidResponseType(String responseType) {
        return "code".equals(responseType) || "token".equals(responseType);
    }

    /**
     * 验证授权类型
     */
    public static boolean isValidGrantType(String grantType) {
        return "authorization_code".equals(grantType) ||
               "refresh_token".equals(grantType) ||
               "client_credentials".equals(grantType) ||
               "password".equals(grantType);
    }
}