package incheon.com.security.aspect;

import incheon.com.security.annotation.RequirePermission;
import incheon.com.security.util.SecurityUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

/**
 * @RequirePermission 어노테이션 AOP 처리
 * - OR 조건 (기본): permissions 중 하나라도 있으면 통과
 * - AND 조건 (requireAll=true): permissions 모두 필요
 */
@Slf4j
@Aspect
@Component
@Order(1) // 다른 AOP보다 먼저 실행 (권한 체크 우선)
public class PermissionCheckAspect {

    @Before("@annotation(incheon.com.security.annotation.RequirePermission)")
    public void checkPermission(JoinPoint joinPoint) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        RequirePermission annotation = signature.getMethod()
                .getAnnotation(RequirePermission.class);

        if (annotation == null) {
            return;
        }

        String system = annotation.system();
        String[] permissions = annotation.permissions();
        boolean requireAll = annotation.requireAll();

        if (log.isDebugEnabled()) {
            log.debug("[PermissionCheckAspect] 권한 체크 시작: method={}, system={}, permissions={}, requireAll={}",
                    signature.getMethod().getName(),
                    system,
                    String.join(",", permissions),
                    requireAll);
        }

        // 권한 체크 수행
        try {
            if (requireAll) {
                // AND 조건: 모든 권한 필요
                SecurityUtil.requireAllPermissions(system, permissions);
            } else {
                // OR 조건: 하나라도 있으면 OK (기본값)
                SecurityUtil.requirePermission(system, permissions);
            }

            if (log.isDebugEnabled()) {
                log.debug("[PermissionCheckAspect] 권한 체크 성공: method={}", signature.getMethod().getName());
            }
        } catch (Exception e) {
            log.warn("[PermissionCheckAspect] 권한 체크 실패: method={}, system={}, permissions={}, error={}",
                    signature.getMethod().getName(),
                    system,
                    String.join(",", permissions),
                    e.getMessage());
            throw e; // AccessDeniedException 재발생
        }
    }
}
