import { readFile } from "node:fs/promises";
import { dirname, join } from "node:path";
const IMPORTANT_DEPENDENCY_PATTERNS = [
    ["react", "ui"],
    ["vue", "ui"],
    ["svelte", "ui"],
    ["vite", "build"],
    ["webpack", "build"],
    ["typescript", "language"],
    ["vitest", "test"],
    ["jest", "test"],
    ["eslint", "lint"],
    ["clap", "cli"],
    ["tokio", "async-runtime"],
    ["serde", "serialization"],
    ["axum", "web"],
    ["actix", "web"],
];
export async function discoverManifestSemantics(cwd, inventory) {
    const commands = [];
    const dependencies = [];
    const frameworks = [];
    const architectureHints = [];
    let projectPurpose;
    for (const manifest of inventory.manifests.filter((manifest) => manifest.path.endsWith("package.json"))) {
        const facts = await parsePackageJson(cwd, manifest.path);
        commands.push(...facts.commands);
        dependencies.push(...facts.dependencies);
        frameworks.push(...facts.frameworks);
        architectureHints.push(...facts.architectureHints);
        projectPurpose = facts.projectPurpose ?? projectPurpose;
    }
    for (const manifest of inventory.manifests.filter((manifest) => manifest.path.endsWith("Cargo.toml"))) {
        const facts = await parseCargoToml(cwd, manifest.path);
        commands.push(...facts.commands);
        dependencies.push(...facts.dependencies);
        frameworks.push(...facts.frameworks);
        architectureHints.push(...facts.architectureHints);
        projectPurpose = projectPurpose ?? facts.projectPurpose;
    }
    return { projectPurpose, commands, dependencies, frameworks, architectureHints };
}
async function parsePackageJson(cwd, manifestPath) {
    try {
        const parsed = JSON.parse(await readFile(join(cwd, manifestPath), "utf-8"));
        const commands = Object.entries(parsed.scripts ?? {}).flatMap(([name, command]) => typeof command === "string"
            ? [
                {
                    name,
                    command: commandForManifest(manifestPath, command),
                    value: `${name}: ${command}`,
                    confidence: "high",
                    sources: [manifestPath],
                },
            ]
            : []);
        const dependencyNames = Object.keys({
            ...(parsed.dependencies ?? {}),
            ...(parsed.devDependencies ?? {}),
            ...(parsed.peerDependencies ?? {}),
        });
        const dependencies = dependencyNames.flatMap((name) => dependencyFact(name, manifestPath));
        return {
            projectPurpose: parsed.description
                ? { value: parsed.description, confidence: "high", sources: [manifestPath] }
                : parsed.name
                    ? { value: `Package ${parsed.name}.`, confidence: "medium", sources: [manifestPath] }
                    : undefined,
            commands,
            dependencies,
            frameworks: dependencies.map((dep) => ({ value: dep.name, confidence: dep.confidence, sources: dep.sources })),
            architectureHints: parsed.workspaces
                ? [{ value: "Node workspace/monorepo layout detected.", confidence: "medium", sources: [manifestPath] }]
                : [],
        };
    }
    catch {
        return emptyFacts();
    }
}
async function parseCargoToml(cwd, manifestPath) {
    try {
        const text = await readFile(join(cwd, manifestPath), "utf-8");
        const name = text.match(/^name\s*=\s*["']([^"']+)["']/m)?.[1];
        const description = text.match(/^description\s*=\s*["']([^"']+)["']/m)?.[1];
        const dependencyNames = Array.from(text.matchAll(/^([a-zA-Z0-9_-]+)\s*=\s*(?:["']|\{)/gm)).map((match) => match[1] ?? "");
        const dependencies = dependencyNames.flatMap((depName) => dependencyFact(depName, manifestPath));
        const cargoCheck = commandForManifest(manifestPath, "cargo check");
        const commands = [
            {
                name: "check",
                command: cargoCheck,
                value: `check: ${cargoCheck}`,
                confidence: "medium",
                sources: [manifestPath],
            },
        ];
        return {
            projectPurpose: description
                ? { value: description, confidence: "high", sources: [manifestPath] }
                : name
                    ? { value: `Rust package ${name}.`, confidence: "medium", sources: [manifestPath] }
                    : undefined,
            commands,
            dependencies,
            frameworks: dependencies.map((dep) => ({ value: dep.name, confidence: dep.confidence, sources: dep.sources })),
            architectureHints: text.includes("[workspace]")
                ? [{ value: "Cargo workspace layout detected.", confidence: "medium", sources: [manifestPath] }]
                : [],
        };
    }
    catch {
        return emptyFacts();
    }
}
function commandForManifest(manifestPath, command) {
    const directory = dirname(manifestPath).replaceAll("\\", "/");
    return directory === "." ? command : `cd ${directory} && ${command}`;
}
function dependencyFact(name, source) {
    const match = IMPORTANT_DEPENDENCY_PATTERNS.find(([pattern]) => name.toLowerCase().includes(pattern));
    if (!match)
        return [];
    return [{ name, role: match[1], value: `${name} (${match[1]})`, confidence: "medium", sources: [source] }];
}
function emptyFacts() {
    return { commands: [], dependencies: [], frameworks: [], architectureHints: [] };
}
//# sourceMappingURL=manifest-parser.js.map