import { access, readFile, stat } from "node:fs/promises";
import { glob } from "glob";
import { resolve } from "node:path";
import { addResource, getTargetMap } from "./package-manager-resource-accumulator.js";
import { collectResourceFiles } from "./package-manager-resource-files.js";
import { conventionDirsForResource, getManifestFromPackageJson, manifestEntriesForResource } from "./package-manager-manifest.js";
import { applyPatterns, hasGlobPattern, isOverridePattern, splitPatterns } from "./package-manager-resource-patterns.js";
import { resolvePathFromBase } from "./package-manager-paths.js";
async function exists(path) {
    try {
        await access(path);
        return true;
    }
    catch {
        return false;
    }
}
async function readPiManifest(packageRoot) {
    try {
        const content = await readFile(resolve(packageRoot, "package.json"), "utf-8");
        return getManifestFromPackageJson(JSON.parse(content));
    }
    catch {
        return null;
    }
}
export async function collectPackageResources(packageRoot, accumulator, filter, metadata) {
    if (filter) {
        for (const resourceType of ["extensions", "skills", "prompts", "themes", "workflows"]) {
            const patterns = filter[resourceType];
            const target = getTargetMap(accumulator, resourceType);
            if (patterns !== undefined)
                await applyPackageFilter(packageRoot, patterns, resourceType, target, metadata);
            else
                await collectDefaultResources(packageRoot, resourceType, target, metadata);
        }
        return true;
    }
    const manifest = await readPiManifest(packageRoot);
    if (manifest) {
        for (const resourceType of ["extensions", "skills", "prompts", "themes", "workflows"]) {
            const entries = manifestEntriesForResource(manifest, resourceType);
            if (entries !== undefined) {
                await addManifestEntries(entries, packageRoot, resourceType, getTargetMap(accumulator, resourceType), metadata);
                continue;
            }
            if (resourceType === "workflows")
                await collectDefaultResources(packageRoot, resourceType, getTargetMap(accumulator, resourceType), metadata);
        }
        return true;
    }
    let hasAnyDir = false;
    for (const resourceType of ["extensions", "skills", "prompts", "themes", "workflows"]) {
        for (const dir of conventionDirsForResource(packageRoot, resourceType)) {
            if (!(await exists(dir)))
                continue;
            for (const f of await collectResourceFiles(dir, resourceType))
                addResource(getTargetMap(accumulator, resourceType), f, metadata, true);
            hasAnyDir = true;
        }
    }
    return hasAnyDir;
}
async function collectDefaultResources(packageRoot, resourceType, target, metadata) {
    const manifest = await readPiManifest(packageRoot);
    const entries = manifestEntriesForResource(manifest, resourceType);
    if (entries !== undefined) {
        await addManifestEntries(entries, packageRoot, resourceType, target, metadata);
        return;
    }
    for (const dir of conventionDirsForResource(packageRoot, resourceType)) {
        if (!(await exists(dir)))
            continue;
        for (const f of await collectResourceFiles(dir, resourceType))
            addResource(target, f, metadata, true);
    }
}
async function applyPackageFilter(packageRoot, userPatterns, resourceType, target, metadata) {
    const { allFiles } = await collectManifestFiles(packageRoot, resourceType);
    if (userPatterns.length === 0) {
        for (const f of allFiles)
            addResource(target, f, metadata, false);
        return;
    }
    const enabledByUser = applyPatterns(allFiles, userPatterns, packageRoot);
    for (const f of allFiles)
        addResource(target, f, metadata, enabledByUser.has(f));
}
async function collectManifestFiles(packageRoot, resourceType) {
    const manifest = await readPiManifest(packageRoot);
    const entries = manifestEntriesForResource(manifest, resourceType);
    if (entries && entries.length > 0) {
        const allFiles = await collectFilesFromManifestEntries(entries, packageRoot, resourceType);
        const manifestPatterns = entries.filter(isOverridePattern);
        const enabledByManifest = manifestPatterns.length > 0 ? applyPatterns(allFiles, manifestPatterns, packageRoot) : new Set(allFiles);
        return { allFiles: Array.from(enabledByManifest), enabledByManifest };
    }
    const allFiles = [];
    for (const dir of conventionDirsForResource(packageRoot, resourceType)) {
        if (await exists(dir))
            allFiles.push(...await collectResourceFiles(dir, resourceType));
    }
    return { allFiles, enabledByManifest: new Set(allFiles) };
}
async function addManifestEntries(entries, root, resourceType, target, metadata) {
    if (!entries)
        return;
    const allFiles = await collectFilesFromManifestEntries(entries, root, resourceType);
    const patterns = entries.filter(isOverridePattern);
    const enabledPaths = applyPatterns(allFiles, patterns, root);
    for (const f of allFiles)
        if (enabledPaths.has(f))
            addResource(target, f, metadata, true);
}
async function collectFilesFromManifestEntries(entries, root, resourceType) {
    const resolved = [];
    for (const entry of entries.filter((entry) => !isOverridePattern(entry))) {
        if (!hasGlobPattern(entry))
            resolved.push(resolve(root, entry));
        else
            resolved.push(...(await glob(entry, { cwd: root, absolute: true, dot: false, nodir: false })).map((match) => resolve(match)));
    }
    return collectFilesFromPaths(resolved, resourceType);
}
export async function resolveLocalEntries(entries, resourceType, target, metadata, baseDir) {
    if (entries.length === 0)
        return;
    const { plain, patterns } = splitPatterns(entries);
    const resolvedPlain = plain.map((p) => resolvePathFromBase(p, baseDir));
    const allFiles = await collectFilesFromPaths(resolvedPlain, resourceType);
    const enabledPaths = applyPatterns(allFiles, patterns, baseDir);
    for (const f of allFiles)
        addResource(target, f, metadata, enabledPaths.has(f));
}
export async function collectFilesFromPaths(paths, resourceType) {
    const files = [];
    for (const p of paths) {
        if (!(await exists(p)))
            continue;
        try {
            const stats = await stat(p);
            if (stats.isFile())
                files.push(p);
            else if (stats.isDirectory())
                files.push(...await collectResourceFiles(p, resourceType));
        }
        catch { }
    }
    return files;
}
//# sourceMappingURL=package-manager-resource-collector.js.map