package com.example.demo.aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

/**
 * 日志切面 - 演示 AOP 基础
 * 
 * 学习点：
 * - @Aspect 定义切面
 * - @Pointcut 切入点表达式
 * - @Before / @After / @Around 通知类型
 * - JoinPoint 获取方法信息
 */
@Aspect
@Component
public class LoggingAspect {
    
    /**
     * 切入点：所有 Controller 方法
     */
    @Pointcut("execution(* com.example.demo.controller.*.*(..))")
    public void controllerMethods() {}
    
    /**
     * 切入点：所有 Service 方法
     */
    @Pointcut("execution(* com.example.demo.service.*.*(..))")
    public void serviceMethods() {}
    
    /**
     * 前置通知 - 方法执行前
     */
    @Before("controllerMethods()")
    public void logBeforeController(JoinPoint joinPoint) {
        System.out.println("[AOP-Before] Controller 方法开始: " + 
            joinPoint.getSignature().getName());
        System.out.println("  参数: " + Arrays.toString(joinPoint.getArgs()));
    }
    
    /**
     * 后置通知 - 方法执行后（无论成功或异常）
     */
    @After("serviceMethods()")
    public void logAfterService(JoinPoint joinPoint) {
        System.out.println("[AOP-After] Service 方法结束: " + 
            joinPoint.getSignature().getName());
    }
    
    /**
     * 返回通知 - 方法成功返回后
     */
    @AfterReturning(pointcut = "controllerMethods()", returning = "result")
    public void logAfterReturning(JoinPoint joinPoint, Object result) {
        System.out.println("[AOP-AfterReturning] 方法返回: " + 
            joinPoint.getSignature().getName());
        System.out.println("  返回值: " + result);
    }
    
    /**
     * 异常通知 - 方法抛出异常后
     */
    @AfterThrowing(pointcut = "controllerMethods() || serviceMethods()", throwing = "error")
    public void logAfterThrowing(JoinPoint joinPoint, Throwable error) {
        System.out.println("[AOP-AfterThrowing] 方法异常: " + 
            joinPoint.getSignature().getName());
        System.out.println("  异常: " + error.getMessage());
    }
}