package com.mvrent.carrental.config;

import com.mvrent.carrental.service.CustomUserDetailsService;
import com.mvrent.carrental.service.OAuth2LoginService;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;

@Configuration
@EnableWebSecurity
@EnableMethodSecurity
@RequiredArgsConstructor
public class SecurityConfig {

    private final CustomUserDetailsService userDetailsService;
    private final OAuth2LoginService oAuth2LoginService;
    private final PasswordEncoder passwordEncoder;

    @Bean
    public DaoAuthenticationProvider authenticationProvider() {
        DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
        provider.setUserDetailsService(userDetailsService);
        provider.setPasswordEncoder(passwordEncoder);
        return provider;
    }

    /**
     * Telematics ingest chain — applies only to /api/telematics/**.
     * Stateless and CSRF-exempt; authenticated by an API key in the controller,
     * so GPS devices can POST pings directly without a session.
     */
    @Bean
    @Order(0)
    public SecurityFilterChain telematicsSecurityFilterChain(HttpSecurity http) throws Exception {
        http
                .securityMatcher("/api/telematics/**")
                .csrf(csrf -> csrf.disable())
                .sessionManagement(sm -> sm.sessionCreationPolicy(
                        org.springframework.security.config.http.SessionCreationPolicy.STATELESS))
                .authorizeHttpRequests(auth -> auth.anyRequest().permitAll());
        return http.build();
    }

    /**
     * Admin module chain — applies only to /admin/**.
     * Has its own login page (/admin/login) and logout (/admin/logout),
     * completely separate from the customer/citizen login flow below.
     */
    @Bean
    @Order(1)
    public SecurityFilterChain adminSecurityFilterChain(HttpSecurity http) throws Exception {
        http
                .securityMatcher("/admin/**")
                .authenticationProvider(authenticationProvider())
                .authorizeHttpRequests(auth -> auth
                        .requestMatchers("/admin/login").permitAll()
                        .anyRequest().hasAnyRole("ADMIN", "STAFF")
                )
                .formLogin(form -> form
                        .loginPage("/admin/login")
                        .loginProcessingUrl("/admin/login")
                        .defaultSuccessUrl("/admin", true)
                        .failureUrl("/admin/login?error")
                        .permitAll()
                )
                .logout(logout -> logout
                        .logoutUrl("/admin/logout")
                        .logoutSuccessUrl("/admin/login?logout")
                        .permitAll()
                );

        return http.build();
    }

    /**
     * Vendor portal chain — applies only to /vendor/**.
     * Own login (/vendor/login) and logout (/vendor/logout); ROLE_VENDOR only.
     */
    @Bean
    @Order(2)
    public SecurityFilterChain vendorSecurityFilterChain(HttpSecurity http) throws Exception {
        http
                .securityMatcher("/vendor/**")
                .authenticationProvider(authenticationProvider())
                .authorizeHttpRequests(auth -> auth
                        .requestMatchers("/vendor/login").permitAll()
                        .anyRequest().hasRole("VENDOR")
                )
                .formLogin(form -> form
                        .loginPage("/vendor/login")
                        .loginProcessingUrl("/vendor/login")
                        .defaultSuccessUrl("/vendor", true)
                        .failureUrl("/vendor/login?error")
                        .permitAll()
                )
                .logout(logout -> logout
                        .logoutUrl("/vendor/logout")
                        .logoutSuccessUrl("/vendor/login?logout")
                        .permitAll()
                );

        return http.build();
    }

    /**
     * Driver portal chain — applies only to /driver/**.
     * Own login (/driver/login) and logout (/driver/logout); ROLE_DRIVER only.
     */
    @Bean
    @Order(3)
    public SecurityFilterChain driverSecurityFilterChain(HttpSecurity http) throws Exception {
        http
                .securityMatcher("/driver/**")
                .authenticationProvider(authenticationProvider())
                .authorizeHttpRequests(auth -> auth
                        .requestMatchers("/driver/login").permitAll()
                        .anyRequest().hasRole("DRIVER")
                )
                .formLogin(form -> form
                        .loginPage("/driver/login")
                        .loginProcessingUrl("/driver/login")
                        .defaultSuccessUrl("/driver", true)
                        .failureUrl("/driver/login?error")
                        .permitAll()
                )
                .logout(logout -> logout
                        .logoutUrl("/driver/logout")
                        .logoutSuccessUrl("/driver/login?logout")
                        .permitAll()
                );

        return http.build();
    }

    /**
     * Customer / citizen chain — handles everything outside /admin/**, /vendor/** and /driver/**.
     * Public browsing + the standard /login and /register flow.
     */
    @Bean
    @Order(4)
    public SecurityFilterChain customerSecurityFilterChain(HttpSecurity http) throws Exception {
        http
                .authenticationProvider(authenticationProvider())
                .authorizeHttpRequests(auth -> auth
                        .requestMatchers("/", "/cars", "/cars/**", "/login", "/register",
                                "/oauth2/**", "/login/oauth2/**",
                                "/css/**", "/js/**", "/images/**", "/uploads/**", "/webjars/**", "/error")
                        .permitAll()
                        .anyRequest().authenticated()
                )
                .formLogin(form -> form
                        .loginPage("/login")
                        .defaultSuccessUrl("/", true)
                        .failureUrl("/login?error")
                        .permitAll()
                )
                .oauth2Login(oauth -> oauth
                        .loginPage("/login")
                        .defaultSuccessUrl("/", true)
                        .failureUrl("/login?error")
                        .userInfoEndpoint(info -> info.userService(oAuth2LoginService))
                )
                .logout(logout -> logout
                        .logoutUrl("/logout")
                        .logoutSuccessUrl("/?logout")
                        .permitAll()
                );

        return http.build();
    }
}
