package com.ecep.contract.config;

import java.util.List;
import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
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.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;

import com.ecep.contract.ds.other.service.EmployeeService;
import com.ecep.contract.model.Employee;
import com.ecep.contract.model.EmployeeRole;

/**
 * Spring Security配置类
 * 用于配置安全认证和授权规则
 */
@Configuration
@EnableWebSecurity
@EnableMethodSecurity(prePostEnabled = true) // 开启 @PreAuthorize 等注解
public class SecurityConfig {

    @Lazy
    @Autowired
    private EmployeeService employeeService;

    /**
     * 配置HTTP安全策略
     * 启用表单登录和HTTP Basic认证
     */
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http, AuthenticationManager authenticationManager)
            throws Exception {
        http
                .authorizeHttpRequests(authorize -> authorize
                        .requestMatchers("/login.html", "/css/**", "/js/**", "/images/**", "/webjars/**", "/login",
                                "/error", "/api/login", "/ws/**")
                        .permitAll() // 允许静态资源、登录页面、错误页面和JSON登录API访问，以及WebSocket连接
                        .anyRequest().authenticated() // 其他所有请求需要认证
                )
                .csrf(AbstractHttpConfigurer::disable) // 禁用CSRF保护，适合开发环境
                .formLogin(form -> form
                        .loginPage("/login.html") // 直接使用静态登录页面
                        .loginProcessingUrl("/login") // 登录处理URL
                        .permitAll() // 允许所有人访问登录页面
                        .defaultSuccessUrl("/", true) // 登录成功后重定向到首页
                        .failureUrl("/login.html?error=true") // 登录失败后重定向到登录页面并显示错误
                        .usernameParameter("username") // 用户名参数名
                        .passwordParameter("password") // 密码参数名
                )
                .httpBasic(Customizer.withDefaults()) // 启用HTTP Basic认证
                .logout(logout -> logout
                        .logoutUrl("/logout") // 注销URL
                        .logoutSuccessUrl("/login?logout=true") // 注销成功后重定向到登录页面
                        .invalidateHttpSession(true) // 使会话失效
                        .deleteCookies("JSESSIONID") // 删除会话cookie
                        .permitAll() // 允许所有人访问注销URL
                )
                .sessionManagement(session -> session
                        .sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED) // 根据需要创建会话
                        .maximumSessions(1) // 每个用户最多1个会话
                        .expiredUrl("/login?expired=true") // 会话过期后重定向到登录页面
                )
                .authenticationManager(authenticationManager); // 设置认证管理器

        return http.build();
    }

    /**
     * 配置AuthenticationManager
     * 用于处理认证请求
     */
    @Bean
    public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration)
            throws Exception {
        return authenticationConfiguration.getAuthenticationManager();
    }

    /**
     * 配置密码编码器
     * BCryptPasswordEncoder是Spring Security推荐的密码编码器
     */
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    /**
     * 配置基于EmployeeService的用户认证
     * 通过EmployeeService获取员工信息并转换为Spring Security的UserDetails
     */
    @Bean
    public UserDetailsService userDetailsService() {
        return username -> {
            // 使用EmployeeService根据用户名查找员工
            Employee employee = employeeService.findByAccount(username);

            // 如果找不到员工，抛出UsernameNotFoundException异常
            if (employee == null) {
                throw new UsernameNotFoundException("用户不存在: " + username);
            }

            // 检查员工是否活跃
            if (!employee.isActive()) {
                throw new UsernameNotFoundException("用户已禁用: " + username);
            }

            // 将员工角色转换为Spring Security的GrantedAuthority
            List<GrantedAuthority> authorities = getAuthoritiesFromRoles(
                    employeeService.getRolesByEmployeeId(employee.getId()));

            // 创建并返回UserDetails对象
            // 注意：根据系统设计，Employee实体中没有密码字段，系统使用IP/MAC绑定认证
            // 这里使用密码编码器加密后的固定密码，确保认证流程能够正常工作
            return User.builder()
                    .username(employee.getName())
                    .password(passwordEncoder().encode("default123")) // 使用默认密码进行加密
                    .accountExpired(false) // 账户未过期
                    .accountLocked(false) // 账户未锁定
                    .credentialsExpired(false) // 凭证未过期
                    .disabled(!employee.isActive()) // 根据员工状态设置是否禁用
                    .authorities(authorities)
                    .build();
        };
    }

    /**
     * 将EmployeeRole列表转换为Spring Security的GrantedAuthority列表
     */
    private List<GrantedAuthority> getAuthoritiesFromRoles(List<EmployeeRole> roles) {
        if (roles == null || roles.isEmpty()) {
            return List.of();
        }

        // 为每个角色创建GrantedAuthority
        // 系统管理员拥有ADMIN角色，其他用户拥有USER角色
        return roles.stream()
                .filter(EmployeeRole::isActive) // 只包含活跃的角色
                .map(role -> {
                    if (role.isSystemAdministrator()) {
                        return new SimpleGrantedAuthority("ROLE_ADMIN");
                    } else {
                        return new SimpleGrantedAuthority("ROLE_USER");
                    }
                })
                .collect(Collectors.toList());
    }

    // Spring Security会自动配置一个使用我们定义的UserDetailsService的DaoAuthenticationProvider
    // 移除显式的authenticationProvider Bean定义以避免警告
    // 当同时存在AuthenticationProvider和UserDetailsService Bean时，Spring
    // Security会优先使用AuthenticationProvider
    // 而忽略直接的UserDetailsService，虽然这不影响功能，但会产生警告
}