// Test-only helpers for the discovery layer. Not exported from the package barrel —
// trust-8 (test-support naming) keeps production code from importing this module.
function toAbs(root, rel) {
    if (rel === "")
        return root;
    return root.endsWith("/") ? `${root}${rel}` : `${root}/${rel}`;
}
function entriesByPrefix(root, files, dirAbs) {
    const prefix = dirAbs === root ? `${root}/` : `${dirAbs}/`;
    const dirNames = new Set();
    const fileNames = new Set();
    for (const relPath of files.keys()) {
        const full = toAbs(root, relPath);
        if (!full.startsWith(prefix))
            continue;
        const rest = full.slice(prefix.length);
        const slash = rest.indexOf("/");
        if (slash === -1) {
            fileNames.add(rest);
        }
        else {
            dirNames.add(rest.slice(0, slash));
        }
    }
    const dirs = [...dirNames].map((name) => ({
        name,
        isDirectory: true,
        isFile: false,
        isSymbolicLink: false,
    }));
    const filesArr = [...fileNames].map((name) => ({
        name,
        isDirectory: false,
        isFile: true,
        isSymbolicLink: false,
    }));
    return [...dirs, ...filesArr];
}
function buildMap(files) {
    const encoder = new TextEncoder();
    const map = new Map();
    for (const f of files) {
        const bytes = typeof f.content === "string" ? encoder.encode(f.content) : f.content;
        const entry = f.realPathOverride !== undefined
            ? { content: bytes, realPathOverride: f.realPathOverride }
            : { content: bytes };
        map.set(f.relativePath, entry);
    }
    return map;
}
function memoryStat(root, map, findKey) {
    return (absolutePath) => {
        const key = findKey(absolutePath);
        if (key === undefined) {
            const hasChildren = [...map.keys()].some((k) => toAbs(root, k).startsWith(`${absolutePath}/`));
            if (hasChildren || absolutePath === root) {
                return { size: 0, isFile: false, isDirectory: true, isSymbolicLink: false };
            }
            throw new Error(`ENOENT: ${absolutePath}`);
        }
        return {
            size: map.get(key)?.content.byteLength ?? 0,
            isFile: true,
            isDirectory: false,
            isSymbolicLink: false,
        };
    };
}
export function memoryFs(root, files) {
    const map = buildMap(files);
    const findKey = (absolutePath) => {
        for (const key of map.keys()) {
            if (toAbs(root, key) === absolutePath)
                return key;
        }
        return undefined;
    };
    return {
        readFileUtf8: (absolutePath) => {
            const key = findKey(absolutePath);
            if (key === undefined)
                throw new Error(`ENOENT: ${absolutePath}`);
            return new TextDecoder("utf-8").decode(map.get(key)?.content ?? new Uint8Array());
        },
        stat: memoryStat(root, map, findKey),
        readDir: (absolutePath) => entriesByPrefix(root, map, absolutePath),
        realPath: (absolutePath) => {
            const key = findKey(absolutePath);
            const override = key === undefined ? undefined : map.get(key)?.realPathOverride;
            return override ?? absolutePath;
        },
        exists: (absolutePath) => findKey(absolutePath) !== undefined || absolutePath === root,
        readFileBytes: (absolutePath, maxBytes) => {
            const key = findKey(absolutePath);
            if (key === undefined)
                return Promise.reject(new Error(`ENOENT: ${absolutePath}`));
            const buf = map.get(key)?.content ?? new Uint8Array();
            const cap = Math.max(0, Math.floor(maxBytes));
            return Promise.resolve(buf.subarray(0, Math.min(buf.length, cap)));
        },
    };
}
export function folderScope(rootPath, options = {}) {
    const base = {
        kind: "folder",
        rootPath,
        recursive: options.recursive ?? true,
    };
    return {
        ...base,
        ...(options.includeGlobs !== undefined ? { includeGlobs: options.includeGlobs } : {}),
        ...(options.excludeGlobs !== undefined ? { excludeGlobs: options.excludeGlobs } : {}),
    };
}
