// dep-auditor/index.ts — Main dependency audit orchestrator (SPEC-025)
// Combines license checking, vuln detection, abandonment heuristics, and duplicate detection.
import { readFile } from 'node:fs/promises';
import { join } from 'node:path';
import { readManifest } from '../stack-auditor/manifest-reader.js';
import { checkLicense, isCommercialProject } from './license-checker.js';
import { detectDuplicates } from './dep-duplicates-detector.js';
import { getVulns } from './vuln-data.js';
import { getAbandonedInfo, classifyEntry } from './abandonment-data.js';
export { formatDepAuditMarkdown, formatDepAuditAcceptanceCriteria } from './formatters.js';
/**
 * Audit all dependencies of a project at projectPath.
 * Scans package.json (npm), requirements.txt (python), go.mod (go),
 * Cargo.toml (rust), pom.xml (java).
 */
export async function auditDeps(projectPath) {
    const manifest = await readManifest(projectPath);
    const ecosystem = manifest.ecosystem;
    // Determine if commercial project (for future license severity adjustment)
    if (ecosystem === 'nodejs') {
        try {
            const pkgJson = await readFile(join(projectPath, 'package.json'), 'utf-8');
            // isCommercialProject result reserved for future enforcement logic
            isCommercialProject(pkgJson);
        }
        catch {
            // default: assume commercial
        }
    }
    const deps = manifest.directDependencies;
    const depNames = Object.keys(deps);
    const licenseMap = await buildLicenseMap(projectPath, ecosystem);
    const entries = depNames.map((name) => {
        const version = deps[name] ?? 'unknown';
        const vulns = getVulns(name, version);
        const licenseRaw = licenseMap[name] ?? '';
        const license = checkLicense(licenseRaw);
        const abandoned = getAbandonedInfo(name);
        return {
            name,
            currentVersion: version,
            ecosystem,
            vulns,
            license,
            abandoned,
        };
    });
    // Detect duplicates
    const duplicates = detectDuplicates(depNames);
    const duplicateCategories = new Map();
    for (const dup of duplicates) {
        for (const pkg of dup.packages) {
            duplicateCategories.set(pkg, dup.category);
        }
    }
    // Tag duplicate groups on entries
    const taggedEntries = entries.map((e) => {
        const grp = duplicateCategories.get(e.name);
        return grp ? { ...e, duplicateGroup: grp } : e;
    });
    const critical = [];
    const warnings = [];
    const clean = [];
    for (const entry of taggedEntries) {
        const cls = classifyEntry(entry);
        if (cls === 'critical') {
            critical.push(entry);
        }
        else if (cls === 'warning') {
            warnings.push(entry);
        }
        else {
            clean.push(entry);
        }
    }
    const totalDeps = depNames.length;
    const summary = buildSummary(totalDeps, critical.length, warnings.length, duplicates.length);
    return { ecosystem, totalDeps, critical, warnings, clean, duplicates, summary };
}
async function buildLicenseMap(projectPath, ecosystem) {
    if (ecosystem !== 'nodejs') {
        return {};
    }
    const licenseMap = {};
    try {
        const pkgJson = await readFile(join(projectPath, 'package.json'), 'utf-8');
        const parsed = JSON.parse(pkgJson);
        const allDeps = {
            ...(parsed.dependencies ?? {}),
            ...(parsed.devDependencies ?? {}),
        };
        for (const depName of Object.keys(allDeps)) {
            try {
                const depPkg = await readFile(join(projectPath, 'node_modules', depName, 'package.json'), 'utf-8');
                const depParsed = JSON.parse(depPkg);
                if (typeof depParsed.license === 'string') {
                    licenseMap[depName] = depParsed.license;
                }
            }
            catch {
                // dep not installed or not accessible — leave as unknown
            }
        }
    }
    catch {
        // no package.json
    }
    return licenseMap;
}
function buildSummary(total, criticalCount, warningCount, duplicateCount) {
    const parts = [`${total} dep(s) scanned`];
    if (criticalCount > 0) {
        parts.push(`${criticalCount} critical issue(s)`);
    }
    if (warningCount > 0) {
        parts.push(`${warningCount} warning(s)`);
    }
    if (duplicateCount > 0) {
        parts.push(`${duplicateCount} duplicate group(s) detected`);
    }
    if (criticalCount === 0 && warningCount === 0 && duplicateCount === 0) {
        parts.push('no issues found');
    }
    return parts.join(' — ');
}
//# sourceMappingURL=index.js.map