package incheon.com.security.aspect;

import incheon.com.security.annotation.RequireRole;
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;

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

    @Before("@within(incheon.com.security.annotation.RequireRole)")
    public void checkRole(JoinPoint joinPoint) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        RequireRole annotation = joinPoint.getTarget().getClass().getAnnotation(RequireRole.class);

        if (annotation == null) {
            return;
        }

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

        if (log.isDebugEnabled()) {
            log.debug("[RoleCheckAspect] 역할 체크 시작: class={}, method={}, system={}, roles={}, requireAll={}",
                    joinPoint.getTarget().getClass().getSimpleName(),
                    signature.getMethod().getName(),
                    system,
                    String.join(",", roles),
                    requireAll);
        }

        // 역할 체크 수행
        try {
            if (requireAll) {
                // AND 조건: 모든 역할 필요
                SecurityUtil.requireAllRoles(system, roles);
            } else {
                // OR 조건: 하나라도 있으면 OK (기본값)
                SecurityUtil.requireRole(system, roles);
            }

            if (log.isDebugEnabled()) {
                log.debug("[RoleCheckAspect] 역할 체크 성공: method={}", signature.getMethod().getName());
            }
        } catch (Exception e) {
            log.warn("[RoleCheckAspect] 역할 체크 실패: class={}, method={}, system={}, roles={}, error={}",
                    joinPoint.getTarget().getClass().getSimpleName(),
                    signature.getMethod().getName(),
                    system,
                    String.join(",", roles),
                    e.getMessage());
            throw e;
        }
    }
}
