package org.ta.gateway.config;

import jakarta.annotation.Resource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
import org.springframework.security.config.web.server.ServerHttpSecurity;
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 org.springframework.security.web.server.SecurityWebFilterChain;
import reactor.core.publisher.Mono;

import java.nio.charset.StandardCharsets;
import java.time.Duration;

/**
 * 修正版：Reactive Security 配置（解决 DataBufferFactory 方法不存在问题）
 * 核心：
 * 1. 放行 Actuator 端点，避免 401
 * 2. 正确构建 DataBuffer（使用响应的 bufferFactory）
 * 3. 适配 Spring Framework 6.x 语法
 */
@Configuration
@EnableWebFluxSecurity
public class SecurityConfig {

    @Resource
    ReactiveJwtDecoder reactiveJwtDecoder;

    @Bean
    public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
        http
                // 禁用 CSRF（Gateway 是 API 网关，无需 CSRF 保护）
                .csrf(ServerHttpSecurity.CsrfSpec::disable)
                // 配置请求鉴权规则
                .authorizeExchange(exchanges -> exchanges
                        // 1. 放行 Actuator 所有端点（健康检查/路由监控）
                        .pathMatchers("/actuator/**").permitAll()
                        // 2. 放行 Auth-Server 授权相关路径（无需令牌）
                        .pathMatchers("/oauth2/**", "/login.html", "/login", "/oauth2/consent", "/callback").permitAll()
                        // 3. /api/** 路径必须携带有效 JWT 令牌
                        .pathMatchers("/api/**").authenticated()
                        // 4. 其他路径默认放行
                        .anyExchange().permitAll()
                )
                // 启用 OAuth2 资源服务器（JWT 鉴权）
                .oauth2ResourceServer(oauth2 -> oauth2
                        .jwt(jwt -> jwt
                                .jwtDecoder(reactiveJwtDecoder)
                        )
                )
                // 异常处理：401 时返回 JSON 响应（修正 DataBufferFactory 调用）
                .exceptionHandling(exceptions -> exceptions
                        .authenticationEntryPoint((exchange, ex) -> {
                            // 1. 设置响应状态码 401
                            exchange.getResponse().setStatusCode(org.springframework.http.HttpStatus.UNAUTHORIZED);
                            // 2. 设置响应头（JSON 格式）
                            exchange.getResponse().getHeaders().set(org.springframework.http.HttpHeaders.CONTENT_TYPE, "application/json;charset=UTF-8");
                            // 3. 构建错误响应内容
                            String errorJson = "{\"code\":401,\"message\":\"令牌无效或缺失\",\"timestamp\":\"" + System.currentTimeMillis() + "\"}";
                            // 4. 核心修正：通过响应的 bufferFactory 创建 DataBuffer（而非静态方法）
                            org.springframework.core.io.buffer.DataBuffer buffer =
                                    exchange.getResponse().bufferFactory().wrap(errorJson.getBytes(StandardCharsets.UTF_8));
                            // 5. 写入响应并返回
                            return exchange.getResponse().writeWith(Mono.just(buffer));
                        })
                );

        return http.build();
    }
}