package com.microservices.zone.resource.service.impl;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.microservices.common.core.constant.SecurityConstants;
import com.microservices.common.core.exception.ServiceException;
import com.microservices.common.core.utils.StringUtils;
import com.microservices.system.api.RemoteFileService;
import com.microservices.system.api.domain.SysFile;
import com.microservices.system.api.utils.FeignUtils;
import com.microservices.zone.resource.domain.vo.AiSkillParseResultVo;
import com.microservices.zone.resource.service.IAiSkillParseService;
import com.microservices.zone.utils.ZoneConstants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

/**
 * Skill ZIP解析服务实现
 */
@Service
public class AiSkillParseServiceImpl implements IAiSkillParseService {

    private static final Logger logger = LoggerFactory.getLogger(AiSkillParseServiceImpl.class);
    private static final String SKILL_MD_FILE = "SKILL.md";

    private final RemoteFileService remoteFileService;

    public AiSkillParseServiceImpl(RemoteFileService remoteFileService) {
        this.remoteFileService = remoteFileService;
    }

    @Override
    public AiSkillParseResultVo parseSkillZip(MultipartFile zipFile) {
        // 1. 校验文件大小
        if (zipFile.getSize() > ZoneConstants.SKILL_ZIP_MAX_SIZE) {
            throw new ServiceException("ZIP包大小不能超过10MB");
        }

        // 2. 校验文件格式
        String originalFilename = zipFile.getOriginalFilename();
        if (originalFilename == null || !originalFilename.toLowerCase().endsWith(".zip")) {
            throw new ServiceException("仅支持ZIP格式文件");
        }

        try (ZipInputStream zis = new ZipInputStream(zipFile.getInputStream(), StandardCharsets.UTF_8)) {
            ZipEntry entry;
            String skillMdContent = null;
            List<FileTreeNode> fileTreeNodes = new ArrayList<>();

            while ((entry = zis.getNextEntry()) != null) {
                String entryName = entry.getName();
                if (entry.isDirectory()) {
                    continue;
                }
                // 防止路径遍历攻击
                if (entryName.contains("..")) {
                    throw new ServiceException("ZIP包中包含非法路径");
                }
                // 提取 SKILL.md（在任意层级下查找）
                String fileName = new File(entryName).getName();
                if (SKILL_MD_FILE.equalsIgnoreCase(fileName)) {
                    skillMdContent = readEntryContent(zis);
                }
                // 收集文件信息构建目录树
                fileTreeNodes.add(new FileTreeNode(entryName, entry.getSize()));
            }

            // 3. 校验 SKILL.md 存在性
            if (skillMdContent == null) {
                throw new ServiceException("ZIP包中必须包含 SKILL.md 文件");
            }

            // 4. 校验 SKILL.md 内容长度
            if (skillMdContent.trim().length() < ZoneConstants.SKILL_MD_MIN_LENGTH) {
                throw new ServiceException("SKILL.md 内容不得少于" + ZoneConstants.SKILL_MD_MIN_LENGTH + "字");
            }

            // 5. 构建目录树 JSON
            JSONObject fileTreeJson = buildFileTreeJson(fileTreeNodes);

            AiSkillParseResultVo result = new AiSkillParseResultVo();
            result.setSkillMdContent(skillMdContent);
            result.setFileTreeJson(fileTreeJson.toJSONString());

            // 从 YAML front matter 中提取 description 字段
            String description = extractDescription(skillMdContent);
            result.setSummary(description);

            // 解析成功后，自动上传ZIP文件到File微服务（上传失败则阻断整个接口）
            SysFile sysFile = FeignUtils.getReturnData(
                    remoteFileService.upload(zipFile, "ai-resource", "skill", SecurityConstants.INNER)
            );
            if (sysFile == null || StringUtils.isEmpty(sysFile.getFileIdentifier())) {
                throw new ServiceException("文件上传返回为空，请重试");
            }
            result.setFileId(sysFile.getFileId());

            return result;

        } catch (ServiceException e) {
            throw e;
        } catch (IOException e) {
            logger.error("ZIP包解析失败", e);
            throw new ServiceException("ZIP包解析失败：" + e.getMessage());
        }
    }

    private String readEntryContent(ZipInputStream zis) throws IOException {
        StringBuilder sb = new StringBuilder();
        byte[] buffer = new byte[4096];
        int len;
        while ((len = zis.read(buffer)) > 0) {
            sb.append(new String(buffer, 0, len, StandardCharsets.UTF_8));
        }
        return sb.toString();
    }

    private JSONObject buildFileTreeJson(List<FileTreeNode> nodes) {
        // 构建树形结构的目录
        JSONObject root = new JSONObject();
        root.put("name", "root");
        root.put("type", "folder");
        JSONArray rootChildren = new JSONArray();
        root.put("children", rootChildren);

        for (FileTreeNode node : nodes) {
            String[] parts = node.path.split("/");
            JSONArray currentChildren = rootChildren;

            for (int i = 0; i < parts.length; i++) {
                String part = parts[i];
                if (StringUtils.isEmpty(part)) {
                    continue;
                }
                boolean isFile = (i == parts.length - 1);

                if (isFile) {
                    JSONObject fileNode = new JSONObject();
                    fileNode.put("name", part);
                    fileNode.put("type", "file");
                    fileNode.put("size", node.size);
                    currentChildren.add(fileNode);
                } else {
                    // 查找是否已存在该文件夹
                    JSONObject existingFolder = null;
                    for (int j = 0; j < currentChildren.size(); j++) {
                        JSONObject child = currentChildren.getJSONObject(j);
                        if (part.equals(child.get("name")) && "folder".equals(child.get("type"))) {
                            existingFolder = child;
                            break;
                        }
                    }

                    if (existingFolder == null) {
                        existingFolder = new JSONObject();
                        existingFolder.put("name", part);
                        existingFolder.put("type", "folder");
                        existingFolder.put("children", new ArrayList<JSONObject>());
                        currentChildren.add(existingFolder);
                    }
                    currentChildren = existingFolder.getJSONArray("children");
                }
            }
        }

        // 如果根目录只有一个子文件夹，直接返回该子文件夹
        JSONArray children = root.getJSONArray("children");
        if (children.size() == 1 && "folder".equals(children.getJSONObject(0).get("type"))) {
            return children.getJSONObject(0);
        }
        return root;
    }

    private static class FileTreeNode {
        final String path;
        final long size;

        FileTreeNode(String path, long size) {
            this.path = path;
            this.size = size;
        }
    }

    /**
     * 从 SKILL.md 内容中提取 description 字段
     *
     * @param skillMdContent SKILL.md 文件内容
     * @return description 内容，如果不存在则返回 null
     */
    private String extractDescription(String skillMdContent) {
        if (StringUtils.isEmpty(skillMdContent)) {
            return null;
        }

        // 查找 YAML front matter 边界
        String[] lines = skillMdContent.split("\\n");
        boolean inFrontMatter = false;
        boolean foundStart = false;

        for (String line : lines) {
            String trimmed = line.trim();

            // 检测 front matter 开始
            if (!foundStart && trimmed.equals("---")) {
                foundStart = true;
                inFrontMatter = true;
                continue;
            }

            // 检测 front matter 结束
            if (foundStart && trimmed.equals("---")) {
                break;
            }

            // 在 front matter 中查找 description
            if (inFrontMatter && trimmed.startsWith("description:")) {
                String desc = trimmed.substring("description:".length()).trim();
                // 处理引号包裹的情况
                if (desc.startsWith("\"") && desc.endsWith("\"")) {
                    return desc.substring(1, desc.length() - 1);
                }
                if (desc.startsWith("'") && desc.endsWith("'")) {
                    return desc.substring(1, desc.length() - 1);
                }
                return desc;
            }
        }

        return null;
    }
}
