package com.zioinfo.cms.config;

import com.zioinfo.cms.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 CMS 보안 설정 — JWT 무상태 인증 + RBAC.
 *
 * <p>RBAC 역할(상위 → 하위): SUPERADMIN ⊃ EDITOR ⊃ AUTHOR ⊃ VIEWER.
 * <ul>
 *   <li>공개 delivery API(/api/cms/delivery/**) — published 콘텐츠만, 인증 불필요(프리뷰는 토큰 검증)</li>
 *   <li>auth/health/swagger — permitAll</li>
 *   <li>조회(GET /api/cms/**) — 인증 사용자 전체(Viewer+)</li>
 *   <li>콘텐츠 작성/수정(POST/PUT/DELETE) — Author 이상</li>
 *   <li>게시 승인/발행(workflow approve/publish) — Editor 이상 (서비스/메서드 가드 병행)</li>
 *   <li>관리자 API(/api/admin/**) — SuperAdmin 전용(감사로그 조회는 Editor+)</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
                .requestMatchers("/api/cms/auth/**").permitAll()
                // 로그인 보조 이식(회원가입/아이디찾기/비번초기화) — 로그인 전 무인증.
                // 회원가입은 승인대기로 INSERT, 비번초기화는 임시비번을 메일/로그로만 전달(응답 무노출).
                .requestMatchers("/api/auth/signup", "/api/auth/find-id", "/api/auth/reset-password").permitAll()
                .requestMatchers("/actuator/health").permitAll()
                .requestMatchers("/swagger-ui/**", "/v3/api-docs/**", "/api/cms/docs/**", "/api/cms/swagger/**").permitAll()

                // 공개 헤드리스 delivery API — GET(published 콘텐츠 조회·토큰 프리뷰)만 무인증.
                // POST(프리뷰 토큰 발급)는 아래 POST /api/cms/** 규칙으로 폴백 → Author+ 강제(H-1 우회 차단)
                .requestMatchers(HttpMethod.GET, "/api/cms/delivery/**").permitAll()
                // 정적 프론트 번들
                .requestMatchers("/", "/index.html", "/assets/**", "/favicon.ico").permitAll()

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

                // UIWS PublicLookup(가입화면 부서/회사 셀렉트박스용 공개 조회) — 로그인 전 GET 무인증.
                // 조회 전용(부서명/회사명만) — 민감정보·자격증명 미포함.
                .requestMatchers(HttpMethod.GET, "/api/public/**").permitAll()
                // UIWS system(시스템관리·권한관리) 이식 — SUPERADMIN 전용.
                .requestMatchers("/api/system/**").hasRole("SUPERADMIN")

                // 콘텐츠/리소스 작성·수정·삭제 — AUTHOR 이상 (게시 승인/발행은 서비스 메서드에서 EDITOR+ 추가 가드)
                .requestMatchers(HttpMethod.POST,   "/api/cms/**").hasAnyRole("SUPERADMIN", "EDITOR", "AUTHOR")
                .requestMatchers(HttpMethod.PUT,    "/api/cms/**").hasAnyRole("SUPERADMIN", "EDITOR", "AUTHOR")
                .requestMatchers(HttpMethod.PATCH,  "/api/cms/**").hasAnyRole("SUPERADMIN", "EDITOR", "AUTHOR")
                .requestMatchers(HttpMethod.DELETE, "/api/cms/**").hasAnyRole("SUPERADMIN", "EDITOR", "AUTHOR")
                // 조회 — 인증 사용자 전체(Viewer+)
                .requestMatchers(HttpMethod.GET, "/api/cms/**").hasAnyRole("SUPERADMIN", "EDITOR", "AUTHOR", "VIEWER")

                .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();
    }
}
