package com.kexue.skills.common.util;

import com.kexue.skills.utils.EscapeCharacterUtils;
import net.sf.sevenzipjbinding.IInArchive;
import net.sf.sevenzipjbinding.SevenZip;
import net.sf.sevenzipjbinding.SevenZipException;
import net.sf.sevenzipjbinding.impl.RandomAccessFileInStream;
import net.sf.sevenzipjbinding.simple.ISimpleInArchive;
import net.sf.sevenzipjbinding.simple.ISimpleInArchiveItem;
import org.yaml.snakeyaml.DumperOptions;
import org.yaml.snakeyaml.Yaml;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

/**
 * 技能包解析工具类
 * 用于解析skill zip包并生成符合要求的yaml描述
 */
public class SkillZipParser {

    private static final Pattern FRONT_MATTER_PATTERN = Pattern.compile(
            "^---\\r?\\n(.*?)\\r?\\n---\\r?\\n",
            Pattern.DOTALL
    );

    /**
     * 提取压缩包中的skillMdText
     * @param filePath 压缩文件路径
     * @param defaultSkillName 默认技能名称
     * @return 包含skillMdText的Map
     * @throws IOException 解析过程中的IO异常
     * @throws SevenZipException 解析RAR文件时的异常
     */
    public static Map<String, Object> extractSkillMdText(String filePath, String defaultSkillName) throws IOException, SevenZipException {
        // 检查文件扩展名
        String fileExtension = "";
        if (filePath.contains(".")) {
            int dotIndex = filePath.lastIndexOf(".");
            fileExtension = filePath.substring(dotIndex).toLowerCase();
        }
        
        // 根据文件类型选择不同的解析方法
        if (".rar".equals(fileExtension)) {
            return extractSkillInfoFromRar(filePath, defaultSkillName);
        } else {
            // 默认为zip文件
            try (ZipFile zipFile = new ZipFile(filePath, StandardCharsets.UTF_8)) {
                return extractSkillInfo(zipFile, defaultSkillName);
            }
        }
    }

    /**
     * 生成技能包的yaml描述
     * @param filePath 压缩文件路径
     * @param author 作者
     * @param skillName 技能名称
     * @param skillDescription 技能描述
     * @param skillTags 技能标签
     * @return 生成的yaml描述
     * @throws IOException 解析过程中的IO异常
     * @throws SevenZipException 解析RAR文件时的异常
     */
    public static String generateYamlFromSkillInfo(String filePath, String author, String skillName, String skillDescription, List<String> skillTags) throws IOException, SevenZipException {
        // 检查文件扩展名
        String fileExtension = "";
        if (filePath.contains(".")) {
            int dotIndex = filePath.lastIndexOf(".");
            fileExtension = filePath.substring(dotIndex).toLowerCase();
        }
        
        // 根据文件类型选择不同的解析方法
        Map<String, Object> skillStructure;
        if (".rar".equals(fileExtension)) {
            skillStructure = generateSkillStructureFromRar(filePath, skillName, skillDescription, skillTags, author);
        } else {
            // 默认为zip文件
            try (ZipFile zipFile = new ZipFile(filePath, StandardCharsets.UTF_8)) {
                skillStructure = generateSkillStructure(zipFile, skillName, skillDescription, skillTags, author);
            }
        }

        Map<String, Object> packageMap = new HashMap<>();
        packageMap.put("package", skillStructure);

        
        // 生成yaml
        return generateYaml(packageMap);
    }


    /**
     * 从rar文件中提取技能信息
     * @param rarFilePath rar文件路径
     * @param defaultSkillName 默认技能名称
     * @return 技能信息
     * @throws IOException 解析过程中的IO异常
     * @throws Exception 解析过程中的异常
     */
    private static Map<String, Object> extractSkillInfoFromRar(String rarFilePath, String defaultSkillName) throws IOException, SevenZipException {
        Map<String, Object> skillInfo = new LinkedHashMap<>();
        boolean foundMdFile = false;

        // 验证文件是否存在
        File rarFile = new File(rarFilePath);
        if (!rarFile.exists()) {
            throw new FileNotFoundException("RAR file not found: " + rarFilePath);
        }
        if (!rarFile.canRead()) {
            throw new IOException("Cannot read RAR file: " + rarFilePath);
        }

        // 打开RAR文件并解析归档内容
        try (RandomAccessFile randomAccessFile = new RandomAccessFile(rarFile, "r");
             IInArchive archive = SevenZip.openInArchive(null, new RandomAccessFileInStream(randomAccessFile))) {
            ISimpleInArchive simpleInArchive = archive.getSimpleInterface();

            // 首先尝试在根目录查找md文件，用于调用deepseek生成package下得第一个节点
            for (ISimpleInArchiveItem item : simpleInArchive.getArchiveItems()) {
                String path = item.getPath();
                if (!item.isFolder() && path.endsWith(".md") && !path.contains("/") && !path.contains("\\")) {

                    if (path.toLowerCase().contains("skill.md") || path.toLowerCase().contains("readme.md")){
                        // 读取文件内容
                        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
                        item.extractSlow(data -> {
                            try {
                                outputStream.write(data);
                            } catch (IOException e) {
                                throw new RuntimeException(e);
                            }
                            return data.length;
                        });

                        String content = outputStream.toString(StandardCharsets.UTF_8);

                        // 存储md文件的完整内容
                        skillInfo.put("skillMdText", content);

                        // 解析md内容
                        parseSkillsMd(content, skillInfo);
                        foundMdFile = true;
                        break; // 找到一个md文件后就停止
                    }
                }
            }

            // 如果根目录没有找到md文件，递归进入子目录查找
            if (!foundMdFile) {
                // 收集所有条目用于后续处理
                List<ISimpleInArchiveItem> allItems = new ArrayList<>();
                for (ISimpleInArchiveItem item : simpleInArchive.getArchiveItems()) {
                    allItems.add(item);
                }

                // 递归查找md文件
                String mdRootDir = findMdFileRecursively(allItems, "", skillInfo);

                // 如果找到了md文件，以该目录为根目录解析所有文件和文件夹
                if (foundMdFile && mdRootDir != null && !mdRootDir.isEmpty()) {
                    // 清空之前可能添加的children（如果有的话）
                    if (skillInfo.containsKey("structure")) {
                        Map<String, Object> structure = (Map<String, Object>) skillInfo.get("structure");
                        if (structure.containsKey("children")) {
                            ((List<?>) structure.get("children")).clear();
                        }
                    }

                    // 以找到的md文件所在目录为根目录，构建目录树结构
                    List<Map<String, Object>> children = new ArrayList<>();
                    Map<String, Map<String, Object>> directoryMap = new HashMap<>();

                    // 首先处理所有目录（只处理mdRootDir及其子目录下的）
                    for (ISimpleInArchiveItem item : allItems) {
                        if (item.isFolder()) {
                            String path = item.getPath();
                            // 确保路径以/结尾
                            if (!path.endsWith("/")) {
                                path = path + "/";
                            }
                            // 只处理mdRootDir目录下的文件夹
                            if (path.startsWith(mdRootDir + "/") || path.equals(mdRootDir + "/")) {
                                String relativePath = path.substring(mdRootDir.length() + 1);
                                if (!relativePath.isEmpty()) {
                                    String[] pathParts = relativePath.split("/");
                                    createDirectoryTree(children, directoryMap, pathParts, path);
                                }
                            }
                        }
                    }

                    // 然后处理所有文件（只处理mdRootDir目录下的）
                    for (ISimpleInArchiveItem item : allItems) {
                        if (!item.isFolder()) {
                            String path = item.getPath();
                            // 只处理mdRootDir目录下的文件
                            if (path.startsWith(mdRootDir + "/")) {
                                String relativePath = path.substring(mdRootDir.length() + 1);
                                String[] pathParts = relativePath.split("/");
                                String fileName = pathParts[pathParts.length - 1];

                                // 读取文件内容
                                ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
                                item.extractSlow(data -> {
                                    try {
                                        outputStream.write(data);
                                    } catch (IOException e) {
                                        throw new RuntimeException(e);
                                    }
                                    return data.length;
                                });

                                String fileContent = outputStream.toString(StandardCharsets.UTF_8);
                                addFileToTreeFromRar(children, directoryMap, pathParts, fileName, fileContent, path);
                            }
                        }
                    }

                    // 将构建好的目录树存储到skillInfo中
                    Map<String, Object> structure = new LinkedHashMap<>();
                    structure.put("name", skillInfo.getOrDefault("name", defaultSkillName));
                    structure.put("type", "directory");
                    structure.put("path", ".");
                    structure.put("format", "directory");
                    structure.put("description", skillInfo.getOrDefault("description", "Skill package"));
                    structure.put("children", children);
                    skillInfo.put("structure", structure);
                }
            }
        }

        // 如果没有找到 md 文件，使用默认值
        if (!foundMdFile) {
            skillInfo.put("name", defaultSkillName);
            skillInfo.put("description", "Skill uploaded via uploadSkillV2");
            skillInfo.put("tags", Arrays.asList("10001", "10002"));
        } else {
            // 确保 tags 不为 null
            if (!skillInfo.containsKey("tags")) {
                skillInfo.put("tags", Arrays.asList("10001"));
            }
        }

        return skillInfo;
    }
    
    /**
     * 从压缩文件中提取技能信息
     * @param zipFile zip文件对象
     * @param defaultSkillName 默认技能名称
     * @return 技能信息
     * @throws IOException 解析过程中的IO异常
     */
    private static Map<String, Object> extractSkillInfo(ZipFile zipFile, String defaultSkillName) throws IOException {
        Map<String, Object> skillInfo = new LinkedHashMap<>();
        boolean foundMdFile = false;
        String mdRootDir = "";
        
        // 尝试从zip根目录的md文件中提取信息
        Enumeration<? extends ZipEntry> entries = zipFile.entries();
        while (entries.hasMoreElements()) {
            ZipEntry entry = entries.nextElement();
            System.out.println(entry.getName());
            // 检查是否是根目录下的md文件
            if (!entry.isDirectory() && (entry.getName().toLowerCase().endsWith("skill.md") || entry.getName().toLowerCase().endsWith("readme.md"))) {
                try (InputStream inputStream = zipFile.getInputStream(entry);
                     BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8))) {
                    StringBuilder content = new StringBuilder();
                    String line;
                    while ((line = reader.readLine()) != null) {
                        content.append(line).append("\n");
                    }
                    
                    // 存储md文件的完整内容
                    skillInfo.put("skillMdText", content.toString());
                    
                    // 解析md内容
                    parseSkillsMd(content.toString(), skillInfo);
                    foundMdFile = true;
                    mdRootDir = ".";
                    break; // 找到一个md文件后就停止
                }
            }
        }
        
        // 如果根目录没有找到md文件，检查根目录下的文件夹
        if (!foundMdFile) {
            // 收集根目录下的文件夹
            List<String> rootFolders = new ArrayList<>();
            entries = zipFile.entries();
            while (entries.hasMoreElements()) {
                ZipEntry entry = entries.nextElement();
                if (entry.isDirectory()) {
                    String path = entry.getName();
                    // 确保是根目录下的文件夹（路径中不包含/，或者以/结尾且前面没有/）
                    if (path.endsWith("/") && !path.substring(0, path.length() - 1).contains("/")) {
                        rootFolders.add(path.substring(0, path.length() - 1));
                    }
                }
            }
            
            // 检查每个根目录文件夹下的md文件
            for (String folder : rootFolders) {
                entries = zipFile.entries();
                while (entries.hasMoreElements()) {
                    ZipEntry entry = entries.nextElement();
                    if (!entry.isDirectory()) {
                        String path = entry.getName();
                        // 检查是否是该文件夹下的md文件
                        if (path.endsWith(".md") && (path.equals(folder + "/skill.md") || path.equals(folder + "/SKILL.md") || 
                            path.equals(folder + "/readme.md") || path.equals(folder + "/README.md"))) {
                            try (InputStream inputStream = zipFile.getInputStream(entry);
                                 BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8))) {
                                StringBuilder content = new StringBuilder();
                                String line;
                                while ((line = reader.readLine()) != null) {
                                    content.append(line).append("\n");
                                }
                                
                                // 存储md文件的完整内容
                                skillInfo.put("skillMdText", content.toString());
                                
                                // 解析md内容
                                parseSkillsMd(content.toString(), skillInfo);
                                foundMdFile = true;
                                mdRootDir = folder;
                                break; // 找到一个md文件后就停止
                            }
                        }
                    }
                }
                if (foundMdFile) break; // 找到一个md文件后就停止
            }
        }

        // 如果找到了md文件，构建目录树结构
        if (foundMdFile && mdRootDir != null && !mdRootDir.isEmpty()) {
            // 清空之前可能添加的children（如果有的话）
            if (skillInfo.containsKey("structure")) {
                Map<String, Object> structure = (Map<String, Object>) skillInfo.get("structure");
                if (structure.containsKey("children")) {
                    ((List<?>) structure.get("children")).clear();
                }
            }

            // 以找到的md文件所在目录为根目录，构建目录树结构
            List<Map<String, Object>> children = new ArrayList<>();
            Map<String, Map<String, Object>> directoryMap = new HashMap<>();

            // 首先处理所有目录（只处理mdRootDir及其子目录下的）
            entries = zipFile.entries();
            while (entries.hasMoreElements()) {
                ZipEntry entry = entries.nextElement();
                if (entry.isDirectory()) {
                    String path = entry.getName();
                    // 确保路径以/结尾
                    if (!path.endsWith("/")) {
                        path = path + "/";
                    }
                    // 只处理mdRootDir目录下的文件夹
                    if (path.startsWith(mdRootDir + "/") || path.equals(mdRootDir + "/")) {
                        String relativePath = path.substring(mdRootDir.length() + 1);
                        if (!relativePath.isEmpty()) {
                            String[] pathParts = relativePath.split("/");
                            createDirectoryTree(children, directoryMap, pathParts, path);
                        }
                    }
                }
            }

            // 然后处理所有文件（只处理mdRootDir目录下的）
            entries = zipFile.entries();
            while (entries.hasMoreElements()) {
                ZipEntry entry = entries.nextElement();
                if (!entry.isDirectory()) {
                    String path = entry.getName();
                    // 只处理mdRootDir目录下的文件
                    if (path.startsWith(mdRootDir + "/")) {
                        String relativePath = path.substring(mdRootDir.length() + 1);
                        String[] pathParts = relativePath.split("/");
                        addFileToTree(children, directoryMap, pathParts, entry, zipFile);
                    } else if (".".equals(mdRootDir) && !path.contains("/")) {
                        // 处理根目录下的文件
                        String[] pathParts = {path};
                        addFileToTree(children, directoryMap, pathParts, entry, zipFile);
                    }
                }
            }

            // 将构建好的目录树存储到skillInfo中
            Map<String, Object> structure = new LinkedHashMap<>();
            // structure.put("name", skillInfo.getOrDefault("name", defaultSkillName));
            // structure.put("type", "directory");
            // structure.put("path", ".");
            // structure.put("format", "directory");
            // structure.put("description", skillInfo.getOrDefault("description", "Skill package"));
            // structure.put("children", children);
            skillInfo.put("structure", structure);
        }

        // 如果没有找到 md 文件，使用默认值
        if (!foundMdFile) {
            skillInfo.put("name", defaultSkillName);
            skillInfo.put("description", "Skill uploaded via uploadSkillV2");
            skillInfo.put("tags", Arrays.asList("10001", "10002"));
        } else {
            // 确保 tags 不为 null
            if (!skillInfo.containsKey("tags")) {
                skillInfo.put("tags", Arrays.asList("10001"));
            }
        }

        return skillInfo;
    }
    
    /**
     * 解析skills.md文件内容
     * @param content skills.md文件内容
     * @param skillInfo 技能信息Map
     */
    private static void parseSkillsMd(String content, Map<String, Object> skillInfo) {
        // 解析技能名称
        Pattern namePattern = Pattern.compile("#\\s+(.*)");
        Matcher nameMatcher = namePattern.matcher(content);
        if (nameMatcher.find()) {
            skillInfo.put("name", nameMatcher.group(1).trim());
        }
            
        // 解析技能描述
        Pattern descPattern = Pattern.compile("##\\s+Description\\s+(.*?)(?=##|$)", Pattern.DOTALL);
        Matcher descMatcher = descPattern.matcher(content);
        if (descMatcher.find()) {
            String description = descMatcher.group(1).trim();
            skillInfo.put("description", description);
        }
            
        // 解析技能标签
        Pattern tagPattern = Pattern.compile("##\\s+Tags\\s+(.*?)(?=##|$)", Pattern.DOTALL);
        Matcher tagMatcher = tagPattern.matcher(content);
        if (tagMatcher.find()) {
            String tagsSection = tagMatcher.group(1);
            Pattern tagItemPattern = Pattern.compile("-\\s+(.*)");
            Matcher tagItemMatcher = tagItemPattern.matcher(tagsSection);
            List<String> tags = new ArrayList<>();
            while (tagItemMatcher.find()) {
                tags.add(tagItemMatcher.group(1).trim());
            }
            if (!tags.isEmpty()) {
                skillInfo.put("tags", tags);
            }
        }
    }
        
    /**
     * 递归查找md文件
     * @param allItems 所有归档条目
     * @param currentDir 当前目录路径
     * @param skillInfo 技能信息Map
     * @return 找到md文件的根目录路径，如果没找到返回null
     * @throws SevenZipException 解析RAR文件时的异常
     */
    private static String findMdFileRecursively(List<ISimpleInArchiveItem> allItems, String currentDir, Map<String, Object> skillInfo) throws SevenZipException {
        // 检查当前目录下是否有md文件
        for (ISimpleInArchiveItem item : allItems) {
            if (!item.isFolder()) {
                String path = item.getPath();
                // 统一路径分隔符为/
                path = path.replace("\\", "/");
                // 确保路径以/结尾（如果是目录）
                String checkPath = currentDir.isEmpty() ? path : (path.startsWith(currentDir + "/") ? path.substring(currentDir.length() + 1) : null);
                    
                if (checkPath != null && !checkPath.contains("/") && checkPath.endsWith(".md")) {
                    // 在当前目录找到了md文件
                    try {
                        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
                        item.extractSlow(data -> {
                            try {
                                outputStream.write(data);
                            } catch (IOException e) {
                                throw new RuntimeException(e);
                            }
                            return data.length;
                        });
                            
                        String content = outputStream.toString(StandardCharsets.UTF_8);
                            
                        // 存储md文件的完整内容
                        skillInfo.put("skillMdText", content);
                            
                        // 解析md内容
                        parseSkillsMd(content, skillInfo);
                            
                        // 返回当前目录作为根目录
                        return currentDir.isEmpty() ? "." : currentDir;
                    } catch (Exception e) {
                        // 如果读取失败，继续查找
                        continue;
                    }
                }
            }
        }
            
        // 当前目录没有找到md文件，进入子目录继续查找
        Set<String> subDirs = new LinkedHashSet<>();
        for (ISimpleInArchiveItem item : allItems) {
            if (item.isFolder()) {
                String path = item.getPath();
                // 统一路径分隔符为/
                path = path.replace("\\", "/");
                // 确保路径以/结尾
                if (!path.endsWith("/")) {
                    path = path + "/";
                }
                    
                // 检查是否是当前目录的直接子目录
                if (currentDir.isEmpty()) {
                    // 根目录下的直接子目录（不包含/）
                    if (!path.substring(0, path.length() - 1).contains("/")) {
                        subDirs.add(path.substring(0, path.length() - 1));
                    }
                } else {
                    // 当前目录下的直接子目录
                    if (path.startsWith(currentDir + "/")) {
                        String relativePath = path.substring(currentDir.length() + 1);
                        if (!relativePath.contains("/")) {
                            subDirs.add(currentDir + "/" + relativePath.substring(0, relativePath.length() - 1));
                        }
                    }
                }
            }
        }
            
        // 递归检查每个子目录
        for (String subDir : subDirs) {
            String result = findMdFileRecursively(allItems, subDir, skillInfo);
            if (result != null) {
                return result;
            }
        }
            
        // 所有子目录都没有找到md文件
        return null;
    }
    /**
     * 从rar文件生成技能包结构
     * @param rarFilePath rar文件路径
     * @param skillName 技能包名称
     * @param skillDescription 技能包描述
     * @param skillTags 技能包标签
     * @param author 作者
     * @return 技能包结构
     * @throws IOException 解析过程中的IO异常
     * @throws Exception 解析过程中的异常
     */
    private static Map<String, Object> generateSkillStructureFromRar(String rarFilePath, String skillName, String skillDescription, List<String> skillTags, String author) throws IOException, SevenZipException {
        // 验证文件是否存在
        File rarFile = new File(rarFilePath);
        if (!rarFile.exists()) {
            throw new FileNotFoundException("RAR file not found: " + rarFilePath);
        }
        if (!rarFile.canRead()) {
            throw new IOException("Cannot read RAR file: " + rarFilePath);
        }
            
        Map<String, Object> skillStructure = new LinkedHashMap<>();
            
        // 核心概要
        skillStructure.put("name", skillName);
        skillStructure.put("version", "1.0.0");
        skillStructure.put("description", skillDescription);
        skillStructure.put("author", author);
        skillStructure.put("created", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        skillStructure.put("tags", skillTags);
            
        // 核心节点 structure
        Map<String, Object> structure = new LinkedHashMap<>();
        structure.put("name", skillName);
        structure.put("type", "directory");
        structure.put("path", ".");
        structure.put("format", "directory");
        structure.put("description", skillDescription);
            
        // 构建目录树结构
        List<Map<String, Object>> children = new ArrayList<>();
        Map<String, Map<String, Object>> directoryMap = new HashMap<>();
            
        // 一次性读取所有条目并处理
        try (RandomAccessFile randomAccessFile = new RandomAccessFile(rarFile, "r");
             IInArchive archive = SevenZip.openInArchive(null, new RandomAccessFileInStream(randomAccessFile))) {
            // 使用简单接口
            ISimpleInArchive simpleInArchive = archive.getSimpleInterface();
            ISimpleInArchiveItem[] archiveItems = simpleInArchive.getArchiveItems();
            
            // 首先处理所有目录
            for (ISimpleInArchiveItem item : archiveItems) {
                if (item.isFolder()) {
                    String path = item.getPath();
                    // 确保路径以/结尾，与 zip 处理一致
                    if (!path.endsWith("\\")) {
                        path = path + "\\";
                    }
                    String[] pathParts = path.split("\\\\");
                    createDirectoryTree(children, directoryMap, pathParts, path);
                }
            }
                
            // 然后处理所有文件
            for (ISimpleInArchiveItem item : archiveItems) {
                if (!item.isFolder()) {
                    String path = item.getPath();
                    String[] pathParts = path.split("\\\\");
                    String fileName = pathParts[pathParts.length - 1];
                    
                    // 读取文件内容
                    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
                    item.extractSlow(data -> {
                        try {
                            outputStream.write(data);
                        } catch (IOException e) {
                            throw new RuntimeException(e);
                        }
                        return data.length;
                    });
                    
                    String fileContent = outputStream.toString(StandardCharsets.UTF_8);
                    addFileToTreeFromRar(children, directoryMap, pathParts, fileName, fileContent, path);
                }
            }
        }
        structure.put("children", children);
        skillStructure.put("structure", structure);
        return skillStructure;
    }
    
    /**
     * 将 rar 文件添加到目录树中
     * @param children 子节点列表
     * @param directoryMap 目录映射
     * @param pathParts 路径部分
     * @param fileName 文件名
     * @param fileContent 文件内容
     * @param filePath 文件路径
     * @throws IOException 读取文件内容时的 IO 异常
     */
    private static void addFileToTreeFromRar(List<Map<String, Object>> children, Map<String, Map<String, Object>> directoryMap, String[] pathParts, String fileName, String fileContent, String filePath) throws IOException {
        if (pathParts.length == 0) return;
        
        // 构建目录路径
        StringBuilder directoryPath = new StringBuilder();
        for (int i = 0; i < pathParts.length - 1; i++) {
            String part = pathParts[i];
            if (!part.isEmpty()) {
                directoryPath.append(part).append("/");
            }
        }
        
        // 找到文件所在的目录节点
        List<Map<String, Object>> targetChildren = children;
        if (directoryPath.length() > 0) {
            Map<String, Object> directoryNode = directoryMap.get(directoryPath.toString());
            if (directoryNode != null) {
                targetChildren = (List<Map<String, Object>>) directoryNode.get("children");
            }
        }
        
        // 创建文件节点并添加到目标目录
        Map<String, Object> fileNode = createFileNodeFromRar(fileName, fileContent, filePath);
        targetChildren.add(fileNode);
    }
    
    /**
     * 从文件信息创建文件节点
     * @param fileName 文件名
     * @param fileContent 文件内容
     * @param filePath 文件路径
     * @return 文件节点
     * @throws IOException 读取文件内容时的 IO 异常
     */
    private static Map<String, Object> createFileNodeFromRar(String fileName, String fileContent, String filePath) throws IOException {
        Map<String, Object> fileNode = new LinkedHashMap<>();
        
        fileNode.put("name", fileName);
        fileNode.put("type", "file");
        fileNode.put("path", "/"+filePath.toString().replaceAll("\\\\","/"));
        fileNode.put("format", getFileFormat(fileName));
        fileNode.put("description", fileName + " file");

        if (fileName.endsWith(".md")){
            fileNode.put("content", EscapeCharacterUtils.removeEscapeCharacters(fileContent,true));
        }else {
            fileNode.put("content", fileContent);
        }

        return fileNode;
    }

    /**
     * 将读取到得md文件进行yaml格式化
     * @return 目录节点
     */
    private static String convertMdToCleanYaml(String mdContent) throws IOException {

        // 2. 提取顶部 FrontMatter（--- 之间的内容）
        Matcher matcher = FRONT_MATTER_PATTERN.matcher(mdContent);
        String frontMatter = "";
        String bodyContent = mdContent;

        if (matcher.find()) {
            frontMatter = matcher.group(1).trim();
            // 截取正文（去掉 FrontMatter）
            bodyContent = mdContent.substring(matcher.end()).trim();
        }

        // 3. 构建最终 YAML（正文使用 | 保留换行，无任何转义）
        StringBuilder yaml = new StringBuilder();
        yaml.append("---\n");
        yaml.append(frontMatter).append("\n");
        yaml.append("content: |\n");

        // 正文每一行前面缩进 2 格（YAML 多行文本规范）
        String[] lines = bodyContent.split("\\r?\\n");
        for (String line : lines) {
            yaml.append("  ").append(line).append("\n");
        }

        yaml.append("---");
        return yaml.toString();
    }
    
    /**
     * 生成技能包结构
     * @param zipFile zip文件对象
     * @param skillName 技能包名称
     * @param skillDescription 技能包描述
     * @param skillTags 技能包标签
     * @param author 作者
     * @return 技能包结构
     * @throws IOException 解析过程中的IO异常
     */
    private static Map<String, Object> generateSkillStructure(ZipFile zipFile, String skillName, String skillDescription, List<String> skillTags, String author) throws IOException {
        Map<String, Object> skillStructure = new LinkedHashMap<>();
        
        // 核心概要
        skillStructure.put("name", skillName);
        skillStructure.put("version", "1.0.0");
        skillStructure.put("description", skillDescription);
        skillStructure.put("author", author);
        skillStructure.put("created", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        skillStructure.put("tags", skillTags);
        
        // 核心节点structure
        Map<String, Object> structure = new LinkedHashMap<>();
        structure.put("name", skillName);
        structure.put("type", "directory");
        structure.put("path", ".");
        structure.put("format", "directory");
        structure.put("description", skillDescription);
        
        // 构建目录树结构
        List<Map<String, Object>> children = new ArrayList<>();
        Map<String, Map<String, Object>> directoryMap = new HashMap<>();
        
        // 首先处理所有目录
        Enumeration<? extends ZipEntry> entries = zipFile.entries();
        while (entries.hasMoreElements()) {
            ZipEntry entry = entries.nextElement();
            if (entry.isDirectory()) {
                String path = entry.getName();
                String[] pathParts = path.split("/");
                createDirectoryTree(children, directoryMap, pathParts, path);
            }
        }
        
        // 然后处理所有文件
        entries = zipFile.entries();
        while (entries.hasMoreElements()) {
            ZipEntry entry = entries.nextElement();
            if (!entry.isDirectory()) {
                String path = entry.getName();
                String[] pathParts = path.split("/");
                addFileToTree(children, directoryMap, pathParts, entry, zipFile);
            }
        }
        structure.put("children", children);
        skillStructure.put("structure", structure);
        return skillStructure;
    }
    
    /**
     * 创建目录树结构
     * @param children 子节点列表
     * @param directoryMap 目录映射
     * @param pathParts 路径部分
     * @param fullPath 完整路径
     */
    private static void createDirectoryTree(List<Map<String, Object>> children, Map<String, Map<String, Object>> directoryMap, String[] pathParts, String fullPath) {
        List<Map<String, Object>> currentChildren = children;
        StringBuilder currentPath = new StringBuilder();
        
        for (int i = 0; i < pathParts.length; i++) {
            String part = pathParts[i];
            if (part.isEmpty()) continue;
            
            currentPath.append(part).append("/");
            String pathKey = currentPath.toString();
            
            // 检查当前目录是否已存在
            Map<String, Object> directoryNode = directoryMap.get(pathKey);
            if (directoryNode == null) {
                // 创建新目录节点
                directoryNode = new LinkedHashMap<>();
                directoryNode.put("name", part);
                directoryNode.put("type", "directory");
                directoryNode.put("path", "/"+pathKey);
                directoryNode.put("format", "directory");
                directoryNode.put("description", part + " directory");
                directoryNode.put("children", new ArrayList<>());
                
                // 添加到当前子节点列表
                currentChildren.add(directoryNode);
                directoryMap.put(pathKey, directoryNode);
            }
            
            // 进入下一级目录
            currentChildren = (List<Map<String, Object>>) directoryNode.get("children");
        }
    }
    
    /**
     * 将文件添加到目录树中
     * @param children 子节点列表
     * @param directoryMap 目录映射
     * @param pathParts 路径部分
     * @param entry zip条目
     * @param zipFile zip文件对象
     * @throws IOException 读取文件内容时的IO异常
     */
    private static void addFileToTree(List<Map<String, Object>> children, Map<String, Map<String, Object>> directoryMap, String[] pathParts, ZipEntry entry, ZipFile zipFile) throws IOException {
        if (pathParts.length == 0) return;
        
        // 获取文件名
        String fileName = pathParts[pathParts.length - 1];
        
        // 构建目录路径
        StringBuilder directoryPath = new StringBuilder("/");
        for (int i = 0; i < pathParts.length - 1; i++) {
            String part = pathParts[i];
            if (!part.isEmpty()) {
                directoryPath.append(part).append("/");
            }
        }
        
        // 找到文件所在的目录节点
        List<Map<String, Object>> targetChildren = children;
        if (directoryPath.length() > 0) {
            Map<String, Object> directoryNode = directoryMap.get(directoryPath.toString().substring(1));
            if (directoryNode != null) {
                targetChildren = (List<Map<String, Object>>) directoryNode.get("children");
            }
        }
        
        // 创建文件节点并添加到目标目录
        Map<String, Object> fileNode = createFileNode(entry, zipFile);
        targetChildren.add(fileNode);
    }

    /**
     * 创建目录节点
     * @param entry zip条目
     * @param zipFile zip文件对象
     * @return 目录节点
     */
    private static Map<String, Object> createDirectoryNode(ZipEntry entry, ZipFile zipFile) {
        Map<String, Object> directoryNode = new LinkedHashMap<>();
        String name = entry.getName().replaceAll("/$", "");
        name = name.substring(name.lastIndexOf("/") + 1);
        
        directoryNode.put("name", name);
        directoryNode.put("type", "directory");
        directoryNode.put("path", entry.getName());
        directoryNode.put("format", "directory");
        directoryNode.put("description", name + " directory");
        directoryNode.put("children", new ArrayList<>());
        
        return directoryNode;
    }

    /**
     * 创建文件节点
     * @param entry zip条目
     * @param zipFile zip文件对象
     * @return 文件节点
     * @throws IOException 读取文件内容时的IO异常
     */
    private static Map<String, Object> createFileNode(ZipEntry entry, ZipFile zipFile) throws IOException {
        Map<String, Object> fileNode = new LinkedHashMap<>();
        String name = entry.getName().substring(entry.getName().lastIndexOf("/") + 1);
        
        fileNode.put("name", name);
        fileNode.put("type", "file");
        fileNode.put("path", "/"+entry.getName().replaceAll("\\\\","/"));
        fileNode.put("format", getFileFormat(name));
        fileNode.put("description", name + " file");
        
        // 读取文件内容
        try (InputStream inputStream = zipFile.getInputStream(entry);
             BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8))) {
            StringBuilder content = new StringBuilder();
            String line;
            while ((line = reader.readLine()) != null) {
                content.append(line).append("\n");
            }
            fileNode.put("content", content.toString());
        }
        
        return fileNode;
    }

    /**
     * 创建skills.md文件节点
     * @param skillName 技能包名称
     * @param skillDescription 技能包描述
     * @param skillTags 技能包标签
     * @return skills.md文件节点
     */
    private static Map<String, Object> createSkillsMdNode(String skillName, String skillDescription, List<String> skillTags) {
        Map<String, Object> skillsMdNode = new LinkedHashMap<>();
        
        skillsMdNode.put("name", "skills.md");
        skillsMdNode.put("type", "file");
        skillsMdNode.put("path", "skills.md");
        skillsMdNode.put("format", "markdown");
        skillsMdNode.put("description", "Skills metadata file");
        
        // 生成skills.md内容
        StringBuilder content = new StringBuilder();
        content.append("# " + skillName).append("\n\n");
        content.append("## Description").append("\n");
        content.append(skillDescription).append("\n\n");
        content.append("## Tags").append("\n");
        if (skillTags != null && !skillTags.isEmpty()) {
            for (String tag : skillTags) {
                content.append("- " + tag).append("\n");
            }
        } else {
            content.append("- general\n").append("- skill\n");
        }
        content.append("\n");
        content.append("## Usage").append("\n");
        content.append("This skill provides functionality for " + skillName).append("\n");
        
        skillsMdNode.put("content", content.toString());
        
        return skillsMdNode;
    }

    /**
     * 创建scripts目录节点
     * @return scripts目录节点
     */
    private static Map<String, Object> createScriptsDirNode() {
        Map<String, Object> scriptsDirNode = new LinkedHashMap<>();
        
        scriptsDirNode.put("name", "scripts");
        scriptsDirNode.put("type", "directory");
        scriptsDirNode.put("path", "scripts/");
        scriptsDirNode.put("format", "directory");
        scriptsDirNode.put("description", "Scripts directory");
        
        // 添加示例脚本
        List<Map<String, Object>> scriptChildren = new ArrayList<>();
        
        // 示例Python脚本
        Map<String, Object> pythonScriptNode = new LinkedHashMap<>();
        pythonScriptNode.put("name", "example.py");
        pythonScriptNode.put("type", "file");
        pythonScriptNode.put("path", "scripts/example.py");
        pythonScriptNode.put("format", "python");
        pythonScriptNode.put("description", "Example Python script");
        pythonScriptNode.put("content", "#!/usr/bin/env python3\n" +
                "\"\"\"\n" +
                "Example script for " + "skill" + "\n" +
                "\"\"\"\n\n" +
                "def main():\n" +
                "    print('Hello from skill script!')\n\n" +
                "if __name__ == '__main__':\n" +
                "    main()\n");
        scriptChildren.add(pythonScriptNode);
        
        scriptsDirNode.put("children", scriptChildren);
        
        return scriptsDirNode;
    }

    /**
     * 获取文件格式
     * @param fileName 文件名
     * @return 文件格式
     */
    private static String getFileFormat(String fileName) {
        if (fileName.endsWith(".md")) {
            return "markdown";
        } else if (fileName.endsWith(".py")) {
            return "python";
        } else if (fileName.endsWith(".js")) {
            return "javascript";
        } else if (fileName.endsWith(".json")) {
            return "json";
        } else if (fileName.endsWith(".yaml") || fileName.endsWith(".yml")) {
            return "yaml";
        } else if (fileName.endsWith(".txt")) {
            return "text";
        } else if (fileName.endsWith(".sh")) {
            return "shell";
        } else {
            return "other";
        }
    }

    /**
     * 生成yaml
     * @param skillStructure 技能包结构
     * @return 生成的yaml描述
     */
    private static String generateYaml(Map<String, Object> skillStructure) {
        DumperOptions options = new DumperOptions();
        options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
        options.setIndent(2);
        options.setPrettyFlow(true);
        
        Yaml yaml = new Yaml(options);
        return yaml.dump(skillStructure);
    }

}