/**
 * Markdown Processor
 *
 * Extracts structure from .md files using regex (no tree-sitter dependency).
 * Creates Section nodes for headings with hierarchy, and IMPORTS edges for
 * cross-file links.
 */
import path from 'node:path';
import { generateId } from '../../lib/utils.js';
const HEADING_RE = /^(#{1,6})\s+(.+)$/;
const LINK_RE = /\[([^\]]*)\]\(([^)]+)\)/g;
const MD_EXTENSIONS = new Set(['.md', '.mdx']);
export const processMarkdown = (graph, files, allPathSet) => {
    let totalSections = 0;
    let totalLinks = 0;
    for (const file of files) {
        const ext = path.extname(file.path).toLowerCase();
        if (!MD_EXTENSIONS.has(ext))
            continue;
        const fileNodeId = generateId('File', file.path);
        // Skip if file node doesn't exist (shouldn't happen, structure-processor creates it)
        if (!graph.getNode(fileNodeId))
            continue;
        // Normalize CRLF/CR to LF before splitting so that line-end agnostic
        // markdown files (Windows-authored, mixed) yield correct headings.
        // Without this, splitting on `\n` alone leaves `## Heading\r` on each line;
        // `$` in HEADING_RE only matches at end-of-string, while `.+` stops before
        // the trailing `\r`, so the line never matches as a heading.
        const lines = file.content.split(/\r\n|\r|\n/);
        // --- Extract headings and build hierarchy ---
        // First pass: collect all heading positions so we can compute endLine spans
        const headings = [];
        for (let i = 0; i < lines.length; i++) {
            const match = lines[i].match(HEADING_RE);
            if (!match)
                continue;
            headings.push({
                level: match[1].length,
                heading: match[2].trim(),
                lineNum: i + 1, // 1-indexed
            });
        }
        // Second pass: create nodes with proper endLine spans
        const sectionStack = [];
        for (let h = 0; h < headings.length; h++) {
            const { level, heading, lineNum } = headings[h];
            // endLine = line before next heading at same or higher level, or EOF
            let endLine = lines.length;
            for (let j = h + 1; j < headings.length; j++) {
                if (headings[j].level <= level) {
                    endLine = headings[j].lineNum - 1;
                    break;
                }
            }
            const sectionId = generateId('Section', `${file.path}:L${lineNum}:${heading}`);
            const node = {
                id: sectionId,
                label: 'Section',
                properties: {
                    name: heading,
                    filePath: file.path,
                    startLine: lineNum,
                    endLine,
                    level,
                    description: `h${level}`,
                },
            };
            graph.addNode(node);
            totalSections++;
            // Find parent: pop stack until we find a level strictly less than current
            while (sectionStack.length > 0 && sectionStack[sectionStack.length - 1].level >= level) {
                sectionStack.pop();
            }
            const parentId = sectionStack.length > 0 ? sectionStack[sectionStack.length - 1].id : fileNodeId;
            graph.addRelationship({
                id: generateId('CONTAINS', `${parentId}->${sectionId}`),
                type: 'CONTAINS',
                sourceId: parentId,
                targetId: sectionId,
                confidence: 1.0,
                reason: 'markdown-heading',
            });
            sectionStack.push({ level, id: sectionId });
        }
        // --- Extract links to other files in the repo ---
        const fileDir = path.dirname(file.path);
        const seenLinks = new Set();
        let linkMatch;
        LINK_RE.lastIndex = 0;
        while ((linkMatch = LINK_RE.exec(file.content)) !== null) {
            const href = linkMatch[2];
            // Skip external URLs, anchors, and mailto
            if (href.startsWith('http://') ||
                href.startsWith('https://') ||
                href.startsWith('#') ||
                href.startsWith('mailto:')) {
                continue;
            }
            // Strip anchor fragments from local links
            const cleanHref = href.split('#')[0];
            if (!cleanHref)
                continue;
            // Resolve relative to the file's directory, then normalize
            const resolved = path.posix.normalize(path.posix.join(fileDir, cleanHref));
            if (allPathSet.has(resolved)) {
                const targetFileId = generateId('File', resolved);
                // Skip if target file node doesn't exist
                if (!graph.getNode(targetFileId))
                    continue;
                // Dedup: skip if we've already linked this file pair
                const linkKey = `${fileNodeId}->${targetFileId}`;
                if (seenLinks.has(linkKey))
                    continue;
                seenLinks.add(linkKey);
                const relId = generateId('IMPORTS', linkKey);
                graph.addRelationship({
                    id: relId,
                    type: 'IMPORTS',
                    sourceId: fileNodeId,
                    targetId: targetFileId,
                    confidence: 0.8,
                    reason: 'markdown-link',
                });
                totalLinks++;
            }
        }
    }
    return { sections: totalSections, links: totalLinks };
};
