package com.example.scaffold.learning;

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

import java.util.*;

/**
 * 事务学习控制器
 * 
 * 学习要点：
 * 1. 事务传播行为
 * 2. 事务隔离级别
 * 3. 事务回滚
 */
@Slf4j
@RestController
@RequestMapping("/api/learning/transaction")
@RequiredArgsConstructor
public class TransactionLearningController {
    
    /**
     * 事务概念
     */
    @GetMapping("/concepts")
    public Map<String, Object> concepts() {
        return Map.of(
            "ACID", Map.of(
                "Atomicity (原子性)", "事务是不可分割的工作单位",
                "Consistency (一致性)", "事务必须使数据库从一个一致性状态变换到另一个一致性状态",
                "Isolation (隔离性)", "多个用户并发访问数据库时，数据库为每个用户开启的事务不能被其他事务干扰",
                "Durability (持久性)", "事务一旦提交，对数据库的改变是永久性的"
            ),
            "Spring事务", "@Transactional 注解实现声明式事务管理"
        );
    }
    
    /**
     * 传播行为详解
     */
    @GetMapping("/propagation")
    public Map<String, Object> propagation() {
        return Map.of(
            "REQUIRED (默认)", Map.of(
                "描述", "有事务则加入，无则新建",
                "场景", "最常用，大多数业务方法",
                "示例", "A 调用 B，B 加入 A 的事务"
            ),
            "REQUIRES_NEW", Map.of(
                "描述", "总是新建事务，挂起当前事务",
                "场景", "日志记录、独立子任务",
                "示例", "A 调用 B，B 在新事务执行，A 回滚不影响 B"
            ),
            "SUPPORTS", Map.of(
                "描述", "有事务则加入，无则以非事务运行",
                "场景", "查询方法"
            ),
            "NOT_SUPPORTED", Map.of(
                "描述", "以非事务运行，挂起当前事务",
                "场景", "不需要事务的操作"
            ),
            "MANDATORY", Map.of(
                "描述", "必须在事务中运行，否则抛异常",
                "场景", "强制要求事务"
            ),
            "NEVER", Map.of(
                "描述", "不能在事务中运行，否则抛异常",
                "场景", "确保无事务"
            ),
            "NESTED", Map.of(
                "描述", "嵌套事务，可独立回滚",
                "场景", "部分失败不影响整体"
            )
        );
    }
    
    /**
     * 隔离级别详解
     */
    @GetMapping("/isolation")
    public Map<String, Object> isolation() {
        return Map.of(
            "DEFAULT", "使用数据库默认隔离级别",
            "READ_UNCOMMITTED", Map.of(
                "描述", "读未提交",
                "问题", "脏读、不可重复读、幻读",
                "性能", "最高"
            ),
            "READ_COMMITTED", Map.of(
                "描述", "读已提交",
                "问题", "不可重复读、幻读",
                "性能", "较高",
                "场景", "大多数数据库默认"
            ),
            "REPEATABLE_READ", Map.of(
                "描述", "可重复读",
                "问题", "幻读",
                "性能", "中等",
                "场景", "MySQL 默认"
            ),
            "SERIALIZABLE", Map.of(
                "描述", "串行化",
                "问题", "无",
                "性能", "最低",
                "场景", "数据一致性要求极高"
            ),
            "问题说明", Map.of(
                "脏读", "读到其他事务未提交的数据",
                "不可重复读", "同一事务两次读取结果不同（修改导致）",
                "幻读", "同一事务两次读取结果不同（新增/删除导致）"
            )
        );
    }
    
    /**
     * 回滚规则
     */
    @GetMapping("/rollback")
    public Map<String, Object> rollback() {
        return Map.of(
            "默认行为", "只对 RuntimeException 和 Error 回滚",
            "rollbackFor", "指定需要回滚的异常类型",
            "noRollbackFor", "指定不需要回滚的异常类型",
            "示例", """
                @Transactional(rollbackFor = Exception.class)
                @Transactional(noRollbackFor = BusinessException.class)
                """,
            "测试API", Map.of(
                "创建订单", "POST /api/orders",
                "创建订单(回滚)", "POST /api/orders?rollback=true"
            )
        );
    }
}