package com.zioinfo.mes.config;

import com.zioinfo.mes.auth.JwtFilter;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
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.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

/**
 * GUARDiA MES 보안 설정 — JWT 무상태 인증 + RBAC.
 *
 * <p>RBAC 역할(상위 → 하위): SUPERADMIN ⊃ MANAGER ⊃ WORKER ⊃ VIEWER.
 * <ul>
 *   <li>auth/health/swagger/정적 — permitAll</li>
 *   <li>조회(GET /api/mes/**) — 인증 사용자 전체(Viewer+)</li>
 *   <li>실적/검사/입출고/재고이동 입력(POST/PUT/PATCH/DELETE) — Worker 이상</li>
 *   <li>기준정보 마감·승인 — Manager 이상(서비스/메서드 가드 병행)</li>
 *   <li>관리자 API(/api/admin/**) — SuperAdmin 전용(감사로그 조회는 Manager+)</li>
 * </ul>
 */
@Configuration
@EnableWebSecurity
@EnableMethodSecurity
@RequiredArgsConstructor
public class SecurityConfig {

    private final JwtFilter jwtFilter;

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .csrf(csrf -> csrf.disable())
            .cors(cors -> {})
            .sessionManagement(sm -> sm.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
            .authorizeHttpRequests(auth -> auth
                // 로그인 + 로그인 보조 3종(signup/find-id/reset-password) + 2FA verify 모두 /api/mes/auth/** 하위 → permitAll
                .requestMatchers("/api/mes/auth/**").permitAll()
                .requestMatchers("/actuator/health").permitAll()
                .requestMatchers("/swagger-ui/**", "/v3/api-docs/**", "/api/mes/docs/**", "/api/mes/swagger/**").permitAll()
                // UIWS system 이식: 무인증 공개 조회(회사/부서 룩업) — 회원가입 화면 등에서 사용
                .requestMatchers(HttpMethod.GET, "/api/public/**").permitAll()
                // 정적 프론트 번들
                .requestMatchers("/", "/index.html", "/assets/**", "/favicon.ico").permitAll()

                // 관리자 — 사용자/설정 관리는 SUPERADMIN 전용
                .requestMatchers("/api/admin/users/**").hasRole("SUPERADMIN")
                .requestMatchers(HttpMethod.GET, "/api/admin/settings").hasAnyRole("SUPERADMIN", "MANAGER")
                .requestMatchers("/api/admin/settings/**").hasRole("SUPERADMIN")
                // 감사 로그 조회 — SUPERADMIN/MANAGER
                .requestMatchers("/api/admin/audit").hasAnyRole("SUPERADMIN", "MANAGER")
                .requestMatchers("/api/admin/**").hasRole("SUPERADMIN")

                // RAG 기법 토글 변경 — MANAGER 이상(운영자 전용). 분석 트리거(POST)는 아래 WORKER+ 규칙 적용.
                .requestMatchers(HttpMethod.PUT, "/api/mes/rag/toggles/**").hasAnyRole("SUPERADMIN", "MANAGER")

                // 변경(실적·검사·입출고·재고이동) — WORKER 이상 (기준정보/마감/승인은 서비스에서 MANAGER+ 가드)
                .requestMatchers(HttpMethod.POST,   "/api/mes/**").hasAnyRole("SUPERADMIN", "MANAGER", "WORKER")
                .requestMatchers(HttpMethod.PUT,    "/api/mes/**").hasAnyRole("SUPERADMIN", "MANAGER", "WORKER")
                .requestMatchers(HttpMethod.PATCH,  "/api/mes/**").hasAnyRole("SUPERADMIN", "MANAGER", "WORKER")
                .requestMatchers(HttpMethod.DELETE, "/api/mes/**").hasAnyRole("SUPERADMIN", "MANAGER", "WORKER")
                // 조회 — 인증 사용자 전체(Viewer+)
                .requestMatchers(HttpMethod.GET, "/api/mes/**").hasAnyRole("SUPERADMIN", "MANAGER", "WORKER", "VIEWER")

                // UIWS system(권한관리) 이식 — 사용자/역할/메뉴/부서/거래처/코드 관리는 SUPERADMIN 전용(RBAC 게이트)
                .requestMatchers("/api/system/**").hasRole("SUPERADMIN")

                .anyRequest().authenticated()
            )
            .addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class);
        return http.build();
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Bean
    public AuthenticationManager authenticationManager(AuthenticationConfiguration config) throws Exception {
        return config.getAuthenticationManager();
    }
}
