package com.bb.config;

import java.util.Arrays;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler;
import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler;
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.configuration.WebSecurityCustomizer;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.context.SecurityContextRepository;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Configuration
@EnableWebSecurity
@EnableMethodSecurity(securedEnabled = true, prePostEnabled = true, proxyTargetClass = true) // EnableGlobalMethodSecurity 대체
@ComponentScan(basePackages = {"com.bb.*"})
public class SecurityConfig {

    @Autowired
    AuthProvider authProvider;
    
    @Autowired
    AuthFailureHandler authFailureHandler;
    
    @Autowired
    AuthSuccessHandler authSuccessHandler;
    
    @Autowired
    CustomWebAuthenticationDetailsSource authenticationDetailsSource;

    static final String SERVER_HOST_1 = "139-162-90-184.ip.linodeusercontent.com";
    static final String SERVER_HOST_2 = "139-162-90-179.ip.linodeusercontent.com";
    
    @Bean
    public MethodSecurityExpressionHandler methodSecurityExpressionHandler() {
        DefaultMethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler();
        // ROLE_ 접두사 규칙을 강제합니다.
        expressionHandler.setDefaultRolePrefix("ROLE_");
        return expressionHandler;
    }
    /**
     * 기존 web.ignoring() 설정 부분
     */
    @Bean
    public WebSecurityCustomizer webSecurityCustomizer() {
        return (web) -> web.ignoring().requestMatchers(
            "/v3/api-docs", "/swagger-resources/**", "/webjars/**", "/swagger/**", "/favicon.ico",
            "/html/**", "/resources/**", "/websocket", "/websocket/**", "/images/**", 
            "/img/**", "/css/**", "/js/**"
        );
    }

    /**
     * 관리자 및 메인 보안 설정 (SecurityFilterChain)
     */
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http, SecurityContextRepository securityContextRepository) throws Exception {
        
        http
            .cors(cors -> cors.configurationSource(corsConfigurationSource()))
            .csrf(csrf -> csrf.disable())
            .headers(headers -> headers.frameOptions(frame -> frame.disable()))
            .securityContext(context -> context
                .securityContextRepository(securityContextRepository)
            )
            .authenticationProvider(authProvider);

        http.authorizeHttpRequests(auth -> auth
            .requestMatchers("/", "/login/**", "/lg/**", "/api/**", "/actuator/**", "/lunch/**", "/websocket", "/websocket/**", "/guest/guestLogin").permitAll()
            .anyRequest().authenticated()
        );

        http.formLogin(form -> form
            .loginPage("/lg")
            .loginProcessingUrl("/authenticate")
            .failureHandler(authFailureHandler)
            .successHandler(authSuccessHandler)
            .usernameParameter("id")
            .passwordParameter("pw")
            .authenticationDetailsSource(authenticationDetailsSource)
        );

        return http.build();
    }

    @Bean
    public FilterRegistrationBean<ApiKeyFilter> filterRegistrationBean() {
        FilterRegistrationBean<ApiKeyFilter> registrationBean = new FilterRegistrationBean<>();
        ApiKeyFilter customURLFilter = new ApiKeyFilter();
    
        registrationBean.setFilter(customURLFilter);
        registrationBean.addUrlPatterns("/api/login");
        registrationBean.setOrder(1); 
    
        return registrationBean;
    }

    @Bean
    public CorsConfigurationSource corsConfigurationSource() {
        final CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOriginPatterns(Arrays.asList("*"));
        configuration.addAllowedHeader("*");
        configuration.addAllowedMethod("*");
        configuration.setAllowCredentials(false);
        
        final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }
}
