import { chunkMarkdownIR, markdownToIR } from "../../../src/markdown/ir.js";
import { renderMarkdownWithMarkers } from "../../../src/markdown/render.js";
import "../../../src/markdown/index.js";
//#region extensions/telegram/src/format.ts
/**
* Telegram Message Formatting Utilities
*
* Converts Markdown to Telegram HTML format using the robust @src/markdown/ package.
* Markdown → Telegram HTML via the shared markdown IR pipeline.
*/
const TELEGRAM_STYLE_MARKERS = {
	bold: {
		open: "<b>",
		close: "</b>"
	},
	italic: {
		open: "<i>",
		close: "</i>"
	},
	strikethrough: {
		open: "<s>",
		close: "</s>"
	},
	code: {
		open: "<code>",
		close: "</code>"
	},
	code_block: {
		open: "<pre><code>",
		close: "</code></pre>"
	},
	spoiler: {
		open: "<tg-spoiler>",
		close: "</tg-spoiler>"
	},
	blockquote: {
		open: "<blockquote>",
		close: "</blockquote>"
	}
};
/**
* Escape HTML special characters
*/
function escapeHtml(text) {
	return text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
}
/**
* Escape HTML attribute values
*/
function escapeHtmlAttr(text) {
	return escapeHtml(text).replace(/"/g, "&quot;");
}
/**
* Build a link renderer for Telegram HTML
*/
function buildTelegramLinkRenderer(_irText) {
	return (link, _text) => {
		const href = link.href.trim();
		if (!href) return null;
		if (!/^(https?|tg|mailto):/i.test(href) && !href.startsWith("#")) return null;
		return {
			start: link.start,
			end: link.end,
			open: `<a href="${escapeHtmlAttr(href)}">`,
			close: "</a>"
		};
	};
}
/**
* Strip or escape unknown HTML tags that Telegram doesn't support
* Telegram only supports: b, strong, i, em, u, ins, s, strike, del, tg-spoiler,
* a, pre, code, blockquote, br
*/
const TELEGRAM_ALLOWED_TAGS = new Set([
	"b",
	"strong",
	"i",
	"em",
	"u",
	"ins",
	"s",
	"strike",
	"del",
	"tg-spoiler",
	"a",
	"pre",
	"code",
	"blockquote",
	"br"
]);
function stripUnknownHtmlTags(html) {
	let processed = html.replace(/&lt;(\/?)([a-zA-Z][a-zA-Z0-9-]*)([^&]*?)&gt;/gi, (match, slash, tagName, attrs) => {
		const normalizedTag = tagName.toLowerCase();
		if (TELEGRAM_ALLOWED_TAGS.has(normalizedTag)) {
			const decodedAttrs = attrs.replace(/&quot;/g, "\"").replace(/&amp;/g, "&").replace(/&lt;/g, "<").replace(/&gt;/g, ">").trim();
			if (decodedAttrs) return `<${slash}${normalizedTag} ${decodedAttrs}>`;
			return `<${slash}${normalizedTag}>`;
		}
		return "";
	});
	processed = processed.replace(/<(\/?)([a-zA-Z][a-zA-Z0-9-]*)([^>]*?)>/gi, (match, slash, tagName, attrs) => {
		const normalizedTag = tagName.toLowerCase();
		if (TELEGRAM_ALLOWED_TAGS.has(normalizedTag)) {
			if (attrs.trim()) return `<${slash}${normalizedTag} ${attrs.trim()}>`;
			return `<${slash}${normalizedTag}>`;
		}
		return "";
	});
	return processed;
}
/**
* Render Markdown IR to Telegram HTML
*/
function renderIRToTelegramHtml(ir) {
	let html = renderMarkdownWithMarkers(ir, {
		styleMarkers: TELEGRAM_STYLE_MARKERS,
		escapeText: escapeHtml,
		buildLink: buildTelegramLinkRenderer(ir.text)
	});
	html = stripUnknownHtmlTags(html);
	return html;
}
/**
* Convert markdown to Telegram HTML
*/
function markdownToTelegramHtml(markdown, options = {}) {
	return renderIRToTelegramHtml(markdownToIR(markdown, {
		linkify: true,
		enableSpoilers: options.enableSpoilers ?? true,
		tableMode: options.tableMode ?? "off"
	}));
}
/**
* Convert markdown to plain text (strip formatting)
*/
function markdownToPlainText(markdown) {
	const ir = markdownToIR(markdown, {
		linkify: true,
		enableSpoilers: true
	});
	let result = ir.text;
	const sortedLinks = [...ir.links].sort((a, b) => b.start - a.start);
	for (const link of sortedLinks) {
		const replacement = `${ir.text.slice(link.start, link.end)} (${link.href})`;
		result = result.slice(0, link.start) + replacement + result.slice(link.end);
	}
	return result;
}
/**
* Convert markdown to Telegram HTML chunks
* Splits long messages while preserving structure
*/
function markdownToTelegramChunks(markdown, limit = 4e3) {
	return chunkMarkdownIR(markdownToIR(markdown, {
		linkify: true,
		enableSpoilers: true
	}), limit).map((chunk) => ({
		html: renderIRToTelegramHtml(chunk),
		text: chunk.text
	}));
}
/**
* Render markdown to Telegram HTML (single message)
* Supports both markdown and HTML input modes
*/
function renderTelegramHtmlText(text, options = {}) {
	if ((options.textMode ?? "markdown") === "html") return text;
	return renderIRToTelegramHtml(markdownToIR(text, {
		linkify: true,
		enableSpoilers: options.enableSpoilers ?? true
	}));
}
const FILE_EXTENSIONS_WITH_TLD = new Set([
	"md",
	"go",
	"py",
	"pl",
	"sh",
	"am",
	"at",
	"be",
	"cc"
]);
/**
* Wrap standalone file references in <code> tags
* Prevents Telegram from generating domain registrar previews
*/
function wrapFileReferencesInHtml(html) {
	let codeDepth = 0;
	let preDepth = 0;
	let anchorDepth = 0;
	let result = "";
	let lastIndex = 0;
	const HTML_TAG_PATTERN = /(<\/?)([a-zA-Z][a-zA-Z0-9-]*)\b[^>]*?>/gi;
	let match;
	while ((match = HTML_TAG_PATTERN.exec(html)) !== null) {
		const tagStart = match.index;
		const tagEnd = tagStart + match[0].length;
		const tagName = match[2].toLowerCase();
		const isClosing = match[1] === "</";
		if (tagStart > lastIndex) {
			const textSegment = html.slice(lastIndex, tagStart);
			result += wrapSegmentFileRefs(textSegment, codeDepth, preDepth, anchorDepth);
		}
		if (tagName === "code") codeDepth += isClosing ? -1 : 1;
		else if (tagName === "pre") preDepth += isClosing ? -1 : 1;
		else if (tagName === "a") anchorDepth += isClosing ? -1 : 1;
		result += match[0];
		lastIndex = tagEnd;
	}
	if (lastIndex < html.length) {
		const textSegment = html.slice(lastIndex);
		result += wrapSegmentFileRefs(textSegment, codeDepth, preDepth, anchorDepth);
	}
	return result;
}
/**
* Wrap file references in a text segment (respecting nesting depth)
*/
function wrapSegmentFileRefs(text, codeDepth, preDepth, anchorDepth) {
	if (!text || codeDepth > 0 || preDepth > 0 || anchorDepth > 0) return text;
	const FILE_EXTENSIONS_PATTERN = Array.from(FILE_EXTENSIONS_WITH_TLD).join("|");
	const FILE_REFERENCE_PATTERN = new RegExp(`(^|[^a-zA-Z0-9_\\-/])([a-zA-Z0-9_.\\-./]+\\.(?:${FILE_EXTENSIONS_PATTERN}))(?=$|[^a-zA-Z0-9_\\-/])`, "gi");
	return text.replace(FILE_REFERENCE_PATTERN, (match, prefix, filename) => {
		if (filename.startsWith("//")) return match;
		if (/https?:\/\/$/i.test(prefix)) return match;
		return `${prefix}<code>${escapeHtml(filename)}</code>`;
	});
}
/**
* Format message for Telegram with proper HTML and file reference protection
*/
function formatTelegramMessage(markdown, options = {}) {
	const html = renderTelegramHtmlText(markdown, { textMode: options.textMode });
	return {
		html: options.wrapFileRefs !== false ? wrapFileReferencesInHtml(html) : html,
		text: markdown
	};
}
/**
* Smart split message into chunks with both HTML and plain text
* Uses Markdown IR for robust chunking that preserves structure
*/
function splitTelegramMessageSmart(markdown, maxChars = 4e3) {
	return markdownToTelegramChunks(markdown, maxChars);
}
/**
* Validate HTML string for Telegram parse_mode
* Returns true if the HTML appears to be valid
*/
function isValidTelegramHtml(html) {
	const voidElements = new Set([
		"br",
		"hr",
		"img",
		"input",
		"link",
		"meta",
		"area",
		"base",
		"col",
		"embed",
		"param",
		"source",
		"track",
		"wbr"
	]);
	const openTags = [];
	let i = 0;
	while (i < html.length) if (html[i] === "<" && i + 1 < html.length && html[i + 1] !== "!") {
		let tagEnd = html.indexOf(">", i);
		if (tagEnd === -1) return false;
		const fullTag = html.slice(i, tagEnd + 1);
		if (fullTag.startsWith("<!") || fullTag.startsWith("<!--")) {
			const commentEnd = html.indexOf("-->", i);
			if (commentEnd !== -1) i = commentEnd + 3;
			else return false;
			continue;
		}
		const isClosing = fullTag.startsWith("</");
		const tagName = fullTag.slice(isClosing ? 2 : 1, -1).trim().toLowerCase().split(/\s/)[0];
		if (!tagName) {
			i = tagEnd + 1;
			continue;
		}
		if (voidElements.has(tagName)) {} else if (isClosing) {
			const lastIndex = openTags.lastIndexOf(tagName);
			if (lastIndex === -1) return false;
			openTags.splice(lastIndex + 1);
			openTags.pop();
		} else openTags.push(tagName);
		i = tagEnd + 1;
	} else i++;
	return openTags.length === 0;
}
/**
* Fix malformed HTML tags by ensuring proper nesting
* This handles cases where LLM generates invalid HTML
*/
function fixMalformedHtml(html) {
	const result = [];
	const openTags = [];
	let i = 0;
	const voidElements = new Set([
		"br",
		"hr",
		"img",
		"input",
		"link",
		"meta",
		"area",
		"base",
		"col",
		"embed",
		"param",
		"source",
		"track",
		"wbr"
	]);
	const inlineTags = new Set([
		"a",
		"b",
		"i",
		"code",
		"s",
		"strike",
		"del",
		"u",
		"em",
		"strong",
		"span",
		"tg-spoiler"
	]);
	while (i < html.length) if (html[i] === "<" && i + 1 < html.length && html[i + 1] !== "!") {
		let tagEnd = html.indexOf(">", i);
		if (tagEnd === -1) {
			result.push(html.slice(i));
			break;
		}
		const fullTag = html.slice(i, tagEnd + 1);
		if (fullTag.startsWith("<!") || fullTag.startsWith("<!--")) {
			const commentEnd = html.indexOf("-->", i);
			if (commentEnd !== -1) i = commentEnd + 3;
			else {
				result.push(html.slice(i));
				break;
			}
			continue;
		}
		if (fullTag.startsWith("</")) {
			const tagName = fullTag.slice(2, -1).trim().toLowerCase().split(/\s/)[0];
			if (voidElements.has(tagName)) result.push(escapeHtml(fullTag));
			else {
				const lastIndex = openTags.lastIndexOf(tagName);
				if (lastIndex !== -1) {
					while (openTags.length > lastIndex + 1) {
						const tagToClose = openTags.pop();
						result.push(`</${tagToClose}>`);
					}
					openTags.pop();
					result.push(fullTag);
				} else result.push(escapeHtml(fullTag));
			}
		} else if (fullTag.endsWith("/>") || voidElements.has(fullTag.slice(1, -1).trim().toLowerCase().split(/\s/)[0])) result.push(fullTag);
		else {
			const tagName = fullTag.slice(1, -1).trim().toLowerCase().split(/\s/)[0];
			if (tagName && (inlineTags.has(tagName) || tagName === "pre" || tagName === "blockquote")) openTags.push(tagName);
			result.push(fullTag);
		}
		i = tagEnd + 1;
	} else {
		result.push(html[i]);
		i++;
	}
	while (openTags.length > 0) result.push(`</${openTags.pop()}>`);
	return result.join("");
}
//#endregion
export { escapeHtml, escapeHtmlAttr, fixMalformedHtml, formatTelegramMessage, isValidTelegramHtml, markdownToPlainText, markdownToTelegramChunks, markdownToTelegramHtml, renderIRToTelegramHtml, renderTelegramHtmlText, splitTelegramMessageSmart, stripUnknownHtmlTags, wrapFileReferencesInHtml };

//# sourceMappingURL=format.js.map