/**
 * @fileoverview Markdown builder utility for creating well-structured, semantic markdown content
 * @module utils/formatting/markdownBuilder
 */
/**
 * Utility class for building well-formatted markdown content with consistent structure.
 *
 * Provides a fluent API for creating markdown documents with proper spacing, hierarchy,
 * and semantic structure. Eliminates string concatenation and ensures consistent
 * formatting across tool response formatters. Each method appends to an internal buffer
 * and returns `this` for chaining; call {@link MarkdownBuilder.build} to produce the
 * final string.
 *
 * @example
 * ```typescript
 * const output = new MarkdownBuilder()
 *   .h1('Commit Created Successfully')
 *   .keyValue('Commit Hash', 'abc123def')
 *   .keyValue('Author', 'John Doe')
 *   .section('Files Changed', () => {
 *     // `section` calls the callback immediately; builder state is mutated in place
 *   })
 *   .list(['file1.ts', 'file2.ts'])
 *   .build();
 * ```
 *
 * @example
 * ```typescript
 * // Using the `markdown()` factory shorthand
 * import { markdown } from '@cyanheads/mcp-ts-core/utils';
 *
 * const md = markdown()
 *   .h2('Results')
 *   .table(['Name', 'Status'], [['foo', 'ok'], ['bar', 'fail']])
 *   .build();
 * ```
 */
export class MarkdownBuilder {
    sections = [];
    /**
     * Add a level 1 heading (`# text`).
     *
     * @param text - The heading text
     * @param emoji - Optional emoji prepended before the text with a space
     * @returns this builder for chaining
     *
     * @example
     * ```typescript
     * markdown().h1('Report').build();           // '# Report'
     * markdown().h1('Report', '📋').build();     // '# 📋 Report'
     * ```
     */
    h1(text, emoji) {
        const prefix = emoji ? `${emoji} ` : '';
        this.sections.push(`# ${prefix}${text}\n\n`);
        return this;
    }
    /**
     * Add a level 2 heading (`## text`).
     *
     * @param text - The heading text
     * @param emoji - Optional emoji prepended before the text with a space
     * @returns this builder for chaining
     *
     * @example
     * ```typescript
     * markdown().h2('Section').build();   // '## Section'
     * ```
     */
    h2(text, emoji) {
        const prefix = emoji ? `${emoji} ` : '';
        this.sections.push(`## ${prefix}${text}\n\n`);
        return this;
    }
    /**
     * Add a level 3 heading (`### text`).
     *
     * @param text - The heading text
     * @param emoji - Optional emoji prepended before the text with a space
     * @returns this builder for chaining
     *
     * @example
     * ```typescript
     * markdown().h3('Subsection').build();   // '### Subsection'
     * ```
     */
    h3(text, emoji) {
        const prefix = emoji ? `${emoji} ` : '';
        this.sections.push(`### ${prefix}${text}\n\n`);
        return this;
    }
    /**
     * Add a level 4 heading (`#### text`).
     *
     * @param text - The heading text
     * @param emoji - Optional emoji prepended before the text with a space
     * @returns this builder for chaining
     *
     * @example
     * ```typescript
     * markdown().h4('Detail').build();   // '#### Detail'
     * ```
     */
    h4(text, emoji) {
        const prefix = emoji ? `${emoji} ` : '';
        this.sections.push(`#### ${prefix}${text}\n\n`);
        return this;
    }
    /**
     * Add a bold key-value pair on a single line (`**key:** value`).
     * `null` values are rendered as the string `'null'`.
     *
     * @param key - The key label, rendered in bold
     * @param value - The value; `null` renders as `'null'`
     * @returns this builder for chaining
     *
     * @example
     * ```typescript
     * markdown().keyValue('Status', 'active').build();   // '**Status:** active'
     * markdown().keyValue('Count', 42).build();          // '**Count:** 42'
     * markdown().keyValue('Flag', null).build();         // '**Flag:** null'
     * ```
     */
    keyValue(key, value) {
        const displayValue = value === null ? 'null' : String(value);
        this.sections.push(`**${key}:** ${displayValue}\n`);
        return this;
    }
    /**
     * Add a plain (unbolded) key-value pair on a single line (`key: value`).
     * Use when less visual emphasis is desired compared to {@link keyValue}.
     * `null` values are rendered as the string `'null'`.
     *
     * @param key - The key label, rendered without formatting
     * @param value - The value; `null` renders as `'null'`
     * @returns this builder for chaining
     *
     * @example
     * ```typescript
     * markdown().keyValuePlain('host', 'localhost').build();   // 'host: localhost'
     * ```
     */
    keyValuePlain(key, value) {
        const displayValue = value === null ? 'null' : String(value);
        this.sections.push(`${key}: ${displayValue}\n`);
        return this;
    }
    /**
     * Add a bulleted (`-`) or numbered list. Empty arrays are silently ignored.
     *
     * @param items - Array of string items to render
     * @param ordered - When `true`, renders a numbered list (`1.`, `2.`, …); defaults to `false` (bulleted)
     * @returns this builder for chaining
     *
     * @example
     * ```typescript
     * markdown().list(['alpha', 'beta', 'gamma']).build();
     * // - alpha
     * // - beta
     * // - gamma
     *
     * markdown().list(['first', 'second'], true).build();
     * // 1. first
     * // 2. second
     * ```
     */
    list(items, ordered = false) {
        if (items.length === 0)
            return this;
        const marker = ordered ? (i) => `${i + 1}.` : () => '-';
        this.sections.push(`${items.map((item, i) => `${marker(i)} ${item}`).join('\n')}\n\n`);
        return this;
    }
    /**
     * Add a fenced code block with optional syntax highlighting.
     *
     * @param content - The code content placed verbatim inside the fence
     * @param language - Language identifier for syntax highlighting (e.g. `'typescript'`, `'json'`, `'diff'`); defaults to no language
     * @returns this builder for chaining
     *
     * @example
     * ```typescript
     * markdown().codeBlock('const x = 1;', 'typescript').build();
     * // ```typescript
     * // const x = 1;
     * // ```
     * ```
     */
    codeBlock(content, language = '') {
        this.sections.push(`\`\`\`${language}\n${content}\n\`\`\`\n\n`);
        return this;
    }
    /**
     * Append inline code wrapped in single backticks (`` `code` ``).
     * No trailing newline is added — suitable for inline use within a sentence.
     *
     * @param code - The code text to wrap
     * @returns this builder for chaining
     *
     * @example
     * ```typescript
     * markdown().text('Call ').inlineCode('build()').text(' when done.').build();
     * // Call `build()` when done.
     * ```
     */
    inlineCode(code) {
        this.sections.push(`\`${code}\``);
        return this;
    }
    /**
     * Add a paragraph of text followed by two newlines.
     *
     * @param text - The paragraph content
     * @returns this builder for chaining
     *
     * @example
     * ```typescript
     * markdown().paragraph('Hello world.').paragraph('Second paragraph.').build();
     * // Hello world.
     * //
     * // Second paragraph.
     * ```
     */
    paragraph(text) {
        this.sections.push(`${text}\n\n`);
        return this;
    }
    /**
     * Add a blockquote. Each line of `text` is prefixed with `> `.
     *
     * @param text - The quoted text; multi-line strings are handled correctly
     * @returns this builder for chaining
     *
     * @example
     * ```typescript
     * markdown().blockquote('Line one\nLine two').build();
     * // > Line one
     * // > Line two
     * ```
     */
    blockquote(text) {
        const lines = text.split('\n');
        const quoted = lines.map((line) => `> ${line}`).join('\n');
        this.sections.push(`${quoted}\n\n`);
        return this;
    }
    /**
     * Add a horizontal rule.
     * @returns this builder for chaining
     */
    hr() {
        this.sections.push('---\n\n');
        return this;
    }
    /**
     * Append an inline markdown link (`[text](url)`).
     * No trailing newline is added — suitable for inline use within a sentence.
     *
     * @param text - The visible link label
     * @param url - The link target URL
     * @returns this builder for chaining
     *
     * @example
     * ```typescript
     * markdown().text('See ').link('the docs', 'https://example.com').text(' for details.').build();
     * // See [the docs](https://example.com) for details.
     * ```
     */
    link(text, url) {
        this.sections.push(`[${text}](${url})`);
        return this;
    }
    /**
     * Add a GFM-style table. Returns without modification if `headers` or `rows` is empty.
     * All separator cells use `---`; no alignment syntax is applied.
     *
     * @param headers - Column header labels
     * @param rows - Data rows; each inner array should have the same length as `headers`
     * @returns this builder for chaining
     *
     * @example
     * ```typescript
     * markdown().table(['Name', 'Status'], [['foo', 'ok'], ['bar', 'fail']]).build();
     * // | Name | Status |
     * // | --- | --- |
     * // | foo | ok |
     * // | bar | fail |
     * ```
     */
    table(headers, rows) {
        if (headers.length === 0 || rows.length === 0)
            return this;
        // Header row
        this.sections.push(`| ${headers.join(' | ')} |\n`);
        // Separator row
        this.sections.push(`| ${headers.map(() => '---').join(' | ')} |\n`);
        // Data rows
        rows.forEach((row) => {
            this.sections.push(`| ${row.join(' | ')} |\n`);
        });
        this.sections.push('\n');
        return this;
    }
    section(title, levelOrContent, content) {
        let level;
        let callback;
        if (typeof levelOrContent === 'function') {
            level = 2;
            callback = levelOrContent;
        }
        else {
            level = levelOrContent;
            // Safe: the overload signatures guarantee content is provided when level is a number
            callback = content ?? (() => { });
        }
        switch (level) {
            case 2:
                this.h2(title);
                break;
            case 3:
                this.h3(title);
                break;
            case 4:
                this.h4(title);
                break;
        }
        callback();
        return this;
    }
    /**
     * Add a collapsible `<details>`/`<summary>` HTML block.
     * The `summary` is always visible; `details` content is collapsed by default.
     * Not all markdown renderers support this — GitHub and GitLab do.
     *
     * @param summary - The always-visible summary label
     * @param details - The collapsible body content (plain text or markdown)
     * @returns this builder for chaining
     *
     * @example
     * ```typescript
     * markdown().details('Show stack trace', 'Error: something went wrong\n  at foo.ts:10').build();
     * // <details>
     * // <summary>Show stack trace</summary>
     * //
     * // Error: something went wrong
     * //   at foo.ts:10
     * //
     * // </details>
     * ```
     */
    details(summary, details) {
        this.sections.push(`<details>\n<summary>${summary}</summary>\n\n`);
        this.sections.push(`${details}\n\n`);
        this.sections.push(`</details>\n\n`);
        return this;
    }
    /**
     * Add a status/alert box (GitHub/GitLab style).
     * Renders as a highlighted blockquote with an icon.
     *
     * Supported types:
     * - 'note': 📝 Neutral information
     * - 'tip': 💡 Helpful suggestions
     * - 'important': ❗ Critical information
     * - 'warning': ⚠️ Warning/caution
     * - 'caution': 🚨 Danger/destructive action
     *
     * @param type - Alert type
     * @param content - Alert content (can be multi-line)
     * @returns this builder for chaining
     *
     * @example
     * ```typescript
     * md.alert('warning', 'This operation cannot be undone!');
     * // Renders: > [!WARNING]
     * //          > This operation cannot be undone!
     * ```
     */
    alert(type, content) {
        const typeUpper = type.toUpperCase();
        const lines = content.split('\n');
        this.sections.push(`> [!${typeUpper}]\n`);
        lines.forEach((line) => {
            this.sections.push(`> ${line}\n`);
        });
        this.sections.push('\n');
        return this;
    }
    /**
     * Add a task list with checkboxes (GitHub style).
     *
     * @param items - Array of tasks with checked status
     * @returns this builder for chaining
     *
     * @example
     * ```typescript
     * md.taskList([
     *   { checked: true, text: 'Complete setup' },
     *   { checked: false, text: 'Run tests' },
     * ]);
     * // Renders: - [x] Complete setup
     * //          - [ ] Run tests
     * ```
     */
    taskList(items) {
        if (items.length === 0)
            return this;
        this.sections.push(`${items.map((item) => `- [${item.checked ? 'x' : ' '}] ${item.text}`).join('\n')}\n\n`);
        return this;
    }
    /**
     * Add an image with alt text and optional title.
     *
     * @param altText - Alternative text for the image
     * @param url - Image URL
     * @param title - Optional title (shown on hover)
     * @returns this builder for chaining
     *
     * @example
     * ```typescript
     * md.image('Architecture diagram', '/assets/diagram.png', 'System Architecture');
     * // Renders: ![Architecture diagram](/assets/diagram.png "System Architecture")
     * ```
     */
    image(altText, url, title) {
        const titlePart = title ? ` "${title}"` : '';
        this.sections.push(`![${altText}](${url}${titlePart})\n\n`);
        return this;
    }
    /**
     * Add strikethrough text.
     *
     * @param text - Text to strike through
     * @returns this builder for chaining
     *
     * @example
     * ```typescript
     * md.text('Price: ').strikethrough('$100').text(' $80');
     * // Renders: Price: ~~$100~~ $80
     * ```
     */
    strikethrough(text) {
        this.sections.push(`~~${text}~~`);
        return this;
    }
    /**
     * Add a `diff`-language fenced code block showing additions and deletions.
     * Rendering order: context lines (two-space indent) → deletions (`- ` prefix) → additions (`+ ` prefix).
     * If all three arrays are empty or omitted, nothing is appended.
     *
     * @param changes - Line arrays for the diff
     * @param changes.context - Unchanged context lines (rendered with two-space indent)
     * @param changes.deletions - Removed lines (rendered with `- ` prefix)
     * @param changes.additions - Added lines (rendered with `+ ` prefix)
     * @returns this builder for chaining
     *
     * @example
     * ```typescript
     * markdown().diff({
     *   context: ['// Configuration'],
     *   deletions: ['const oldFeature = false;'],
     *   additions: ['const newFeature = true;'],
     * }).build();
     * // ```diff
     * //   // Configuration
     * // - const oldFeature = false;
     * // + const newFeature = true;
     * // ```
     * ```
     */
    diff(changes) {
        const lines = [];
        // Context lines (no prefix)
        if (changes.context) {
            lines.push(...changes.context.map((line) => `  ${line}`));
        }
        // Deletions (- prefix)
        if (changes.deletions) {
            lines.push(...changes.deletions.map((line) => `- ${line}`));
        }
        // Additions (+ prefix)
        if (changes.additions) {
            lines.push(...changes.additions.map((line) => `+ ${line}`));
        }
        if (lines.length > 0) {
            this.codeBlock(lines.join('\n'), 'diff');
        }
        return this;
    }
    /**
     * Add a badge/shield (uses shields.io style).
     *
     * @param label - Badge label (left side)
     * @param message - Badge message (right side)
     * @param color - Optional color (e.g., 'green', 'red', 'blue', 'yellow')
     * @returns this builder for chaining
     *
     * @example
     * ```typescript
     * md.badge('build', 'passing', 'green');
     * // Renders: ![build: passing](https://img.shields.io/badge/build-passing-green)
     * ```
     */
    badge(label, message, color = 'blue') {
        const encodedLabel = encodeURIComponent(label);
        const encodedMessage = encodeURIComponent(message);
        const url = `https://img.shields.io/badge/${encodedLabel}-${encodedMessage}-${color}`;
        this.sections.push(`![${label}: ${message}](${url})`);
        return this;
    }
    /**
     * Add bold text.
     *
     * @param text - Text to make bold
     * @returns this builder for chaining
     *
     * @example
     * ```typescript
     * md.text('This is ').bold('important').text(' information.');
     * // Renders: This is **important** information.
     * ```
     */
    bold(text) {
        this.sections.push(`**${text}**`);
        return this;
    }
    /**
     * Add italic text.
     *
     * @param text - Text to make italic
     * @returns this builder for chaining
     *
     * @example
     * ```typescript
     * md.text('This is ').italic('emphasized').text('.');
     * // Renders: This is *emphasized*.
     * ```
     */
    italic(text) {
        this.sections.push(`*${text}*`);
        return this;
    }
    /**
     * Add bold and italic text.
     *
     * @param text - Text to make bold and italic
     * @returns this builder for chaining
     *
     * @example
     * ```typescript
     * md.boldItalic('Very important');
     * // Renders: ***Very important***
     * ```
     */
    boldItalic(text) {
        this.sections.push(`***${text}***`);
        return this;
    }
    /**
     * Append a raw markdown string directly to the buffer without any transformation.
     * Use this for custom formatting not covered by other methods.
     *
     * @param markdown - Raw markdown string appended verbatim
     * @returns this builder for chaining
     *
     * @example
     * ```typescript
     * markdown().raw('> custom blockquote\n\n').build();
     * // > custom blockquote
     * ```
     */
    raw(markdown) {
        this.sections.push(markdown);
        return this;
    }
    /**
     * Add a blank line for spacing.
     * @returns this builder for chaining
     */
    blankLine() {
        this.sections.push('\n');
        return this;
    }
    /**
     * Append plain text without any markdown formatting or implicit line breaks.
     * Useful for building inline content by interleaving with methods like
     * {@link bold}, {@link italic}, {@link inlineCode}, and {@link link}.
     *
     * @param text - The text to append verbatim
     * @returns this builder for chaining
     *
     * @example
     * ```typescript
     * markdown().text('Result: ').bold('42').text(' items found.').build();
     * // Result: **42** items found.
     * ```
     */
    text(text) {
        this.sections.push(text);
        return this;
    }
    /**
     * Conditionally append content. The callback is invoked synchronously only when
     * `condition` is `true`; otherwise the builder is returned unchanged.
     *
     * @param condition - When `true`, the callback is invoked
     * @param content - Callback that appends content to this builder
     * @returns this builder for chaining
     *
     * @example
     * ```typescript
     * md.when(files.length > 0, () => {
     *   md.h2('Files Changed').list(files);
     * });
     * ```
     */
    when(condition, content) {
        if (condition) {
            content();
        }
        return this;
    }
    /**
     * Concatenate all buffered sections and return the final markdown string.
     * Leading and trailing whitespace is trimmed so documents always end cleanly.
     * The builder instance is NOT reset — call {@link reset} explicitly if reuse is needed.
     *
     * @returns The complete markdown document as a trimmed string
     *
     * @example
     * ```typescript
     * const output = markdown().h1('Hello').paragraph('World').build();
     * // '# Hello\n\nWorld'
     * ```
     */
    build() {
        return this.sections.join('').trim();
    }
    /**
     * Clear all buffered content so the builder can be reused for a new document.
     *
     * @returns this builder for chaining
     *
     * @example
     * ```typescript
     * const md = markdown().h1('Draft');
     * md.reset().h1('Final').build();   // '# Final'
     * ```
     */
    reset() {
        this.sections = [];
        return this;
    }
}
/**
 * Factory function that creates a new {@link MarkdownBuilder} instance.
 * Prefer this over `new MarkdownBuilder()` for concise call-site syntax.
 *
 * @returns A fresh, empty `MarkdownBuilder`
 *
 * @example
 * ```typescript
 * import { markdown } from '@cyanheads/mcp-ts-core/utils';
 *
 * const output = markdown()
 *   .h1('Summary')
 *   .keyValue('Total', 5)
 *   .build();
 * ```
 */
export function markdown() {
    return new MarkdownBuilder();
}
//# sourceMappingURL=markdownBuilder.js.map