import { readFile, stat } from "node:fs/promises";
import { join } from "node:path";
const COMPLETE_MAX_FILES = 80;
const COMPLETE_MAX_BYTES_PER_FILE = 96 * 1024;
const COMPLETE_MAX_TOTAL_BYTES = 768 * 1024;
const LITE_MAX_FILES = 24;
const LITE_MAX_BYTES_PER_FILE = 48 * 1024;
const LITE_MAX_TOTAL_BYTES = 192 * 1024;
const CONFIG_NAMES = new Set([
    "vite.config.ts",
    "vite.config.js",
    "tsconfig.json",
    "eslint.config.js",
    "tauri.conf.json",
    "wrangler.toml",
]);
export async function collectThreadSuiteEvidencePack(cwd, inventory, options) {
    const limits = options.profile === "lite"
        ? { maxFiles: LITE_MAX_FILES, maxBytesPerFile: LITE_MAX_BYTES_PER_FILE, maxTotalBytes: LITE_MAX_TOTAL_BYTES }
        : {
            maxFiles: COMPLETE_MAX_FILES,
            maxBytesPerFile: COMPLETE_MAX_BYTES_PER_FILE,
            maxTotalBytes: COMPLETE_MAX_TOTAL_BYTES,
        };
    const skipped = [...inventory.skipped];
    const candidatePaths = prioritizeEvidencePaths(inventory);
    const items = [];
    let totalBytes = 0;
    for (const candidate of candidatePaths) {
        if (items.length >= limits.maxFiles) {
            skipped.push({ path: candidate.path, reason: "evidence file limit reached" });
            continue;
        }
        const absolutePath = join(cwd, candidate.path);
        const stats = await safeStat(absolutePath);
        if (!stats) {
            skipped.push({ path: candidate.path, reason: "evidence file unreadable" });
            continue;
        }
        if (totalBytes >= limits.maxTotalBytes) {
            skipped.push({ path: candidate.path, reason: "evidence total byte limit reached" });
            continue;
        }
        const raw = await safeReadFile(absolutePath);
        if (raw === undefined) {
            skipped.push({ path: candidate.path, reason: "evidence file unreadable" });
            continue;
        }
        const remainingBytes = limits.maxTotalBytes - totalBytes;
        const maxBytes = Math.min(limits.maxBytesPerFile, remainingBytes);
        const content = truncateUtf8(raw, maxBytes);
        const sizeBytes = Buffer.byteLength(content, "utf-8");
        totalBytes += sizeBytes;
        items.push({
            path: candidate.path,
            kind: candidate.kind,
            content,
            sizeBytes: stats.size,
            truncated: stats.size > sizeBytes,
        });
    }
    return {
        cwd,
        createdAt: new Date().toISOString(),
        items,
        skipped,
        totalBytes,
        coverage: summarizeCoverage(items),
        limits,
    };
}
function prioritizeEvidencePaths(inventory) {
    const candidates = [];
    for (const manifest of inventory.manifests)
        candidates.push({ path: manifest.path, kind: "manifest", priority: 0 });
    for (const document of inventory.documents)
        candidates.push({ path: document.path, kind: docKind(document.path), priority: docPriority(document.path) });
    for (const root of inventory.sourceRoots) {
        for (const entrypoint of likelyEntrypoints(root))
            candidates.push({ path: entrypoint, kind: "entrypoint", priority: 2 });
        for (const config of CONFIG_NAMES)
            candidates.push({ path: `${root}/${config}`, kind: "config", priority: 4 });
    }
    for (const continuity of inventory.continuityFiles)
        candidates.push({ path: continuity.path, kind: "continuity", priority: 5 });
    for (const adr of inventory.adrFiles)
        candidates.push({ path: adr.path, kind: "adr", priority: 6 });
    const seen = new Set();
    return candidates
        .filter((candidate) => {
        if (seen.has(candidate.path))
            return false;
        seen.add(candidate.path);
        return true;
    })
        .sort((a, b) => a.priority - b.priority || a.path.localeCompare(b.path));
}
function docKind(path) {
    if (path.startsWith("docs/adr/"))
        return "adr";
    return "doc";
}
function docPriority(path) {
    if (/package\.json$|Cargo\.toml$|pyproject\.toml$|go\.mod$/i.test(path))
        return 0;
    if (/README\.md$/i.test(path))
        return 1;
    if (/PROJECT_PLAN\.md$|_PLAN\.md$/i.test(path))
        return 1;
    if (/^docs\//i.test(path) && !/^docs\/adr\//i.test(path))
        return 3;
    if (/CONTEXT\.md$/i.test(path))
        return 4;
    return 5;
}
function summarizeCoverage(items) {
    return {
        manifestCount: items.filter((item) => item.kind === "manifest").length,
        documentCount: items.filter((item) => item.kind === "doc").length,
        entrypointCount: items.filter((item) => item.kind === "entrypoint").length,
        configCount: items.filter((item) => item.kind === "config").length,
        continuityCount: items.filter((item) => item.kind === "continuity").length,
        adrCount: items.filter((item) => item.kind === "adr").length,
        truncatedCount: items.filter((item) => item.truncated).length,
    };
}
function likelyEntrypoints(root) {
    return [
        `${root}/main.ts`,
        `${root}/main.js`,
        `${root}/index.ts`,
        `${root}/index.js`,
        `${root}/src/main.ts`,
        `${root}/src/main.js`,
        `${root}/src/index.ts`,
        `${root}/src/index.js`,
        `${root}/src/lib.rs`,
        `${root}/src/main.rs`,
    ];
}
async function safeStat(path) {
    try {
        return await stat(path);
    }
    catch {
        return undefined;
    }
}
async function safeReadFile(path) {
    try {
        return await readFile(path, "utf-8");
    }
    catch {
        return undefined;
    }
}
function truncateUtf8(value, maxBytes) {
    if (Buffer.byteLength(value, "utf-8") <= maxBytes)
        return value;
    let end = Math.min(value.length, maxBytes);
    while (Buffer.byteLength(value.slice(0, end), "utf-8") > maxBytes && end > 0)
        end -= 1;
    return value.slice(0, end);
}
//# sourceMappingURL=evidence-pack.js.map