"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.renderArchitectureMapJson = renderArchitectureMapJson;
exports.renderDependencyGraphJson = renderDependencyGraphJson;
exports.renderArchitectureMapMarkdown = renderArchitectureMapMarkdown;
exports.renderModuleBoundariesMarkdown = renderModuleBoundariesMarkdown;
exports.renderArchitectureMapDot = renderArchitectureMapDot;
exports.renderArchitectureMapSvg = renderArchitectureMapSvg;
function escapeMdCell(value) {
    return value.replaceAll('|', '\\|').replaceAll('\n', ' ');
}
function escapeXml(value) {
    return value
        .replaceAll('&', '&amp;')
        .replaceAll('<', '&lt;')
        .replaceAll('>', '&gt;')
        .replaceAll('"', '&quot;')
        .replaceAll("'", '&apos;');
}
function formatCountList(values) {
    if (values.length === 0) {
        return '- (none)';
    }
    return values.map((entry) => `- ${entry.moduleName} (${entry.count})`).join('\n');
}
function formatStringList(values) {
    if (values.length === 0) {
        return '- (none)';
    }
    return values.map((entry) => `- ${entry}`).join('\n');
}
function renderArchitectureMapJson(map) {
    return `${JSON.stringify(map, null, 2)}\n`;
}
function renderDependencyGraphJson(map) {
    const dependenciesBySource = new Map();
    for (const moduleEntry of map.modules) {
        dependenciesBySource.set(moduleEntry.moduleName, new Set());
    }
    for (const edge of map.edges) {
        dependenciesBySource.get(edge.source)?.add(edge.target);
    }
    const modules = [...map.modules]
        .sort((left, right) => left.moduleName.localeCompare(right.moduleName))
        .map((moduleEntry) => ({
        name: moduleEntry.moduleName,
        path: moduleEntry.sourcePath,
        dependsOn: [...(dependenciesBySource.get(moduleEntry.moduleName) ?? new Set())].sort((left, right) => left.localeCompare(right)),
    }));
    return `${JSON.stringify({
        ...(map.xArchPilot ? { xArchPilot: map.xArchPilot } : {}),
        generatedAtUtc: map.generatedAtUtc,
        modules,
        edges: map.edges,
        graph: {
            nodes: map.graph.nodes,
            edges: map.graph.edges,
        },
    }, null, 2)}\n`;
}
function renderArchitectureMapMarkdown(map) {
    const moduleRows = map.moduleHotspotSummary
        .map((moduleSummary) => {
        const moduleRecord = map.modules.find((entry) => entry.moduleName === moduleSummary.moduleName);
        const sourceKind = moduleRecord?.discoverySource ?? 'inferred-scan';
        const contractPath = moduleRecord?.contractPath ?? '(none)';
        const alignment = moduleSummary.missingPublicEntrypointAlignment === undefined
            ? 'n/a'
            : moduleSummary.missingPublicEntrypointAlignment
                ? 'yes'
                : 'no';
        return `| ${escapeMdCell(moduleSummary.moduleName)} | ${sourceKind} | ${moduleSummary.incomingDependencyCount} | ${moduleSummary.outgoingDependencyCount} | ${moduleSummary.participatesInCycle ? 'yes' : 'no'} | ${moduleSummary.orphan ? 'yes' : 'no'} | ${moduleSummary.missingContract ? 'yes' : 'no'} | ${alignment} | ${escapeMdCell(moduleRecord?.sourcePath ?? '(unknown)')} | ${escapeMdCell(contractPath)} |`;
    })
        .join('\n');
    const edgeRows = map.edges.length === 0
        ? '- (none)'
        : map.edges
            .map((edge) => `- ${edge.source} -> ${edge.target} | imports=${edge.importCount}, public=${edge.publicImportCount}, nonPublic=${edge.nonPublicImportCount}`)
            .join('\n');
    const cycleRows = map.cycles.length === 0
        ? '- (none)'
        : map.cycles.map((cycle) => `- ${cycle.join(' -> ')} -> ${cycle[0]}`).join('\n');
    const architectureJsonNote = map.discoveryMode === 'architecture-json'
        ? 'Used `.archpilot/architecture.json` module registry as primary source.'
        : `Did not use \`.archpilot/architecture.json\` module registry (missing or empty modules); used fallback inference from \`${map.modulesRoot}\`.`;
    return `${renderManagedMarkdownMarker(map.xArchPilot)}# ArchPilot Architecture Map

- Project: ${map.projectName}
- Timestamp (UTC): ${map.generatedAtUtc}
- Report version: ${map.reportVersion}

## Discovery Summary
- Discovery mode: ${map.discoveryMode}
- Modules root: ${map.modulesRoot}
- Modules discovered: ${map.summaryCounts.moduleCount}
- Module edges discovered: ${map.summaryCounts.edgeCount}
- Circular dependencies: ${map.summaryCounts.cycleCount}
- Orphan modules: ${map.summaryCounts.orphanCount}
- Missing contracts: ${map.summaryCounts.missingContractCount}
- Highly connected modules: ${map.summaryCounts.highlyConnectedCount}
- Notes: ${architectureJsonNote}

## Modules
| Module | Source | Incoming | Outgoing | In Cycle | Orphan | Missing Contract | Missing Entrypoint Alignment | Source Path | Contract Path |
| --- | --- | ---: | ---: | --- | --- | --- | --- | --- | --- |
${moduleRows || '| (none) | n/a | 0 | 0 | no | yes | yes | n/a | (none) | (none) |'}

## Dependency Summary
${edgeRows}

## Hotspots
### Most Depended-On Modules
${formatCountList(map.hotspots.mostDependedOnModules)}

### Highest Outgoing Fan-Out Modules
${formatCountList(map.hotspots.highestOutgoingFanOutModules)}

### Highly Connected Modules
${formatCountList(map.hotspots.highlyConnectedModules)}

### Modules In Circular Dependencies
${formatStringList(map.hotspots.modulesInCircularDependencies)}

### Orphan Modules
${formatStringList(map.hotspots.orphanModules)}

### Missing Contracts
${formatStringList(map.hotspots.missingContracts)}

### Missing Public Entrypoint Alignment
${formatStringList(map.hotspots.missingPublicEntrypointAlignment)}

## Circular Dependencies
${cycleRows}

## Notes
- usedArchitectureJson: ${map.notes.usedArchitectureJson}
- usedFallbackInference: ${map.notes.usedFallbackInference}
`.trimEnd() + '\n';
}
function renderModuleBoundariesMarkdown(map) {
    const dependenciesBySource = new Map();
    for (const moduleEntry of map.modules) {
        dependenciesBySource.set(moduleEntry.moduleName, new Set());
    }
    for (const edge of map.edges) {
        dependenciesBySource.get(edge.source)?.add(edge.target);
    }
    const sections = [...map.modules]
        .sort((left, right) => left.moduleName.localeCompare(right.moduleName))
        .map((moduleEntry) => {
        const dependsOn = [...(dependenciesBySource.get(moduleEntry.moduleName) ?? new Set())].sort((left, right) => left.localeCompare(right));
        const dependenciesList = dependsOn.length === 0
            ? '- (none)'
            : dependsOn.map((dependency) => `- ${dependency}`).join('\n');
        return `## ${moduleEntry.moduleName}\nDepends on:\n${dependenciesList}\n`;
    })
        .join('\n');
    return `${renderManagedMarkdownMarker(map.xArchPilot)}${sections.trimEnd()}\n`;
}
function renderManagedMarkdownMarker(metadata) {
    return metadata ? `<!-- archpilot:managed generated-by=${metadata.generator} -->\n` : '';
}
function renderArchitectureMapDot(map) {
    const lines = [];
    lines.push('digraph ArchPilotModuleGraph {');
    lines.push('  rankdir=LR;');
    lines.push('  node [shape=box, style="rounded,filled", color="#2d3748", fillcolor="#edf2f7"];');
    lines.push('  edge [color="#4a5568"];');
    for (const node of map.graph.nodes) {
        lines.push(`  "${node.id}" [label="${node.label}"];`);
    }
    for (const edge of map.graph.edges) {
        lines.push(`  "${edge.source}" -> "${edge.target}" [label="imports=${edge.importCount}, public=${edge.publicImportCount}, nonPublic=${edge.nonPublicImportCount}"];`);
    }
    lines.push('}');
    return `${lines.join('\n')}\n`;
}
function renderArchitectureMapSvg(map) {
    const nodeWidth = 200;
    const nodeHeight = 34;
    const verticalGap = 22;
    const leftX = 120;
    const rightCurveX = 460;
    const topPadding = 20;
    const svgWidth = 860;
    const svgHeight = topPadding * 2 +
        map.graph.nodes.length * nodeHeight +
        Math.max(0, map.graph.nodes.length - 1) * verticalGap;
    const nodeIndex = new Map(map.graph.nodes.map((node, index) => [node.id, index]));
    const nodeY = (index) => topPadding + index * (nodeHeight + verticalGap);
    const nodeCenterY = (index) => nodeY(index) + nodeHeight / 2;
    const edgePaths = map.graph.edges
        .filter((edge) => nodeIndex.has(edge.source) && nodeIndex.has(edge.target))
        .map((edge) => {
        const sourceIndex = nodeIndex.get(edge.source) ?? 0;
        const targetIndex = nodeIndex.get(edge.target) ?? 0;
        const startX = leftX + nodeWidth;
        const startY = nodeCenterY(sourceIndex);
        const endX = leftX;
        const endY = nodeCenterY(targetIndex);
        const pathD = `M ${startX} ${startY} C ${rightCurveX} ${startY}, ${rightCurveX} ${endY}, ${endX} ${endY}`;
        const edgeLabel = `${edge.source} -> ${edge.target} (imports=${edge.importCount}, public=${edge.publicImportCount}, nonPublic=${edge.nonPublicImportCount})`;
        const strokeWidth = edge.nonPublicImportCount > 0 ? 2.1 : 1.4;
        const stroke = edge.nonPublicImportCount > 0 ? '#c53030' : '#4a5568';
        return `<path d="${pathD}" stroke="${stroke}" stroke-width="${strokeWidth}" fill="none" marker-end="url(#arrow)" data-source="${escapeXml(edge.source)}" data-target="${escapeXml(edge.target)}"><title>${escapeXml(edgeLabel)}</title></path>`;
    })
        .join('\n');
    const nodes = map.graph.nodes
        .map((node) => {
        const index = nodeIndex.get(node.id) ?? 0;
        const y = nodeY(index);
        return `<g data-module="${escapeXml(node.id)}"><rect x="${leftX}" y="${y}" rx="8" ry="8" width="${nodeWidth}" height="${nodeHeight}" fill="#edf2f7" stroke="#2d3748"></rect><text x="${leftX + 12}" y="${y + 22}" font-size="12" font-family="Segoe UI, Arial, sans-serif" fill="#1a202c">${escapeXml(node.label)}</text></g>`;
    })
        .join('\n');
    return `<svg xmlns="http://www.w3.org/2000/svg" width="${svgWidth}" height="${svgHeight}" viewBox="0 0 ${svgWidth} ${svgHeight}" role="img" aria-label="ArchPilot module dependency graph">
  <defs>
    <marker id="arrow" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto" markerUnits="strokeWidth">
      <path d="M0,0 L8,3 L0,6 Z" fill="#4a5568"></path>
    </marker>
  </defs>
  <rect x="0" y="0" width="${svgWidth}" height="${svgHeight}" fill="#ffffff"></rect>
  ${edgePaths}
  ${nodes}
</svg>
`;
}
//# sourceMappingURL=architectureMapReporter.js.map