package com.test.bijihoudaun.config;

import com.test.bijihoudaun.config.security.JwtAccessDeniedHandler;
import com.test.bijihoudaun.config.security.JwtAuthenticationEntryPoint;
import com.test.bijihoudaun.interceptor.JwtAuthenticationTokenFilter;
import com.test.bijihoudaun.util.JwtTokenUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
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 java.util.Arrays;

@Configuration
@EnableWebSecurity
@EnableMethodSecurity(prePostEnabled = true)
public class SecurityConfig {

    @Autowired
    private UserDetailsService userDetailsService;

    @Autowired
    private JwtTokenUtil jwtTokenUtil;

    @Autowired
    private JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;

    @Autowired
    private JwtAccessDeniedHandler jwtAccessDeniedHandler;

    @Autowired
    private Environment environment;

    @Value("${jwt.header}")
    private String tokenHeader;

    @Value("${jwt.tokenHead}")
    private String tokenHead;


    // 配置了密码编码器
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    // 配置了安全过滤器链
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter = new JwtAuthenticationTokenFilter(userDetailsService, jwtTokenUtil, tokenHeader, tokenHead);

        // 检查当前激活的profile中是否包含 "prod"
        boolean isProd = Arrays.asList(environment.getActiveProfiles()).contains("prod");

        // 根据环境动态设置白名单
        String[] publicEndpoints = isProd ?
                new String[]{"/api/user/login", "/api/user/register"} :
                new String[]{
                        "/doc.html",
                        "/webjars/**",
                        "/v3/api-docs/**",
                        "/api/user/login",
                        "/api/user/register"
                };

        http
                .cors(cors -> cors.configurationSource(request -> {
                    org.springframework.web.cors.CorsConfiguration config = new org.springframework.web.cors.CorsConfiguration();
                    config.addAllowedOriginPattern("*");
                    config.addAllowedMethod("*");
                    config.addAllowedHeader("*");
                    config.setAllowCredentials(false); // 与CORS配置保持一致
                    return config;
                }))
                .csrf(csrf -> csrf.disable())   // 配置了 CSRF 禁用、无状态会话管理
                .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
                .authorizeHttpRequests(authz -> authz
                        // 1. 动态允许公共端点
                        .requestMatchers(publicEndpoints).permitAll()

                        // 2. 精确允许用于“公开阅读”的 GET 请求
                        .requestMatchers(org.springframework.http.HttpMethod.GET,
                                "/api/groupings/**",          // 获取分组
                                "/api/images/preview/**",      // 预览图片
                                "/api/markdown/**",            // 所有Markdown相关的GET请求
                                "/api/system/registration/status" // 检查注册是否开启
                        ).permitAll()

                        // 3. 除上述白名单外，所有其他请求都需要认证
                        .anyRequest().authenticated()
                )
                // 添加自定义的异常处理器
                .exceptionHandling(exceptions -> exceptions
                        .authenticationEntryPoint(jwtAuthenticationEntryPoint)
                        .accessDeniedHandler(jwtAccessDeniedHandler)
                );

        // 在这里添加JWT过滤器
        http.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);

        return http.build();
    }
}
