"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.renderArchitectureDiagramJson = renderArchitectureDiagramJson;
exports.renderArchitectureDiagramMermaid = renderArchitectureDiagramMermaid;
exports.renderArchitectureDiagramSvg = renderArchitectureDiagramSvg;
function sanitizeNodeId(value) {
    const sanitized = value.replace(/[^a-zA-Z0-9_]/g, '_');
    return /^[a-zA-Z_]/.test(sanitized) ? sanitized : `m_${sanitized}`;
}
function escapeMermaidLabel(value) {
    return value.replaceAll('"', '\\"');
}
function renderArchitectureDiagramJson(model) {
    return `${JSON.stringify(model, null, 2)}\n`;
}
function renderArchitectureDiagramMermaid(model) {
    const nodeIdByModule = new Map();
    for (const moduleEntry of model.modules) {
        nodeIdByModule.set(moduleEntry.name, sanitizeNodeId(moduleEntry.name));
    }
    const lines = [];
    lines.push('%% ArchPilot architecture diagram');
    lines.push('%% Generated by: archpilot diagrams generate');
    lines.push('%% To view/edit:');
    lines.push('%% 1. Copy this file content');
    lines.push('%% 2. Open https://mermaid.live');
    lines.push('%% 3. Paste the content into the editor');
    lines.push('');
    lines.push('graph TD');
    for (const moduleEntry of model.modules) {
        const nodeId = nodeIdByModule.get(moduleEntry.name) ?? sanitizeNodeId(moduleEntry.name);
        lines.push(`  ${nodeId}["${escapeMermaidLabel(moduleEntry.name)}<br/><small>${escapeMermaidLabel(moduleEntry.path)}</small>"]`);
    }
    for (const edge of model.edges) {
        const sourceId = nodeIdByModule.get(edge.source) ?? sanitizeNodeId(edge.source);
        const targetId = nodeIdByModule.get(edge.target) ?? sanitizeNodeId(edge.target);
        lines.push(`  ${sourceId} --> ${targetId}`);
    }
    lines.push('');
    lines.push('  classDef cycle fill:#fff3cd,stroke:#d29922,stroke-width:2px');
    lines.push('  classDef orphan fill:#f8f9fa,stroke:#6c757d,stroke-dasharray: 5 3');
    lines.push('  classDef hub fill:#e8f4ff,stroke:#0078d4,stroke-width:2px');
    const cycleModules = model.modules
        .filter((entry) => entry.participatesInCycle)
        .map((entry) => nodeIdByModule.get(entry.name) ?? sanitizeNodeId(entry.name))
        .sort((left, right) => left.localeCompare(right));
    if (cycleModules.length > 0) {
        lines.push(`  class ${cycleModules.join(',')} cycle`);
    }
    const orphanModules = model.modules
        .filter((entry) => entry.orphan)
        .map((entry) => nodeIdByModule.get(entry.name) ?? sanitizeNodeId(entry.name))
        .sort((left, right) => left.localeCompare(right));
    if (orphanModules.length > 0) {
        lines.push(`  class ${orphanModules.join(',')} orphan`);
    }
    const highDependencyModules = model.highDependencyModules
        .map((moduleName) => nodeIdByModule.get(moduleName) ?? sanitizeNodeId(moduleName))
        .sort((left, right) => left.localeCompare(right));
    if (highDependencyModules.length > 0) {
        lines.push(`  class ${highDependencyModules.join(',')} hub`);
    }
    return `${lines.join('\n')}\n`;
}
function escapeXml(value) {
    return value
        .replaceAll('&', '&amp;')
        .replaceAll('<', '&lt;')
        .replaceAll('>', '&gt;')
        .replaceAll('"', '&quot;')
        .replaceAll("'", '&apos;');
}
function renderArchitectureDiagramSvg(model) {
    const nodeWidth = 200;
    const nodeHeight = 36;
    const verticalGap = 20;
    const leftX = 120;
    const rightCurveX = 460;
    const topPadding = 20;
    const svgWidth = 880;
    const svgHeight = topPadding * 2 +
        model.modules.length * nodeHeight +
        Math.max(0, model.modules.length - 1) * verticalGap;
    const nodeIndex = new Map(model.modules.map((moduleEntry, index) => [moduleEntry.name, index]));
    const nodeY = (index) => topPadding + index * (nodeHeight + verticalGap);
    const nodeCenterY = (index) => nodeY(index) + nodeHeight / 2;
    const cycleMembership = new Set(model.cycles.flatMap((cycle) => cycle).filter((value) => value.length > 0));
    const orphanMembership = new Set(model.orphanModules);
    const highDependencyMembership = new Set(model.highDependencyModules);
    const edges = model.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 isCycleEdge = model.cycles.some((cycle) => {
            for (let index = 0; index < cycle.length; index += 1) {
                const source = cycle[index];
                const target = cycle[(index + 1) % cycle.length];
                if (source === edge.source && target === edge.target) {
                    return true;
                }
            }
            return false;
        });
        const stroke = isCycleEdge ? '#d29922' : '#4a5568';
        const strokeWidth = isCycleEdge ? 2.4 : 1.6;
        return `<path d="${pathD}" stroke="${stroke}" stroke-width="${strokeWidth}" fill="none" marker-end="url(#arch-arrow)"><title>${escapeXml(`${edge.source} -> ${edge.target}`)}</title></path>`;
    })
        .join('\n');
    const nodes = model.modules
        .map((moduleEntry) => {
        const index = nodeIndex.get(moduleEntry.name) ?? 0;
        const y = nodeY(index);
        const stroke = orphanMembership.has(moduleEntry.name)
            ? '#6c757d'
            : cycleMembership.has(moduleEntry.name)
                ? '#d29922'
                : highDependencyMembership.has(moduleEntry.name)
                    ? '#0078d4'
                    : '#2d3748';
        const fill = orphanMembership.has(moduleEntry.name)
            ? '#f8f9fa'
            : cycleMembership.has(moduleEntry.name)
                ? '#fff3cd'
                : highDependencyMembership.has(moduleEntry.name)
                    ? '#e8f4ff'
                    : '#edf2f7';
        return `<g><rect x="${leftX}" y="${y}" rx="8" ry="8" width="${nodeWidth}" height="${nodeHeight}" fill="${fill}" stroke="${stroke}"></rect><text x="${leftX + 12}" y="${y + 23}" font-size="12" font-family="Segoe UI, Arial, sans-serif" fill="#1a202c">${escapeXml(moduleEntry.name)}</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 architecture diagram">
  <defs>
    <marker id="arch-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>
  ${edges}
  ${nodes}
</svg>
`;
}
//# sourceMappingURL=architectureDiagramReporter.js.map