package com.caliverse.admin.global.common.aspect;

import com.caliverse.admin.domain.entity.log.LogAction;
import com.caliverse.admin.global.common.annotation.BusinessProcess;
import com.caliverse.admin.global.component.manager.BusinessProcessIdManager;
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 BusinessProcessAspect {
    private final BusinessProcessIdManager processIdManager;

    public BusinessProcessAspect(BusinessProcessIdManager processIdManager) {
        this.processIdManager = processIdManager;
    }

    @Around("@annotation(businessProcess)")
    public Object handleBusinessProcess(ProceedingJoinPoint joinPoint, BusinessProcess businessProcess) throws Throwable {

        // 이미 프로세스 ID가 있는 경우 (하위 메서드) - 그대로 진행
        if (processIdManager.hasProcessId()) {
            return joinPoint.proceed();
        }

        // 새로운 프로세스 시작
        String processId = processIdManager.createNewProcessId();
        String processName = joinPoint.getSignature().getName();

        LogAction businessAction = businessProcess.action();
        if (businessAction == LogAction.UNKNOWN) {
            log.warn("Unknown business action: {}", processName);
        }
        processIdManager.setCurrentAction(businessAction);

        log.debug("Business process started: {} (ID: {})", processName, processId);

        try {
            Object result = joinPoint.proceed();
            log.debug("Business process completed: {} (ID: {})", processName, processId);
            return result;

        } catch (Exception e) {
            log.error("Business process failed: {} (ID: {}), Error: {}", processName, processId, e.getMessage());
            throw e;

        } finally {
            // 프로세스 종료 시 clear
            processIdManager.clear();
        }
    }
}
