package ru.nbch.indicsearchservice.aspect;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.transaction.support.TransactionSynchronization;
import org.springframework.transaction.support.TransactionSynchronizationManager;

@Aspect
@Component
public class TransactionLoggingAspect {
    private static final Logger log = LoggerFactory.getLogger(TransactionLoggingAspect.class);

    @Around("@annotation(org.springframework.transaction.annotation.Transactional)")
    public Object logTransaction(ProceedingJoinPoint joinPoint) throws Throwable {
        boolean newTransaction = !TransactionSynchronizationManager.isActualTransactionActive();

        if (newTransaction) {
            log.debug("Transaction STARTED: {}", joinPoint.getSignature());
        }

        if (TransactionSynchronizationManager.isActualTransactionActive()) {
            TransactionSynchronizationManager.registerSynchronization(
                new TransactionSynchronization() {
                    @Override
                    public void afterCommit() {
                        log.debug("Transaction COMMITTED: {}", joinPoint.getSignature());
                    }

                    @Override
                    public void afterCompletion(int status) {
                        if (status == STATUS_ROLLED_BACK) {
                            log.debug("Transaction ROLLED BACK: {}", joinPoint.getSignature());
                        }
                    }
                }
            );
        }

        try {
            return joinPoint.proceed();
        } catch (Exception ex) {
            log.warn("Exception inside transaction: {}", joinPoint.getSignature(), ex);
            throw ex;
        }
    }
}
