package com.bio.bio_backend.global.aop;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

@Aspect
@Component
@Slf4j
public class RepositoryLoggingAspect {
    
    /**
     * Repository 계층의 모든 메서드 호출을 가로채서 로깅하는 Around 어드바이스
     */
    @Around("execution(* org.springframework.data.repository.Repository+.*(..))")
    public Object logQueryCall(ProceedingJoinPoint pjp) throws Throwable {
        // 메서드 실행 시작 시간을 기록
        long t0 = System.currentTimeMillis();
        
        // 실행될 메서드의 클래스명과 메서드명을 추출
        String type = pjp.getSignature().getDeclaringTypeName();
        String method = pjp.getSignature().getName();
        
        // 메서드 호출 시 전달되는 매개변수들을 추출
        Object[] args = pjp.getArgs();

        // 메서드 호출 시작을 로그로 기록
        log.info("[QUERY CALL] {}.{}(args={})", type, method, java.util.Arrays.toString(args));
        
        try {
            // 원본 메서드를 실행
            Object result = pjp.proceed();
            
            // 메서드 실행 완료를 로그로 기록 (실행 시간 포함)
            log.info("[QUERY DONE] {}.{}() in {}ms", type, method, (System.currentTimeMillis() - t0));
            
            // 원본 메서드의 결과를 반환
            return result;
        } catch (Throwable ex) {
            log.warn("[QUERY FAIL] {}.{}() -> {}", type, method, ex.toString());
            throw ex;
        }
    }
}