package com.example.scaffold.learning;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.session.SqlSessionFactory;
import org.springframework.web.bind.annotation.*;

import java.util.*;

/**
 * MyBatis 学习控制器
 * 
 * 学习要点：
 * 1. MyBatis vs JPA 对比
 * 2. 动态 SQL
 * 3. 缓存机制
 * 4. 结果映射
 */
@Slf4j
@RestController
@RequestMapping("/api/learning/mybatis")
@RequiredArgsConstructor
public class MyBatisLearningController {
    
    private final SqlSessionFactory sqlSessionFactory;
    
    /**
     * MyBatis 核心概念
     */
    @GetMapping("/concepts")
    public Map<String, Object> concepts() {
        return Map.of(
            "MyBatis", "半自动 ORM 框架，SQL 与 Java 对象映射",
            "核心组件", Map.of(
                "SqlSessionFactory", "创建 SqlSession 的工厂",
                "SqlSession", "执行 SQL 的会话",
                "Mapper", "接口绑定的 SQL 语句",
                "Configuration", "MyBatis 配置信息"
            ),
            "缓存", Map.of(
                "一级缓存", "SqlSession 级别，默认开启",
                "二级缓存", "Mapper 级别，需配置 @CacheNamespace"
            )
        );
    }
    
    /**
     * MyBatis vs JPA 对比
     */
    @GetMapping("/vs-jpa")
    public Map<String, Object> vsJpa() {
        return Map.of(
            "MyBatis", Map.of(
                "优点", List.of("SQL 灵活可控", "性能优化方便", "复杂查询友好"),
                "缺点", List.of("SQL 与代码耦合", "数据库迁移成本高", "需要手写 SQL"),
                "适用场景", "复杂查询、性能要求高、DBA 参与项目"
            ),
            "JPA/Hibernate", Map.of(
                "优点", List.of("面向对象", "数据库无关", "开发效率高"),
                "缺点", List.of("复杂查询困难", "性能调优复杂", "学习曲线陡"),
                "适用场景", "标准 CRUD、快速开发、领域驱动设计"
            ),
            "建议", "小型项目用 JPA，大型/复杂查询项目用 MyBatis"
        );
    }
    
    /**
     * 动态 SQL 语法
     */
    @GetMapping("/dynamic-sql")
    public Map<String, Object> dynamicSql() {
        return Map.of(
            "if", "条件判断 <if test='name != null'> AND name = #{name} </if>",
            "choose/when/otherwise", "类似 switch-case",
            "trim/where/set", "处理 SQL 拼接",
            "foreach", "循环遍历 <foreach item='item' collection='list' separator=','>#{item}</foreach>",
            "bind", "定义变量 <bind name='pattern' value=\"'%' + name + '%'\" />",
            "示例", """
                <select id='findUser'>
                    SELECT * FROM users
                    <where>
                        <if test='name != null'>AND name LIKE #{name}</if>
                        <if test='email != null'>AND email = #{email}</if>
                    </where>
                </select>
                """
        );
    }
    
    /**
     * 缓存演示
     */
    @GetMapping("/cache")
    public Map<String, Object> cacheDemo() {
        return Map.of(
            "一级缓存", Map.of(
                "范围", "SqlSession 级别",
                "默认", "开启",
                "失效条件", List.of("执行 insert/update/delete", "调用 sqlSession.clearCache()", "事务提交/回滚"),
                "演示", "同一 SqlSession 内连续两次相同查询，第二次不执行 SQL"
            ),
            "二级缓存", Map.of(
                "范围", "Mapper 级别",
                "配置", "@CacheNamespace 或 XML 配置",
                "注意", "实体类需要实现 Serializable",
                "本项目", "UserMapper 已启用二级缓存"
            ),
            "验证方式", "查看控制台 SQL 日志，缓存命中时不打印 SQL"
        );
    }
    
    /**
     * 查看当前配置
     */
    @GetMapping("/config")
    public Map<String, Object> getConfig() {
        var config = sqlSessionFactory.getConfiguration();
        
        return Map.of(
            "cacheEnabled", config.isCacheEnabled(),
            "localCacheScope", config.getLocalCacheScope().name(),
            "defaultExecutorType", config.getDefaultExecutorType().name(),
            "mapUnderscoreToCamelCase", config.isMapUnderscoreToCamelCase(),
            "mappedStatements", config.getMappedStatements().size()
        );
    }
}