package com.example.demo.controller;

import com.example.demo.aop.PerformanceAspect;
import com.example.demo.aop.RateLimitAspect;
import com.example.demo.aop.RateLimited;
import com.example.demo.event.UserEventPublisher;
import com.example.demo.model.User;
import com.example.demo.service.UserService;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * AOP 和事件机制学习控制器
 */
@RestController
@RequestMapping("/aop")
public class AopEventController {

    private final UserService userService;
    private final UserEventPublisher eventPublisher;
    private final PerformanceAspect performanceAspect;
    private final RateLimitAspect rateLimitAspect;

    public AopEventController(UserService userService,
                              UserEventPublisher eventPublisher,
                              PerformanceAspect performanceAspect,
                              RateLimitAspect rateLimitAspect) {
        this.userService = userService;
        this.eventPublisher = eventPublisher;
        this.performanceAspect = performanceAspect;
        this.rateLimitAspect = rateLimitAspect;
    }

    /**
     * 学习首页
     */
    @GetMapping
    public Map<String, Object> index() {
        Map<String, Object> info = new HashMap<>();
        info.put("message", "Spring Boot 学习中心");
        info.put("topics", new String[]{
            "AOP 切面编程",
            "事件机制",
            "Bean 生命周期"
        });
        info.put("endpoints", new String[]{
            "GET  /aop          - AOP 概念说明",
            "GET  /aop/stats    - 性能统计",
            "GET  /aop/event    - 事件机制说明",
            "POST /aop/event/publish - 发布用户事件",
            "GET  /aop/event/history - 查看事件历史",
            "GET  /aop/ratelimit    - 限流测试"
        });
        return info;
    }

    // ==================== AOP 示例 ====================

    /**
     * AOP 概念说明
     */
    @GetMapping("/aop")
    public Map<String, Object> aopInfo() {
        Map<String, Object> info = new HashMap<>();
        info.put("title", "AOP 切面编程");
        info.put("concepts", new String[]{
            "Aspect（切面）: 横切关注点的模块化",
            "JoinPoint（连接点）: 程序执行的某个点",
            "Pointcut（切入点）: 匹配连接点的表达式",
            "Advice（通知）: 在连接点执行的动作",
            "Weaving（织入）: 将切面应用到目标对象"
        });
        info.put("adviceTypes", new String[]{
            "@Before - 方法执行前",
            "@After - 方法执行后（无论成功或异常）",
            "@AfterReturning - 方法成功返回后",
            "@AfterThrowing - 方法抛出异常后",
            "@Around - 环绕通知（最强大）"
        });
        info.put("useCases", new String[]{
            "日志记录",
            "性能监控",
            "事务管理",
            "权限检查",
            "限流控制"
        });
        return info;
    }

    /**
     * 查看性能统计
     */
    @GetMapping("/aop/stats")
    public Map<String, Object> getPerformanceStats() {
        Map<String, Object> result = new HashMap<>();
        result.put("title", "方法性能统计");
        result.put("description", "由 PerformanceAspect 自动收集");
        result.put("statistics", performanceAspect.getStatistics());
        return result;
    }

    // ==================== 事件机制示例 ====================

    /**
     * 事件机制说明
     */
    @GetMapping("/event")
    public Map<String, Object> eventInfo() {
        Map<String, Object> info = new HashMap<>();
        info.put("title", "Spring 事件机制");
        info.put("concepts", new String[]{
            "ApplicationEventPublisher - 事件发布者",
            "@EventListener - 事件监听器",
            "@Async - 异步处理事件",
            "condition - 条件过滤"
        });
        info.put("benefits", new String[]{
            "解耦：发布者和监听者互不依赖",
            "扩展：新增监听器无需修改发布者",
            "异步：耗时操作不阻塞主流程",
            "测试：更容易进行单元测试"
        });
        info.put("eventTypes", new String[]{
            "CREATED - 用户创建",
            "UPDATED - 用户更新",
            "DELETED - 用户删除",
            "LOGIN - 用户登录"
        });
        return info;
    }

    /**
     * 发布用户事件
     */
    @PostMapping("/event/publish")
    public Map<String, Object> publishEvent(
            @RequestParam Long userId,
            @RequestParam String userName,
            @RequestParam(defaultValue = "LOGIN") String eventType
    ) {
        eventPublisher.publishUserLogin(userId, userName);

        Map<String, Object> result = new HashMap<>();
        result.put("message", "事件已发布");
        result.put("eventType", eventType);
        result.put("userId", userId);
        result.put("userName", userName);
        return result;
    }

    /**
     * 查看事件历史
     */
    @GetMapping("/event/history")
    public Map<String, Object> getEventHistory() {
        Map<String, Object> result = new HashMap<>();
        result.put("title", "事件历史记录");
        result.put("note", "由 UserEventListener 自动记录");
        return result;
    }

    // ==================== 限流示例 ====================

    /**
     * 限流测试接口
     */
    @GetMapping("/ratelimit")
    @RateLimited(value = 10, message = "测试限流：每分钟最多10次")
    public Map<String, Object> testRateLimit() {
        Map<String, Object> result = new HashMap<>();
        result.put("message", "请求成功");
        result.put("note", "使用 @RateLimited 注解");
        result.put("rateLimitStatus", rateLimitAspect.getRateLimitStatus());
        return result;
    }
}