package org.xyzh.common.auth.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.xyzh.common.auth.filter.JwtAuthenticationFilter;
import org.xyzh.common.auth.token.TokenParser;
import org.xyzh.common.redis.service.RedisService;

@Configuration
@EnableMethodSecurity
public class SecurityConfig {

    /**
     * 密码编码器 - 用于用户密码加密（使用 BCrypt）
     */
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    /**
     * JWT 认证过滤器 - 仅在非 Gateway 模式下启用
     * 当 auth.gateway-mode=false 或未配置时使用
     */
    @Bean
    @ConditionalOnProperty(name = "auth.gateway-mode", havingValue = "false", matchIfMissing = true)
    public JwtAuthenticationFilter jwtAuthenticationFilter(TokenParser tokenParser,
                                                           AuthProperties authProperties,
                                                           RedisService redisService) {
        return new JwtAuthenticationFilter(tokenParser, authProperties, redisService);
    }

    /**
     * Security 过滤器链配置
     * 根据是否启用 Gateway 模式决定是否添加 JWT 过滤器
     */
    @Bean
    public SecurityFilterChain securityFilterChain(
            HttpSecurity http,
            AuthProperties authProperties,
            @Autowired(required = false) JwtAuthenticationFilter jwtAuthenticationFilter,
            @Autowired(required = false) GatewayAuthConfig.GatewayTrustFilter gatewayTrustFilter) throws Exception {
        
        http
            .csrf(csrf -> csrf.disable())
            .formLogin(form -> form.disable())
            .httpBasic(basic -> basic.disable())
            .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
            .authorizeHttpRequests(authz -> {
                // 认证接口放行（login / logout / captcha / refresh）
                if (authProperties.getAuthPaths() != null) {
                    authProperties.getAuthPaths().forEach(path -> authz.requestMatchers(path).permitAll());
                }

                // 通用白名单放行（Swagger、静态资源等）
                if (authProperties.getWhitelist() != null) {
                    authProperties.getWhitelist().forEach(path -> authz.requestMatchers(path).permitAll());
                }

                authz
                    .requestMatchers("/error", "/favicon.ico").permitAll()
                    .anyRequest().authenticated();
            });

        // 根据模式添加对应的过滤器
        if (jwtAuthenticationFilter != null) {
            // 非 Gateway 模式：使用 JWT 过滤器
            http.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
        } else if (gatewayTrustFilter != null) {
            // Gateway 模式：使用信任过滤器
            http.addFilterBefore(gatewayTrustFilter, UsernamePasswordAuthenticationFilter.class);
        }

        return http.build();
    }
}


