package com.kexue.skills.utils;

import org.apache.commons.io.FileUtils;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.error.YAMLException;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Objects;

/**
 * 通用 YAML 解析工具：YAML 文件/文本 → Map（支持嵌套结构）
 */
public class YamlToMapUtil {

    // 初始化 YAML 解析器（线程安全，可全局复用）
    private static final Yaml YAML_PARSER = new Yaml();

    /**
     * 1. 读取 YAML 文件，解析成 Map（支持嵌套结构）
     * @param yamlFilePath YAML 文件路径（如 "D:/config.yaml" 或 "classpath:config.yaml"）
     * @return 嵌套 Map（key: 字段名，value: 字段值，嵌套结构保留）
     * @throws IOException      文件不存在/读取失败
     * @throws YAMLException    YAML 格式错误
     */
    @SuppressWarnings("unchecked")
    public static Map<String, Object> yamlFileToMap(String yamlFilePath) throws IOException, YAMLException {
        // 处理 classpath 下的文件（如 resources/config.yaml）
        if (yamlFilePath.startsWith("classpath:")) {
            String path = yamlFilePath.replace("classpath:", "");
            // 通过类加载器获取输入流（避免路径问题）
            try (InputStream inputStream = YamlToMapUtil.class.getClassLoader().getResourceAsStream(path)) {
                if (inputStream == null) {
                    throw new IOException("Classpath 下未找到 YAML 文件：" + path);
                }
                // 解析 YAML 为 Map（SnakeYAML 自动识别结构）
                return YAML_PARSER.loadAs(inputStream, Map.class);
            }
        }

        // 处理本地绝对路径文件（如 D:/config.yaml）
        File yamlFile = new File(yamlFilePath);
        if (!yamlFile.exists()) {
            throw new IOException("YAML 文件不存在：" + yamlFilePath);
        }
        // 读取文件内容并解析
        String yamlContent = FileUtils.readFileToString(yamlFile, StandardCharsets.UTF_8);
        return yamlTextToMap(yamlContent);
    }

    /**
     * 2. 解析 YAML 字符串，生成 Map（支持嵌套结构）
     * @param yamlText YAML 字符串（如 "name: test\nage: 18"）
     * @return 嵌套 Map
     * @throws YAMLException YAML 格式错误
     */
    @SuppressWarnings("unchecked")
    public static Map<String, Object> yamlTextToMap(String yamlText) throws YAMLException {
        if (yamlText == null || yamlText.trim().isEmpty()) {
            return new LinkedHashMap<>(); // 返回空 Map，避免空指针
        }
        // 解析 YAML 文本，SnakeYAML 会自动转换类型（数字→Integer/Long，布尔→Boolean）
        Object result = YAML_PARSER.load(yamlText);
        // 若 YAML 是纯数组（如 "- a\n- b"），返回 key 为 "list" 的 Map；否则直接返回 Map
        if (result instanceof Map) {
            return (Map<String, Object>) result;
        } else if (result instanceof Iterable) {
            Map<String, Object> map = new LinkedHashMap<>();
            map.put("list", result);
            return map;
        } else {
            // 纯单个值（如 "test"），返回 key 为 "value" 的 Map
            Map<String, Object> map = new LinkedHashMap<>();
            map.put("value", result);
            return map;
        }
    }

    /**
     * 3. 可选工具：将嵌套 Map 扁平化（如 a.b.c: 123），方便直接取值
     * @param nestedMap 嵌套 Map（来自上述两个方法的返回值）
     * @return 扁平化 Map（key: 拼接路径，value: 原始值）
     */
    public static Map<String, Object> flattenMap(Map<String, Object> nestedMap) {
        Map<String, Object> flatMap = new LinkedHashMap<>();
        flattenMapRecursive(nestedMap, "", flatMap);
        return flatMap;
    }

    /**
     * 递归处理嵌套 Map，生成扁平化 key（私有辅助方法）
     */
    @SuppressWarnings("unchecked")
    private static void flattenMapRecursive(Map<String, Object> map, String parentKey, Map<String, Object> flatMap) {
        for (Map.Entry<String, Object> entry : map.entrySet()) {
            String currentKey = parentKey.isEmpty() ? entry.getKey() : parentKey + "." + entry.getKey();
            Object value = entry.getValue();

            if (value instanceof Map) {
                // 嵌套 Map，递归处理
                flattenMapRecursive((Map<String, Object>) value, currentKey, flatMap);
            } else if (value instanceof Iterable && !(value instanceof String)) {
                // 数组/列表（如 List），key 加索引（如 list.0, list.1）
                int index = 0;
                for (Object item : (Iterable<?>) value) {
                    String listKey = currentKey + "." + index;
                    if (item instanceof Map) {
                        flattenMapRecursive((Map<String, Object>) item, listKey, flatMap);
                    } else {
                        flatMap.put(listKey, item);
                    }
                    index++;
                }
            } else {
                // 基本类型（字符串、数字、布尔），直接放入扁平化 Map
                flatMap.put(currentKey, value);
            }
        }
    }

    // ==================== 测试示例 ====================
    public static void main(String[] args) {
        try {
            // 示例1：解析 YAML 文件（classpath 下的 config.yaml）
            Map<String, Object> fileMap = yamlFileToMap("classpath:config.yaml");
            System.out.println("【嵌套 Map（文件解析）】" + fileMap);

            // 示例2：解析 YAML 字符串（含嵌套结构）
            String yamlText = """
                    name: "ppt_gen_direct"
                    description: "Create PPT"
                    settings:
                      timeout: 300
                      enable: true
                      colors:
                        - red
                        - blue
                    """;
            Map<String, Object> textMap = yamlTextToMap(yamlText);
            System.out.println("【嵌套 Map（文本解析）】" + textMap);

            // 示例3：扁平化 Map，方便取值
            Map<String, Object> flatMap = flattenMap(textMap);
            System.out.println("【扁平化 Map】" + flatMap);
            // 直接通过拼接 key 取值
            System.out.println("settings.timeout = " + flatMap.get("settings.timeout"));
            System.out.println("settings.colors.0 = " + flatMap.get("settings.colors.0"));

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}