package com.ai.da.common.security.config;

import com.ai.da.common.security.*;
import com.ai.da.common.security.filter.AuthenticationFilter;
import com.ai.da.common.security.filter.UserAuthenticationProcessingFilter;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.Customizer;
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.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

import jakarta.annotation.Resource;

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

    @Resource
    private SecurityProperties securityProperties;
    @Resource
    private UserLoginSuccessHandler userLoginSuccessHandler;
    @Resource
    private UserLoginFailureHandler userLoginFailureHandler;
    @Resource
    private UserAuthAccessDeniedHandler userAuthAccessDeniedHandler;
    @Resource
    private UserAuthenticationEntryPointHandler userAuthenticationEntryPointHandler;
    @Resource
    private UserAuthenticationManager userAuthenticationManager;
    @Resource
    private UserAuthenticationProcessingFilter userAuthenticationProcessingFilter;

    /**
     * 不通过注入spring管理 让Security来管理 这样自定义的Filter就不会走,.permitAll()才能起作用
     */
    @Resource
    private AuthenticationFilter authenticationFilter;
    @Resource
    private UserPermissionEvaluator userPermissionEvaluator;

    @Bean
    public AuthenticationManager authenticationManager() throws Exception {
        return this.userAuthenticationManager;
    }

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception {
        httpSecurity
                .cors(Customizer.withDefaults())
                .authorizeHttpRequests(auth -> auth
                        .requestMatchers(
                                new AntPathRequestMatcher("/doc.html"),
                                new AntPathRequestMatcher("/swagger-ui.html"),
                                new AntPathRequestMatcher("/swagger-ui/**"),
                                new AntPathRequestMatcher("/swagger-resources/**"),
                                new AntPathRequestMatcher("/v2/api-docs"),
                                new AntPathRequestMatcher("/v3/api-docs/**"),
                                new AntPathRequestMatcher("/webjars/**")
                        ).permitAll()
                        .requestMatchers(securityProperties.getIgnorePaths()).permitAll()
                        .anyRequest().authenticated()
                )
                .headers(headers -> headers
                        .frameOptions(HeadersConfigurer.FrameOptionsConfig::disable)
                        .cacheControl(cache -> cache.disable())
                )
                .exceptionHandling(exception -> exception
                        .authenticationEntryPoint(userAuthenticationEntryPointHandler)
                        .accessDeniedHandler(userAuthAccessDeniedHandler)
                )
                .formLogin(form -> form
                        .loginProcessingUrl(securityProperties.getAuthApi())
                        .successHandler(userLoginSuccessHandler)
                        .failureHandler(userLoginFailureHandler)
                )
                .csrf(AbstractHttpConfigurer::disable)
                .sessionManagement(session -> session
                        .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                );
        
        //自定义过滤器在登录时认证用户名、密码
        httpSecurity.addFilterAt(userAuthenticationProcessingFilter, UsernamePasswordAuthenticationFilter.class)
                .addFilterBefore(authenticationFilter, BasicAuthenticationFilter.class);
        
        return httpSecurity.build();
    }

    @Bean
    public DefaultWebSecurityExpressionHandler userSecurityExpressionHandler() {
        DefaultWebSecurityExpressionHandler handler = new DefaultWebSecurityExpressionHandler();
        handler.setPermissionEvaluator(userPermissionEvaluator);
        return handler;
    }
}
