package com.alterdekim.game.security;

import com.alterdekim.game.controller.FileServerController;
import com.alterdekim.game.entity.Role;
import com.alterdekim.game.storage.StorageProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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.WebSecurityCustomizer;
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.access.AccessDeniedHandler;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.firewall.StrictHttpFirewall;
import org.springframework.security.web.savedrequest.HttpSessionRequestCache;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

@Configuration
@EnableWebSecurity
public class SpringSecurity {

    @Autowired
    private UserDetailsService userDetailsService;

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        HttpSessionRequestCache requestCache = new HttpSessionRequestCache();
        requestCache.setMatchingRequestParameterName(null);
        http.csrf().disable()
                        .authorizeHttpRequests((authorize) ->
                                authorize
                                        .requestMatchers("/").permitAll()
                                        .requestMatchers("/login").permitAll()
                                        .requestMatchers("/panel").hasAuthority(Role.RoleType.RoleAdmin.name())
                                        .requestMatchers("/panel_user").hasAuthority(Role.RoleType.RoleAdmin.name())
                                        .requestMatchers("/panel_inventory").hasAuthority(Role.RoleType.RoleAdmin.name())
                                        .requestMatchers("/goods").hasAuthority(Role.RoleType.RoleAdmin.name())
                                        .requestMatchers("/api/**").hasAuthority(Role.RoleType.RoleAdmin.name())
                                        .requestMatchers("/main").hasAnyAuthority(Role.RoleType.RoleUser.name(), Role.RoleType.RoleAdmin.name())
                                        .requestMatchers("/"+ FileServerController.URL_PATH +"/**").permitAll()
                                        .requestMatchers("/ConstructorACHandler.ashx").permitAll()
                                        .requestMatchers("/async/**").hasAnyAuthority(Role.RoleType.RoleUser.name())
                                        .requestMatchers("/signup").permitAll()
                                        .requestMatchers("/cache/**").hasAnyAuthority(Role.RoleType.RoleUser.name(), Role.RoleType.RoleAdmin.name())
                                        .requestMatchers("/signup/**").permitAll()
                        )
                        .formLogin(
                                form -> form
                                        .loginPage("/login")
                                        .loginProcessingUrl("/login")
                                        .failureForwardUrl("/")
                                        .defaultSuccessUrl("/login")
                                        .permitAll()
                        )
                        .logout(
                                logout -> logout
                                        .logoutUrl("/logout")
                                        .logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
                                        .permitAll()
                        )
                        .requestCache((cache) -> cache
                                .requestCache(requestCache)
                        );
        return http.build();
    }

    /*@Bean
    public AccessDeniedHandler accessDeniedHandler() {
        return new CustomAccessDeniedHandler();
    }*/

    @Bean
    public AuthenticationFailureHandler authenticationFailureHandler() {
        return new CustomAuthenticationFailureHandler();
    }

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
    }


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

    @Bean
    public WebSecurityCustomizer webSecurityCustomizer() {
        StrictHttpFirewall firewall = new StrictHttpFirewall();
        firewall.setUnsafeAllowAnyHttpMethod(true);
        return (web) -> web.httpFirewall(firewall);
    }
}
