"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateOnboardingDocs = generateOnboardingDocs;
const path = __importStar(require("node:path"));
const node_fs_1 = require("node:fs");
const architectureMap_1 = require("./architectureMap");
function normalizePath(value) {
    return value.replace(/\\/g, '/');
}
async function pathExists(filePath) {
    try {
        await node_fs_1.promises.access(filePath);
        return true;
    }
    catch {
        return false;
    }
}
function sortUnique(values) {
    return [...new Set(values)].sort((left, right) => left.localeCompare(right));
}
function isFoundationalModuleName(moduleName) {
    return /(^|[-_])(shared|common|core|foundation|platform|base|util|utils)([-_]|$)/i.test(moduleName);
}
function computeRisk(entry) {
    const reasons = [];
    let riskScore = 0;
    if (entry.participatesInCycle) {
        reasons.push('Participates in dependency cycle');
        riskScore += 100;
    }
    if (!entry.contractExists) {
        reasons.push('Missing module contract');
        riskScore += 70;
    }
    if (entry.missingPublicEntrypointAlignment === true) {
        reasons.push('Public entrypoint mismatch');
        riskScore += 50;
    }
    if (entry.incomingDependencyCount >= 3) {
        reasons.push('High inbound dependency count');
        riskScore += 30 + entry.incomingDependencyCount;
    }
    if (entry.outgoingDependencyCount >= 4) {
        reasons.push('High outgoing dependency count');
        riskScore += 20 + entry.outgoingDependencyCount;
    }
    return {
        moduleName: entry.moduleName,
        riskScore,
        reasons: reasons.sort((left, right) => left.localeCompare(right)),
    };
}
async function generateOnboardingDocs(workspaceRoot) {
    const map = await (0, architectureMap_1.generateArchitectureMap)(workspaceRoot);
    const hotspotByModule = new Map(map.moduleHotspotSummary
        .map((entry) => [entry.moduleName, entry])
        .sort(([left], [right]) => left.localeCompare(right)));
    const modules = await Promise.all([...map.modules]
        .sort((left, right) => left.moduleName.localeCompare(right.moduleName))
        .map(async (moduleEntry) => {
        const readmePath = `${moduleEntry.sourcePath}/README.md`;
        const indexPath = `${moduleEntry.sourcePath}/index.ts`;
        const readmeExists = await pathExists(path.join(workspaceRoot, ...readmePath.split('/')));
        const indexExists = await pathExists(path.join(workspaceRoot, ...indexPath.split('/')));
        const hotspot = hotspotByModule.get(moduleEntry.moduleName);
        const recommendedFirstFiles = sortUnique([
            readmeExists ? readmePath : undefined,
            indexExists ? indexPath : undefined,
            moduleEntry.contractExists ? moduleEntry.contractPath : undefined,
        ].filter((value) => !!value));
        return {
            moduleName: moduleEntry.moduleName,
            path: moduleEntry.sourcePath,
            ...(moduleEntry.contractPath
                ? { contractPath: moduleEntry.contractPath }
                : {}),
            contractExists: moduleEntry.contractExists,
            readmePath,
            readmeExists,
            indexPath,
            indexExists,
            incomingDependencyCount: hotspot?.incomingDependencyCount ?? 0,
            outgoingDependencyCount: hotspot?.outgoingDependencyCount ?? 0,
            participatesInCycle: hotspot?.participatesInCycle ?? false,
            orphan: hotspot?.orphan ?? false,
            ...(hotspot?.missingPublicEntrypointAlignment !== undefined
                ? {
                    missingPublicEntrypointAlignment: hotspot.missingPublicEntrypointAlignment,
                }
                : {}),
            recommendedFirstFiles,
        };
    }));
    const foundational = modules
        .filter((entry) => isFoundationalModuleName(entry.moduleName) && !entry.orphan)
        .sort((left, right) => left.moduleName.localeCompare(right.moduleName));
    const foundationalSet = new Set(foundational.map((entry) => entry.moduleName));
    const heavilyDepended = modules
        .filter((entry) => !entry.orphan &&
        !foundationalSet.has(entry.moduleName) &&
        entry.incomingDependencyCount > 0)
        .sort((left, right) => {
        const inboundCompare = right.incomingDependencyCount - left.incomingDependencyCount;
        if (inboundCompare !== 0) {
            return inboundCompare;
        }
        return left.moduleName.localeCompare(right.moduleName);
    });
    const heavySet = new Set(heavilyDepended.map((entry) => entry.moduleName));
    const regularModules = modules
        .filter((entry) => !entry.orphan &&
        !foundationalSet.has(entry.moduleName) &&
        !heavySet.has(entry.moduleName))
        .sort((left, right) => left.moduleName.localeCompare(right.moduleName));
    const orphanRisk = modules
        .filter((entry) => entry.orphan)
        .map((entry) => ({
        entry,
        risk: computeRisk(entry),
    }));
    const riskyOrphans = orphanRisk
        .filter(({ risk }) => risk.riskScore > 0)
        .sort((left, right) => {
        const scoreCompare = right.risk.riskScore - left.risk.riskScore;
        if (scoreCompare !== 0) {
            return scoreCompare;
        }
        return left.entry.moduleName.localeCompare(right.entry.moduleName);
    })
        .map(({ entry }) => entry);
    const riskyOrphanSet = new Set(riskyOrphans.map((entry) => entry.moduleName));
    const regularOrphans = modules
        .filter((entry) => entry.orphan && !riskyOrphanSet.has(entry.moduleName))
        .sort((left, right) => left.moduleName.localeCompare(right.moduleName));
    const suggestedReadingOrder = [
        ...foundational.map((entry) => ({
            moduleName: entry.moduleName,
            reason: 'Foundational/shared module',
            participatesInCycle: entry.participatesInCycle,
        })),
        ...heavilyDepended.map((entry) => ({
            moduleName: entry.moduleName,
            reason: 'High inbound dependency module',
            participatesInCycle: entry.participatesInCycle,
        })),
        ...regularModules.map((entry) => ({
            moduleName: entry.moduleName,
            reason: 'Feature module',
            participatesInCycle: entry.participatesInCycle,
        })),
        ...riskyOrphans.map((entry) => ({
            moduleName: entry.moduleName,
            reason: 'Orphan module (risk flagged)',
            participatesInCycle: entry.participatesInCycle,
        })),
        ...regularOrphans.map((entry) => ({
            moduleName: entry.moduleName,
            reason: 'Orphan module',
            participatesInCycle: entry.participatesInCycle,
        })),
    ];
    const computedRisk = modules
        .map((entry) => computeRisk(entry))
        .filter((entry) => entry.riskScore > 0)
        .sort((left, right) => {
        const scoreCompare = right.riskScore - left.riskScore;
        if (scoreCompare !== 0) {
            return scoreCompare;
        }
        return left.moduleName.localeCompare(right.moduleName);
    });
    const highRiskModules = computedRisk.length > 0
        ? computedRisk
        : modules
            .slice()
            .sort((left, right) => {
            const scoreLeft = left.incomingDependencyCount + left.outgoingDependencyCount;
            const scoreRight = right.incomingDependencyCount + right.outgoingDependencyCount;
            const compare = scoreRight - scoreLeft;
            if (compare !== 0) {
                return compare;
            }
            return left.moduleName.localeCompare(right.moduleName);
        })
            .slice(0, 3)
            .map((entry) => ({
            moduleName: entry.moduleName,
            riskScore: entry.incomingDependencyCount + entry.outgoingDependencyCount,
            reasons: ['Connectivity hotspot'],
        }));
    const sortedEdges = [...map.edges].sort((left, right) => {
        const sourceCompare = left.source.localeCompare(right.source);
        if (sourceCompare !== 0) {
            return sourceCompare;
        }
        return left.target.localeCompare(right.target);
    });
    return {
        reportVersion: 1,
        projectName: map.projectName,
        generatedAtUtc: map.generatedAtUtc,
        summary: {
            moduleCount: modules.length,
            edgeCount: sortedEdges.length,
            cycleCount: map.cycles.length,
            orphanCount: map.hotspots.orphanModules.length,
            missingContractCount: map.hotspots.missingContracts.length,
        },
        modules,
        dependencySummary: {
            edges: sortedEdges.map((edge) => ({
                source: edge.source,
                target: edge.target,
                importCount: edge.importCount,
            })),
            totalCrossModuleImports: sortedEdges.reduce((total, edge) => total + edge.importCount, 0),
        },
        cycles: [...map.cycles]
            .map((cycle) => [...cycle])
            .sort((left, right) => left.join('->').localeCompare(right.join('->'))),
        orphanModules: sortUnique(map.hotspots.orphanModules),
        missingContracts: sortUnique(map.hotspots.missingContracts),
        publicEntrypointMismatches: sortUnique(map.hotspots.missingPublicEntrypointAlignment ?? []),
        suggestedReadingOrder,
        highRiskModules,
    };
}
//# sourceMappingURL=generateOnboardingDocs.js.map