/**
 * Content Parser for Intelligent Living Docs Sync
 *
 * Parses increment spec.md into structured sections for classification and distribution.
 *
 * @module living-docs/content-parser
 */
import matter from 'gray-matter';
/**
 * Content Parser class
 */
export class ContentParser {
    constructor(options = {}) {
        this.options = {
            preserveCodeBlocks: options.preserveCodeBlocks ?? true,
            preserveLinks: options.preserveLinks ?? true,
            preserveImages: options.preserveImages ?? true,
            maxDepth: options.maxDepth ?? 6,
            includeRawContent: options.includeRawContent ?? true,
        };
    }
    /**
     * Parse markdown content into structured sections
     */
    parse(markdown, filePath) {
        // 1. Extract frontmatter
        const { data: frontmatter, content } = matter(markdown);
        // 2. Split into lines for line number tracking
        const lines = content.split('\n');
        // 3. Parse sections
        const sections = this.parseSections(lines, 0, lines.length);
        return {
            frontmatter,
            sections,
            raw: markdown,
            filePath,
        };
    }
    /**
     * Parse sections from lines array (recursive for nested sections)
     */
    parseSections(lines, startIndex, endIndex, parentLevel = 0) {
        const sections = [];
        let currentSection = null;
        let sectionContentLines = [];
        let currentLine = startIndex;
        while (currentLine < endIndex) {
            const line = lines[currentLine];
            const headingMatch = line.match(/^(#{1,6})\s+(.+)$/);
            if (headingMatch) {
                const level = headingMatch[1].length;
                // Only process headings at or below max depth
                if (level <= this.options.maxDepth) {
                    // Save previous section
                    if (currentSection) {
                        currentSection.content = sectionContentLines.join('\n').trim();
                        currentSection.endLine = currentLine - 1;
                        // Parse content elements
                        if (this.options.preserveCodeBlocks) {
                            currentSection.codeBlocks = this.extractCodeBlocks(currentSection.content);
                        }
                        if (this.options.preserveLinks) {
                            currentSection.links = this.extractLinks(currentSection.content);
                        }
                        if (this.options.preserveImages) {
                            currentSection.images = this.extractImages(currentSection.content);
                        }
                        sections.push(currentSection);
                    }
                    // Start new section
                    const heading = headingMatch[2].trim();
                    currentSection = {
                        id: this.slugify(heading),
                        heading,
                        level,
                        content: '',
                        rawContent: '',
                        codeBlocks: [],
                        links: [],
                        images: [],
                        startLine: currentLine,
                        endLine: currentLine,
                        children: [],
                    };
                    sectionContentLines = [];
                }
            }
            else if (currentSection) {
                // Add line to current section content
                sectionContentLines.push(line);
            }
            currentLine++;
        }
        // Save last section
        if (currentSection) {
            currentSection.content = sectionContentLines.join('\n').trim();
            currentSection.endLine = endIndex - 1;
            if (this.options.preserveCodeBlocks) {
                currentSection.codeBlocks = this.extractCodeBlocks(currentSection.content);
            }
            if (this.options.preserveLinks) {
                currentSection.links = this.extractLinks(currentSection.content);
            }
            if (this.options.preserveImages) {
                currentSection.images = this.extractImages(currentSection.content);
            }
            sections.push(currentSection);
        }
        // Build hierarchy (nest sub-sections)
        return this.buildHierarchy(sections);
    }
    /**
     * Build section hierarchy (nest sub-sections under parent sections)
     */
    buildHierarchy(sections) {
        const result = [];
        const stack = [];
        for (const section of sections) {
            // Pop stack until we find a parent with lower level
            while (stack.length > 0 && stack[stack.length - 1].level >= section.level) {
                stack.pop();
            }
            if (stack.length === 0) {
                // Top-level section
                result.push(section);
            }
            else {
                // Nested section - add to parent
                const parent = stack[stack.length - 1];
                parent.children.push(section);
            }
            stack.push(section);
        }
        // Set raw content for each section (including children)
        this.setRawContent(result);
        return result;
    }
    /**
     * Set raw content for sections (including nested children)
     */
    setRawContent(sections) {
        for (const section of sections) {
            if (this.options.includeRawContent) {
                section.rawContent = this.generateRawContent(section);
            }
            if (section.children.length > 0) {
                this.setRawContent(section.children);
            }
        }
    }
    /**
     * Generate raw content for a section (including nested children)
     */
    generateRawContent(section) {
        let content = `${'#'.repeat(section.level)} ${section.heading}\n\n`;
        content += section.content;
        for (const child of section.children) {
            content += '\n\n' + this.generateRawContent(child);
        }
        return content;
    }
    /**
     * Extract code blocks from content
     */
    extractCodeBlocks(content) {
        const codeBlocks = [];
        const lines = content.split('\n');
        let inCodeBlock = false;
        let currentBlock = null;
        lines.forEach((line, index) => {
            const codeBlockStart = line.match(/^```(\w*)/);
            const codeBlockEnd = line.match(/^```\s*$/);
            if (codeBlockStart && !inCodeBlock) {
                inCodeBlock = true;
                currentBlock = {
                    language: codeBlockStart[1] || 'text',
                    lines: [],
                    startLine: index,
                };
            }
            else if (codeBlockEnd && inCodeBlock && currentBlock) {
                inCodeBlock = false;
                codeBlocks.push({
                    language: currentBlock.language,
                    content: currentBlock.lines.join('\n'),
                    startLine: currentBlock.startLine,
                    endLine: index,
                });
                currentBlock = null;
            }
            else if (inCodeBlock && currentBlock) {
                currentBlock.lines.push(line);
            }
        });
        return codeBlocks;
    }
    /**
     * Extract links from content
     */
    extractLinks(content) {
        const links = [];
        // Markdown links: [text](url)
        const markdownLinkRegex = /\[([^\]]+)\]\(([^)]+)\)/g;
        let match;
        while ((match = markdownLinkRegex.exec(content)) !== null) {
            const [, text, url] = match;
            links.push({
                text,
                url,
                type: this.determineLinkType(url),
            });
        }
        return links;
    }
    /**
     * Extract images from content
     */
    extractImages(content) {
        const images = [];
        // Markdown images: ![alt](url "title")
        const imageRegex = /!\[([^\]]*)\]\(([^)\s]+)(?:\s+"([^"]+)")?\)/g;
        let match;
        while ((match = imageRegex.exec(content)) !== null) {
            const [, alt, url, title] = match;
            images.push({
                alt,
                url,
                title,
            });
        }
        return images;
    }
    /**
     * Determine link type (internal/external/anchor)
     */
    determineLinkType(url) {
        if (url.startsWith('#')) {
            return 'anchor';
        }
        else if (url.startsWith('http://') || url.startsWith('https://')) {
            return 'external';
        }
        else {
            return 'internal';
        }
    }
    /**
     * Convert heading to URL-safe slug
     */
    slugify(text) {
        return text
            .toLowerCase()
            .replace(/[^\w\s-]/g, '') // Remove special characters
            .replace(/\s+/g, '-') // Replace spaces with hyphens
            .replace(/--+/g, '-') // Replace multiple hyphens with single
            .trim();
    }
    /**
     * Find section by ID (recursive search)
     */
    findSection(sections, id) {
        for (const section of sections) {
            if (section.id === id) {
                return section;
            }
            if (section.children.length > 0) {
                const found = this.findSection(section.children, id);
                if (found)
                    return found;
            }
        }
        return null;
    }
    /**
     * Get all sections flattened (no hierarchy)
     */
    flattenSections(sections) {
        const result = [];
        for (const section of sections) {
            result.push(section);
            if (section.children.length > 0) {
                result.push(...this.flattenSections(section.children));
            }
        }
        return result;
    }
    /**
     * Get sections by level
     */
    getSectionsByLevel(sections, level) {
        return this.flattenSections(sections).filter((s) => s.level === level);
    }
    /**
     * Get section content without code blocks
     */
    getContentWithoutCode(section) {
        let content = section.content;
        // Remove code blocks
        content = content.replace(/```[\s\S]*?```/g, '');
        return content.trim();
    }
}
/**
 * Factory function to create parser
 */
export function createContentParser(options) {
    return new ContentParser(options);
}
/**
 * Convenience function to parse markdown
 */
export function parseMarkdown(markdown, options) {
    const parser = new ContentParser(options);
    return parser.parse(markdown);
}
//# sourceMappingURL=content-parser.js.map