package com.flightticket.aspect;

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;
import org.springframework.transaction.annotation.Transactional;

/**
 * Aspect for logging database transactions
 * Requirements: 13.2
 * 
 * Logs:
 * - Transaction start
 * - Transaction commit
 * - Transaction rollback on failure
 * - Transaction execution time
 */
@Aspect
@Component
@Slf4j
public class TransactionLoggingAspect {
    
    /**
     * Log all transactional method executions
     * Captures transaction lifecycle and rollback scenarios
     */
    @Around("@annotation(transactional)")
    public Object logTransaction(ProceedingJoinPoint joinPoint, Transactional transactional) throws Throwable {
        String methodName = joinPoint.getSignature().toShortString();
        boolean readOnly = transactional.readOnly();
        
        if (!readOnly) {
            log.debug("Starting transaction for method: {}", methodName);
        }
        
        long startTime = System.currentTimeMillis();
        
        try {
            Object result = joinPoint.proceed();
            
            long executionTime = System.currentTimeMillis() - startTime;
            
            if (!readOnly) {
                log.debug("Transaction committed successfully for method: {} ({}ms)", 
                         methodName, executionTime);
            }
            
            return result;
            
        } catch (Exception e) {
            long executionTime = System.currentTimeMillis() - startTime;
            
            if (!readOnly) {
                log.error("Transaction rolled back for method: {} ({}ms) - Error: {}", 
                         methodName, executionTime, e.getMessage());
            }
            
            // Re-throw the exception to ensure rollback
            throw e;
        }
    }
    
    /**
     * Log all methods in service implementation classes
     * This provides broader coverage for transaction monitoring
     */
    @Around("execution(* com.flightticket.service.impl.*.*(..))")
    public Object logServiceTransaction(ProceedingJoinPoint joinPoint) throws Throwable {
        String methodName = joinPoint.getSignature().toShortString();
        String className = joinPoint.getTarget().getClass().getSimpleName();
        
        log.trace("Executing service method: {}.{}", className, methodName);
        
        long startTime = System.currentTimeMillis();
        
        try {
            Object result = joinPoint.proceed();
            
            long executionTime = System.currentTimeMillis() - startTime;
            
            if (executionTime > 1000) {
                log.warn("Slow service method execution: {}.{} ({}ms)", 
                        className, methodName, executionTime);
            }
            
            return result;
            
        } catch (Exception e) {
            long executionTime = System.currentTimeMillis() - startTime;
            
            log.error("Service method failed: {}.{} ({}ms) - Error: {} - Message: {}", 
                     className, methodName, executionTime, 
                     e.getClass().getSimpleName(), e.getMessage());
            
            throw e;
        }
    }
}
