package org.ta.gateway.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.oauth2.jwt.ReactiveJwtDecoder;
import org.springframework.security.oauth2.jwt.NimbusReactiveJwtDecoder;
import org.springframework.security.oauth2.core.DelegatingOAuth2TokenValidator;
import org.springframework.security.oauth2.core.OAuth2TokenValidator;
import org.springframework.security.oauth2.jwt.Jwt;
import org.springframework.security.oauth2.jwt.JwtIssuerValidator;
import org.springframework.security.oauth2.jwt.JwtTimestampValidator;

import java.time.Duration;

/**
 * 终极版：Spring Security 6.3.x + Gateway 4.3.0 官方标准实现
 * 1. 无任何不存在的方法（setClockSkew/setJwkSetUriTimeout/jwsAlgorithmValidator 均移除）
 * 2. 时钟偏差配置到 JwtTimestampValidator（官方推荐）
 * 3. 泛型完全匹配，无编译错误
 * 4. 自动适配 Auth-Server 的 JWKS 签名验证
 */
@Configuration
public class JwtConfig {

    @Bean
    public ReactiveJwtDecoder reactiveJwtDecoder() {
        // 1. 配置 Auth-Server 的 JWKS 端点（必须与 Auth-Server 一致）
        String jwkSetUri = "http://localhost:8080/oauth2/jwks";

        // 2. 构建标准的 NimbusReactiveJwtDecoder（仅调用官方公开方法）
        // 核心能力：自动从 JWKS 获取公钥，验证 JWT 签名 + 算法（RS256）
        NimbusReactiveJwtDecoder jwtDecoder = NimbusReactiveJwtDecoder.withJwkSetUri(jwkSetUri).build();

        // 3. 构建 JWT 验证器（官方标准配置）
        // 3.1 验证令牌签发者（iss 必须等于 Auth-Server 地址）
        OAuth2TokenValidator<Jwt> issuerValidator = new JwtIssuerValidator("http://localhost:8080");

        // 3.2 验证令牌过期/生效时间（核心修正：时钟偏差配置到验证器，而非解码器）
        // Duration.ofSeconds(60)：容忍 60 秒的服务器时间偏差（避免因时钟不同步导致令牌校验失败）
        OAuth2TokenValidator<Jwt> timestampValidator = new JwtTimestampValidator(Duration.ofSeconds(60));

        // 3.3 组合验证器（泛型显式指定 Jwt，解决类型匹配问题）
        OAuth2TokenValidator<Jwt> validator = new DelegatingOAuth2TokenValidator<>(
                issuerValidator,
                timestampValidator
        );

        // 4. 绑定验证器到解码器（唯一公开的核心方法）
        jwtDecoder.setJwtValidator(validator);

        return jwtDecoder;
    }
}