package com.beautifulsoup.chengfeng.config;

import com.beautifulsoup.chengfeng.handler.UserLoginSuccessHandler;
import com.beautifulsoup.chengfeng.handler.TokenRefreshSuccessHandler;
import com.beautifulsoup.chengfeng.handler.TokenClearLogoutHandler;
import com.beautifulsoup.chengfeng.security.ChengfengAccessDeniedHandler;
import com.beautifulsoup.chengfeng.security.UserInfoService;
import com.beautifulsoup.chengfeng.security.configurer.UserLoginConfigurer;
import com.beautifulsoup.chengfeng.security.configurer.TokenLoginConfigurer;
import com.beautifulsoup.chengfeng.security.provider.TokenAuthenticationProvider;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
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.configuration.WebSecurityConfigurerAdapter;
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.authentication.logout.HttpStatusReturningLogoutSuccessHandler;
import org.springframework.security.web.header.Header;
import org.springframework.security.web.header.writers.StaticHeadersWriter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.CorsUtils;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

import java.util.Arrays;

@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/images/**").permitAll()//设置静态资源无权限限制
                .antMatchers("/swagger-ui.html").permitAll()
                .antMatchers("/swagger-resources/**").permitAll()
                .antMatchers("/webjars/**").permitAll()
                .antMatchers("/v2/api-docs").permitAll()
                .antMatchers("/configuration/ui").permitAll()
                .antMatchers("/configuration/security").permitAll()
                .antMatchers("/community/listall","/user/registry").permitAll()//指定可以直接访问的url
                .antMatchers("/file/upload","/file/uploads","/user/login").permitAll()//指定可以直接访问的url
                .requestMatchers(CorsUtils::isPreFlightRequest).permitAll()
                .requestMatchers(CorsUtils::isCorsRequest).permitAll()
                .anyRequest().authenticated()
                .and()
                .csrf().disable()
                .formLogin().disable()
                .sessionManagement().disable()
//                .headers().addHeaderWriter(new StaticHeadersWriter(Arrays.asList(
//                new Header("Access-control-Allow-Origin","*"),
//                new Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE"),
//                new Header("Access-Control-Max-Age", "3600"),
//                new Header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept"),
//                new Header("Access-Control-Expose-Headers","Authorization"))))
//                .and()
                //登录请求的过滤
                .apply(new UserLoginConfigurer<>()).loginSuccessHandler(userLoginSuccessHandler())
                .and()
                .exceptionHandling().accessDeniedHandler(accessDeniedHandler())
                .and()
                //token请求的过滤
                .apply(new TokenLoginConfigurer<>())
                .tokenValidSuccessHandler(tokenRefreshSuccessHandler())
                .permissiveRequestUrls("/logout","/community/listall","/images/**","/user/registry","/swagger-resources/**","/swagger-ui.html")
                .permissiveRequestUrls("/webjars/**","/v2/api-docs","/configuration/ui","/configuration/security","/file/upload","/file/uploads","/user/login")
                .and()
                //登出的过滤器
                .logout()
                .addLogoutHandler(tokenClearLogoutHandler())
                .logoutSuccessHandler(new HttpStatusReturningLogoutSuccessHandler())
                .and()
                .sessionManagement().disable()
                .cors().and().exceptionHandling().accessDeniedHandler(accessDeniedHandler());
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(daoAuthenticationProvider()).authenticationProvider(tokenAuthenticationProvider());
    }

    @Override
    protected UserDetailsService userDetailsService() {
        return new UserInfoService();
    }



    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Bean("daoAuthenticationProvider")
    protected AuthenticationProvider daoAuthenticationProvider() throws Exception{
        DaoAuthenticationProvider daoProvider = new DaoAuthenticationProvider();
        daoProvider.setPasswordEncoder(passwordEncoder());
        daoProvider.setUserDetailsService(userInfoService());
        return daoProvider;
    }
    @Bean("tokenAuthenticationProvider")
    protected AuthenticationProvider tokenAuthenticationProvider() {
        return new TokenAuthenticationProvider(userInfoService());
    }

    @Bean("userInfoService")
    protected UserInfoService userInfoService() {
        return new UserInfoService();
    }

    @Bean("passwordEncoder")
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }

    @Bean
    protected UserLoginSuccessHandler userLoginSuccessHandler() {
        return new UserLoginSuccessHandler(userInfoService());
    }

    @Bean
    protected TokenRefreshSuccessHandler tokenRefreshSuccessHandler() {
        return new TokenRefreshSuccessHandler();
    }

    @Bean
    protected TokenClearLogoutHandler tokenClearLogoutHandler() {
        return new TokenClearLogoutHandler(userInfoService());
    }

    @Bean
    protected ChengfengAccessDeniedHandler accessDeniedHandler(){
        return new ChengfengAccessDeniedHandler();
    }


//    @Bean
//    public WebMvcConfigurer corsConfigurer() {
//        return new WebMvcConfigurerAdapter() {
//            @Override
//            public void addCorsMappings(CorsRegistry registry) {
//                registry.addMapping("/**").allowedOrigins("*").allowedHeaders("*").allowedMethods("*");
//            }
//        };
//    }
//
//    @Bean
//    public FilterRegistrationBean corsFilter(){
//        FilterRegistrationBean bean=new FilterRegistrationBean(new CorsFilter(corsConfigurationSource()));
//        bean.setOrder(0);
//        return bean;
//    }
//
//
//    @Bean
//    protected CorsConfigurationSource corsConfigurationSource() {
//        CorsConfiguration configuration = new CorsConfiguration();
//        configuration.addAllowedOrigin("*");
//        configuration.addAllowedMethod("*");
//        configuration.addAllowedHeader("*");
//        configuration.addExposedHeader("Authorization");
//        configuration.setAllowCredentials(true);
//        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
//        source.registerCorsConfiguration("/**", configuration);
//        return source;
//    }

}

//.cors()
//.and()
//.headers().addHeaderWriter(new StaticHeadersWriter(Arrays.asList(
//new Header("Access-Control-Allow-Origin","*"),
//new Header("Access-Control-Expose-Headers","Authorization"))))//设置支持跨域请求
//.and()
//.addFilterAfter(new OptionsRequestFilter(), CorsFilter.class)