package com.bio.bio_backend.global.security;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.security.authentication.AuthenticationManager;
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.configurers.AbstractHttpConfigurer;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.filter.CorsFilter;

import com.fasterxml.jackson.databind.ObjectMapper;

import jakarta.servlet.Filter;
//import com.bio.bio_backend.domain.common.service.AccessLogService;
import com.bio.bio_backend.domain.user.member.service.MemberService;
import com.bio.bio_backend.global.exception.CustomAuthenticationFailureHandler;
import com.bio.bio_backend.global.exception.JwtAccessDeniedHandler;
import com.bio.bio_backend.global.exception.JwtAuthenticationEntryPoint;
//import com.bio.bio_backend.global.filter.HttpLoggingFilter;
import com.bio.bio_backend.global.utils.HttpUtils;
import com.bio.bio_backend.global.utils.JwtUtils;
import lombok.RequiredArgsConstructor;

@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class WebSecurity {

    private final MemberService memberService;
    private final BCryptPasswordEncoder bCryptPasswordEncoder;
    private final JwtUtils jwtUtils;
//    private final AccessLogService accessLogService;
    private final CorsFilter corsFilter;
    private final ObjectMapper objectMapper;
    private final HttpUtils httpUtils;
    private final Environment env;
    private final JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;
    private final JwtAccessDeniedHandler jwtAccessDeniedHandler;
    
    private final UriAllowFilter uriAllowFilter;
    

    private JwtAuthenticationFilter getJwtAuthenticationFilter(AuthenticationManager authenticationManager) throws Exception {
        JwtAuthenticationFilter filter = new JwtAuthenticationFilter(authenticationManager, memberService, jwtUtils, env);
        filter.setFilterProcessesUrl("/login"); // 로그인 EndPoint
        filter.setAuthenticationFailureHandler(new CustomAuthenticationFailureHandler(objectMapper));
        return filter;
    }

    private Filter getJwtTokenFilter() {
        return new JwtTokenFilter(jwtUtils, memberService, env, uriAllowFilter);
    }
    
    @Bean
    SecurityFilterChain filterChain(HttpSecurity http) throws Exception {

        // AuthenticationManager 설정
        AuthenticationManagerBuilder authenticationManagerBuilder =
                http.getSharedObject(AuthenticationManagerBuilder.class);
        authenticationManagerBuilder.userDetailsService(memberService).passwordEncoder(bCryptPasswordEncoder);

        AuthenticationManager authenticationManager = authenticationManagerBuilder.build();

        http.csrf(AbstractHttpConfigurer::disable)          //csrf 비활성화
                .authorizeHttpRequests(request ->               //request 허용 설정
                        request
                        	.anyRequest().permitAll()  // 모든 요청 허용
//                    		.requestMatchers("/ws/**").permitAll()
//                            .requestMatchers("/admin/**", "/join").hasAnyAuthority(MemberConstants.ROLE_ADMIN)
//                            .requestMatchers("/member/**").hasAnyAuthority(MemberConstants.ROLE_MEMBER)
//                            .anyRequest().authenticated()
                )
                .authenticationManager(authenticationManager)
                .logout(AbstractHttpConfigurer::disable);

        // 예외 처리 핸들링
        http.exceptionHandling((exceptionConfig) ->
                exceptionConfig
                        .authenticationEntryPoint(jwtAuthenticationEntryPoint)
                        .accessDeniedHandler(jwtAccessDeniedHandler)
        );

//        http
//        		.addFilterBefore(corsFilter, UsernamePasswordAuthenticationFilter.class)
//                .addFilterBefore(new HttpLoggingFilter(accessLogService, httpUtils), UsernamePasswordAuthenticationFilter.class)
//                .addFilterBefore(getJwtAuthenticationFilter(authenticationManager), UsernamePasswordAuthenticationFilter.class)
//                .addFilterBefore(getJwtTokenFilter(), UsernamePasswordAuthenticationFilter.class);


//                .sessionManagement(httpSecuritySessionManagementConfigurer ->       //Session 사용 X
//                        httpSecuritySessionManagementConfigurer.sessionCreationPolicy(SessionCreationPolicy.STATELESS));


        return http.build();
    }
}
