package kr.lunaticbum.back.lun.configs

import com.fasterxml.jackson.databind.ObjectMapper
import jakarta.servlet.http.HttpServletRequest
import jakarta.servlet.http.HttpServletResponse
import kr.lunaticbum.back.lun.utils.LogService
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.http.HttpMethod
import org.springframework.http.HttpStatus
import org.springframework.http.MediaType
import org.springframework.security.access.AccessDeniedException
import org.springframework.security.config.annotation.web.builders.HttpSecurity
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity
import org.springframework.security.config.http.SessionCreationPolicy
import org.springframework.security.core.AuthenticationException
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder
import org.springframework.security.web.AuthenticationEntryPoint
import org.springframework.security.web.SecurityFilterChain
import org.springframework.security.web.access.AccessDeniedHandler
import org.springframework.web.ErrorResponse


@Configuration
@EnableWebSecurity
class SecurityConfig {
    @Autowired
    lateinit var logService: LogService


    @Bean
    fun filterChain(http: HttpSecurity): SecurityFilterChain {

        http.csrf {
            it.ignoringRequestMatchers("/user/joinUser.ajax").disable()
        }
        http.cors { it.disable() }
        http.headers {
            it.frameOptions { frameOptionsConfig ->
                frameOptionsConfig.disable()
            }
        }

        http.authorizeHttpRequests {
            logService.log(it.toString())
            it.requestMatchers(HttpMethod.POST,"/user/**").permitAll()
//            it.requestMatchers(HttpMethod.POST,"/user/**").permitAll()
//                it.requestMatchers("/", "/user/**").permitAll()
//                .requestMatchers(".ajax").permitAll()
//                it.requestMatchers("/", "/user/joinUser.api").permitAll()
//                it.requestMatchers("user/joinUser.api").permitAll()
            it.anyRequest().permitAll()
//                    .requestMatchers("/", "/login/**").permitAll()
//                    .requestMatchers("/posts/**", "/api/v1/posts/**").hasRole(Role.USER.name)
//                    .requestMatchers("/admins/**", "/api/v1/admins/**").hasRole(Role.ADMIN.name)
//                    .anyRequest().authenticated()
        }
        http.sessionManagement {
            it.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
        }
            .exceptionHandling { it ->
                it.authenticationEntryPoint(unauthorizedEntryPoint)
                    .accessDeniedHandler(accessDeniedHandler)
            }
//            .formLogin { formLogin ->
//                formLogin
//                    .loginPage("/user/join")
//////                    .usernameParameter("username")
//////                    .passwordParameter("password")
//                    .loginProcessingUrl("/user/joinUser.api")
//                    .defaultSuccessUrl("/", true)
//            }

        return http.build()
    }

    private val unauthorizedEntryPoint =
        AuthenticationEntryPoint { request: HttpServletRequest?, response: HttpServletResponse, authException: AuthenticationException? ->
            val fail: ErrorResponse = ErrorResponse.create( Throwable("아직 못들어와"),
                HttpStatus.UNAUTHORIZED, "Spring security unauthorized..."
            )
            response.status = HttpStatus.UNAUTHORIZED.value()
            val json = ObjectMapper().writeValueAsString(fail)
            response.contentType = MediaType.APPLICATION_JSON_VALUE
            val writer = response.writer
            writer.write(json)
            writer.flush()
        }

    private val accessDeniedHandler =
        AccessDeniedHandler { request: HttpServletRequest?, response: HttpServletResponse, accessDeniedException: AccessDeniedException? ->
            val fail: ErrorResponse = ErrorResponse.create( Throwable("아직 못들어와"),
                HttpStatus.FORBIDDEN, "Spring security forbidden..."
            )
            response.status = HttpStatus.FORBIDDEN.value()
            val json = ObjectMapper().writeValueAsString(fail)
            response.contentType = MediaType.APPLICATION_JSON_VALUE
            val writer = response.writer
            writer.write(json)
            writer.flush()
        }

    @Bean
    fun bCryptPasswordEncoder(): BCryptPasswordEncoder {
        return BCryptPasswordEncoder()
    }
}