package com.easyagents.skill.util;

import com.easyagents.skill.model.Skill;
import com.easyagents.skill.model.SkillAsset;
import com.easyagents.skill.model.SkillMetadata;
import com.easyagents.skill.model.SkillReference;
import com.easyagents.skill.model.SkillResource;
import com.easyagents.skill.model.SkillResourceKind;
import com.easyagents.skill.model.SkillScript;
import com.easyagents.skill.model.SkillScriptLanguage;

import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Set;

/**
 * 通用 Skill 资源与旧资源视图之间的兼容适配工具。
 */
public final class SkillResources {

    private static final Set<String> TEXT_EXTENSIONS = Set.of(
            ".md", ".markdown", ".txt", ".json", ".yaml", ".yml", ".xml", ".csv", ".tsv",
            ".htm", ".html", ".css", ".properties", ".toml", ".ini", ".sql", ".java", ".kt", ".kts",
            ".py", ".js", ".mjs", ".cjs", ".ts", ".tsx", ".jsx", ".sh", ".bash", ".zsh",
            ".rb", ".go", ".rs", ".c", ".h", ".cpp", ".hpp", ".gradle", ".groovy"
    );

    private SkillResources() {
    }

    /**
     * 根据顶层目录识别资源语义类型。
     *
     * @param path Skill 根目录相对路径
     * @return 资源语义类型
     */
    public static SkillResourceKind classify(String path) {
        String topDirectory = SkillPaths.firstSegment(path);
        return switch (topDirectory) {
            case SkillPaths.REFERENCES_DIR -> SkillResourceKind.REFERENCE;
            case SkillPaths.SCRIPTS_DIR -> SkillResourceKind.SCRIPT;
            case SkillPaths.ASSETS_DIR -> SkillResourceKind.ASSET;
            case SkillPaths.EXAMPLES_DIR -> SkillResourceKind.EXAMPLE;
            default -> SkillResourceKind.OTHER;
        };
    }

    /**
     * 判断资源是否应按严格 UTF-8 文本处理。
     *
     * @param path 资源路径
     * @param kind 资源语义类型
     * @param mediaType 媒体类型
     * @return 文本资源时为 true
     */
    public static boolean isText(String path, SkillResourceKind kind, String mediaType) {
        if (kind == SkillResourceKind.SCRIPT) {
            return true;
        }
        if (kind == SkillResourceKind.ASSET) {
            return false;
        }
        if (mediaType != null && (mediaType.startsWith("text/")
                || mediaType.contains("json") || mediaType.contains("yaml")
                || mediaType.contains("xml") || mediaType.contains("javascript"))) {
            return true;
        }
        String lowerPath = path.toLowerCase(Locale.ROOT);
        return TEXT_EXTENSIONS.stream().anyMatch(lowerPath::endsWith);
    }

    /**
     * 获取 Skill 的正式通用资源；旧模型会被按需转换。
     *
     * @param skill Skill 聚合
     * @return 通用资源副本
     */
    public static List<SkillResource> canonicalResources(Skill skill) {
        if (skill == null) {
            return new ArrayList<>();
        }
        return new ArrayList<>(skill.getResources());
    }

    /**
     * 将尚未迁移的旧 references、scripts、assets 视图转换为正式通用资源。
     *
     * <p>该方法只读取旧视图，不读取或修改正式资源列表，由 {@link Skill#getResources()}
     * 在第一次正式访问时完成一次性迁移。</p>
     *
     * @param skill Skill 聚合
     * @return 从旧视图转换得到的通用资源副本
     */
    public static List<SkillResource> fromLegacyViews(Skill skill) {
        List<SkillResource> resources = new ArrayList<>();
        if (skill == null) {
            return resources;
        }
        if (skill.getReferences() != null) {
            for (SkillReference reference : skill.getReferences()) {
                SkillResource resource = base(reference.getPath(), SkillResourceKind.REFERENCE,
                        "text/markdown", reference.getContentHash(), reference.getSize(), reference.getMetadata());
                resource.setTextContent(reference.getContent());
                resources.add(resource);
            }
        }
        if (skill.getScripts() != null) {
            for (SkillScript script : skill.getScripts()) {
                SkillResource resource = base(script.getPath(), SkillResourceKind.SCRIPT,
                        "text/plain", script.getContentHash(), script.getSize(), script.getMetadata());
                resource.setTextContent(script.getContent());
                resources.add(resource);
            }
        }
        if (skill.getAssets() != null) {
            for (SkillAsset asset : skill.getAssets()) {
                SkillResource resource = base(asset.getPath(), SkillResourceKind.ASSET,
                        asset.getMediaType(), asset.getContentHash(), asset.getSize(), asset.getMetadata());
                resource.setContentRef(asset.getContentRef());
                resources.add(resource);
            }
        }
        return resources;
    }

    /**
     * 依据通用资源刷新旧 references、scripts、assets 兼容视图。
     *
     * @param skill Skill 聚合
     */
    public static void refreshLegacyViews(Skill skill) {
        List<SkillReference> references = new ArrayList<>();
        List<SkillScript> scripts = new ArrayList<>();
        List<SkillAsset> assets = new ArrayList<>();
        for (SkillResource resource : skill.getResources()) {
            if (resource.getKind() == SkillResourceKind.REFERENCE && resource.isText()) {
                SkillReference reference = new SkillReference();
                reference.setPath(resource.getPath());
                reference.setName(SkillPaths.fileName(resource.getPath()));
                reference.setContent(resource.getTextContent());
                reference.setContentHash(resource.getContentHash());
                reference.setSize(resource.getSize());
                reference.setMetadata(copy(resource.getMetadata()));
                references.add(reference);
            } else if (resource.getKind() == SkillResourceKind.SCRIPT && resource.isText()) {
                SkillScript script = new SkillScript();
                script.setPath(resource.getPath());
                script.setLanguage(SkillScriptLanguage.fromPath(resource.getPath()));
                script.setContent(resource.getTextContent());
                script.setContentHash(resource.getContentHash());
                script.setSize(resource.getSize());
                script.setMetadata(copy(resource.getMetadata()));
                scripts.add(script);
            } else if (resource.getKind() == SkillResourceKind.ASSET) {
                SkillAsset asset = new SkillAsset();
                asset.setPath(resource.getPath());
                asset.setName(SkillPaths.fileName(resource.getPath()));
                asset.setMediaType(resource.getMediaType());
                asset.setContentRef(resource.getContentRef());
                asset.setContentHash(resource.getContentHash());
                asset.setSize(resource.getSize());
                asset.setMetadata(copy(resource.getMetadata()));
                assets.add(asset);
            }
        }
        skill.setReferences(references);
        skill.setScripts(scripts);
        skill.setAssets(assets);
    }

    private static SkillResource base(String path, SkillResourceKind kind, String mediaType,
                                      String hash, long size, SkillMetadata metadata) {
        SkillResource resource = new SkillResource();
        resource.setPath(path);
        resource.setKind(kind);
        resource.setMediaType(mediaType);
        resource.setContentHash(hash);
        resource.setSize(size);
        resource.setMetadata(copy(metadata));
        return resource;
    }

    private static SkillMetadata copy(SkillMetadata metadata) {
        return metadata == null ? new SkillMetadata() : new SkillMetadata(metadata.getValues());
    }
}
