package com.its.web.security;

import com.its.web.interceptor.ConnectHistory;
import com.its.web.service.admin.LoginService;
import com.its.web.service.common.CommonService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.session.SessionRegistry;
import org.springframework.security.core.session.SessionRegistryImpl;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Slf4j
@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class WebSecurityConfig implements WebMvcConfigurer {

    private final LoginService loginService;
    private final WebLoginSuccessHandler webLoginSuccessHandler;
    private final WebLoginFailureHandler webLoginFailureHandler;
    private final CommonService commonService;

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http.headers().frameOptions().sameOrigin();
        http.csrf().disable();
        http.authorizeRequests()
//                .antMatchers("/swagger-ui.html", "/swagger/**", "/swagger-resources/**", "/webjars/**", "/v2/api-docs").permitAll()
//                .antMatchers("/", "/parking/**","/trafficMap/**", "/api/**", "/notice/**", "/center/**", "/statistics/**").permitAll()
//                .antMatchers("/images/**", "/css/**", "/js/**", "/font/**").permitAll()
            .antMatchers("/phits").permitAll()
            .antMatchers("/phits/**").hasRole("ADMIN");

        http.formLogin()
                .loginPage("/phits")
                .loginProcessingUrl("/phits/login")
                .failureUrl("/phits")
                .successHandler(this.webLoginSuccessHandler)
                .failureHandler(this.webLoginFailureHandler);
        http.logout()
            .logoutUrl("/phits/logout")
            .logoutSuccessUrl("/phits");

        return http.build();
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new ConnectHistory(commonService))
                .excludePathPatterns("/api/**", "/images/**", "/css/**", "/js/**", "/font/**"
                        , "/swagger-ui.html", "/swagger/**", "/swagger-resources/**", "/webjars/**", "/v2/api-docs");
    }

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

    @Bean
    public SessionRegistry sessionRegistry() {
        return new SessionRegistryImpl();
    }

    @Bean
    public DaoAuthenticationProvider daoAuthenticationProvider() {
        DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
        authenticationProvider.setUserDetailsService(this.loginService);
        authenticationProvider.setPasswordEncoder(passwordEncoder());
        // loadUserByUsername 의 UsernameNotFoundException 이 BadCredentialsException 로 발생함.
        // Exception 을 catch 하기 위해서는 아래를 false 로 설정하면 됨.
        authenticationProvider.setHideUserNotFoundExceptions(true);
        return authenticationProvider;
    }

//    @Bean
//    public AccessDeniedHandler accessDeniedHandler() {
//        return (request, response, accessDeniedException) -> {
//
//            CustomException customException = new ForbiddenException("forbidden",this.getClass().toString());
//            ErrorResponse errorResponse =
//                    new ErrorResponse(customException.getErrorType(), customException.getMessage(), customException.getPath());
//
//            Map<String, Object> responseBody = new HashMap<>();
//            responseBody.put("status", "FAILED");
//            responseBody.put("data", errorResponse);
//
//            response.setStatus(200);
//            response.setContentType("application/json;charset=UTF-8");
//            response.getWriter().write(new ObjectMapper().writeValueAsString(responseBody));
//        };
//    }

}
