package com.example.scaffold.learning;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

import java.util.*;

/**
 * AOP 学习控制器
 * 
 * 学习要点：
 * 1. 切面概念
 * 2. 通知类型
 * 3. 切入点表达式
 */
@Slf4j
@RestController
@RequestMapping("/api/learning/aop")
@RequiredArgsConstructor
public class AopLearningController {
    
    /**
     * AOP 概念说明
     */
    @GetMapping("/concepts")
    public Map<String, Object> concepts() {
        return Map.of(
            "AOP", "面向切面编程 (Aspect Oriented Programming)",
            "核心概念", Map.of(
                "Aspect (切面)", "横切关注点的模块化",
                "JoinPoint (连接点)", "程序执行的某个特定位置",
                "Pointcut (切入点)", "匹配连接点的表达式",
                "Advice (通知)", "在切入点执行的代码",
                "Target (目标对象)", "被通知的对象",
                "Proxy (代理)", "AOP 创建的代理对象",
                "Weaving (织入)", "将切面应用到目标对象的过程"
            ),
            "通知类型", Map.of(
                "@Before", "方法执行前",
                "@After", "方法执行后（无论是否异常）",
                "@AfterReturning", "方法成功返回后",
                "@AfterThrowing", "方法抛出异常后",
                "@Around", "环绕 - 完全控制方法执行"
            )
        );
    }
    
    /**
     * 切入点表达式语法
     */
    @GetMapping("/pointcut-syntax")
    public Map<String, Object> pointcutSyntax() {
        return Map.of(
            "语法", "execution(修饰符? 返回类型 包名.类名.方法名(参数) 异常?)",
            "示例", List.of(
                "execution(* com.example.service.*.*(..)) - service包下所有方法",
                "execution(* com.example.service..*.*(..)) - service包及子包所有方法",
                "execution(public * *(..)) - 所有public方法",
                "execution(* set*(..)) - 所有set开头的方法",
                "execution(* com.example.service.UserService.*(..)) - UserService的所有方法",
                "@annotation(org.springframework.transaction.annotation.Transactional) - 带@Transactional的方法"
            ),
            "通配符", Map.of(
                "*", "匹配任意字符",
                "..", "匹配任意层级的包或任意参数",
                "+", "匹配指定类及其子类"
            )
        );
    }
    
    /**
     * 测试 AOP - 这个方法会被切面拦截
     */
    @GetMapping("/test")
    public Map<String, Object> testAop(@RequestParam(defaultValue = "test") String message) {
        log.info("📝 [AopLearningController] 测试方法被调用: message={}", message);
        
        return Map.of(
            "message", "AOP 测试成功",
            "input", message,
            "tip", "查看控制台日志，观察 AOP 通知的执行顺序",
            "expectedOrder", List.of(
                "1. @Around 开始",
                "2. @Before",
                "3. 方法执行",
                "4. @AfterReturning",
                "5. @After",
                "6. @Around 结束"
            )
        );
    }
    
    /**
     * 演示异常通知
     */
    @GetMapping("/test-error")
    public Map<String, Object> testError(@RequestParam(defaultValue = "false") boolean error) {
        log.info("📝 [AopLearningController] 测试异常通知: error={}", error);
        
        if (error) {
            throw new RuntimeException("这是一个测试异常，用于触发 @AfterThrowing");
        }
        
        return Map.of(
            "message", "正常执行",
            "tip", "传入 error=true 触发异常，观察 @AfterThrowing"
        );
    }
}