/** Lightweight syntax highlighting — returns HTML strings with <span class="hl-*"> tokens */

function esc(s: string): string {
	return s.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
}

function restoreTokens(source: string, tokens: string[]): string {
	let result = source;
	let prev = '';
	while (result !== prev) {
		prev = result;
		result = result.replace(/__HL_(\d+)__/g, (_m, idx) => tokens[Number(idx)] ?? '');
	}
	return result;
}

/** Highlight systemd journal / nanoclaw logs */
export function highlightLogs(text: string): string {
	function stash(
		source: string,
		pattern: RegExp,
		render: (...args: string[]) => string,
		store: string[]
	): string {
		return source.replace(pattern, (...args) => {
			const html = render(...(args.slice(1, -2) as string[]));
			const token = `__HL_${store.length}__`;
			store.push(html);
			return token;
		});
	}

	return text
		.split('\n')
		.map((line) => {
			const tokens: string[] = [];
			let result = esc(line);

			result = stash(
				result,
				/^(\S+\s+\d+\s+[\d:]+|\d{4}-\d{2}-\d{2}T[\d:.]+\S*)/,
				(value) => `<span class="hl-date">${value}</span>`,
				tokens
			);

			result = stash(
				result,
				/^(__HL_\d+__\s+)(\S+)\s+([\w.-]+\[\d+\]:?)/,
				(prefix, host, tag) => `${prefix}<span class="hl-host">${host}</span> <span class="hl-tag">${tag}</span>`,
				tokens
			);

			result = stash(
				result,
				/"([^"]*)"/g,
				(value) => `"<span class="hl-str">${value}</span>"`,
				tokens
			);

			result = stash(
				result,
				/\b(\d+(?:\.\d+)?(?:ms|s|MB|GB|KB|%))\b/g,
				(value) => `<span class="hl-num">${value}</span>`,
				tokens
			);

			result = stash(
				result,
				/(\/[\w./-]+)/g,
				(value) => `<span class="hl-path">${value}</span>`,
				tokens
			);

			result = stash(
				result,
				/\b(error|Error|ERROR|FATAL|fatal|panic|PANIC|fail|FAIL|Failed)\b/g,
				(value) => `<span class="hl-err">${value}</span>`,
				tokens
			);

			result = stash(
				result,
				/\b(warn|WARN|warning|WARNING)\b/g,
				(value) => `<span class="hl-warn">${value}</span>`,
				tokens
			);

			result = stash(
				result,
				/\b(info|INFO|started|Started|success|SUCCESS|active|running)\b/gi,
				(value) => `<span class="hl-info">${value}</span>`,
				tokens
			);

			return restoreTokens(result, tokens);
		})
		.join('\n');
}

/** Highlight Caddyfile syntax */
export function highlightCaddyfile(text: string): string {
	function stash(
		source: string,
		pattern: RegExp,
		render: (...args: string[]) => string,
		store: string[]
	): string {
		return source.replace(pattern, (...args) => {
			const html = render(...(args.slice(1, -2) as string[]));
			const token = `__HL_${store.length}__`;
			store.push(html);
			return token;
		});
	}

	return text
		.split('\n')
		.map((line) => {
			// Comments
			if (/^\s*#/.test(line)) {
				return `<span class="hl-comment">${esc(line)}</span>`;
			}

			const commentIdx = line.indexOf('#');
			const codePart = commentIdx >= 0 ? line.slice(0, commentIdx) : line;
			const commentPart = commentIdx >= 0 ? line.slice(commentIdx) : '';
			const tokens: string[] = [];

			let result = esc(codePart);

			result = stash(
				result,
				/"([^"]*)"/g,
				(content) => `"<span class="hl-str">${content}</span>"`,
				tokens
			);
			result = stash(
				result,
				/\{([\w.]+)\}/g,
				(name) => `<span class="hl-placeholder">{${name}}</span>`,
				tokens
			);
			result = stash(
				result,
				/(https?:\/\/[\w.:/-]+|localhost:\d+)/g,
				(url) => `<span class="hl-url">${url}</span>`,
				tokens
			);

			result = result.replace(/^(\s*)(import)(\s+)(\S+)/, (_m, indent, directive, space, target) =>
				`${indent}<span class="hl-directive">${directive}</span>${space}<span class="hl-path">${target}</span>`
			);

			result = result.replace(/^(\s+)([\w_-]+)/, '$1<span class="hl-directive">$2</span>');

			result = result.replace(
				/^(\s*)([^\s{][^{]*?)(\s*)(\{)?$/,
				(_m, indent, site, space, brace) => {
					const trimmedSite = site.trim();
					if (!trimmedSite || trimmedSite.startsWith('<span')) return _m;
					if (!/[.:]/.test(trimmedSite)) return _m;
					const trailing = brace ? `${space}__HL_BRACE_OPEN__` : '';
					return `${indent}<span class="hl-domain">${trimmedSite}</span>${trailing}`;
				}
			);

			result = result.replace(/\{/g, '<span class="hl-brace">{</span>');
			result = result.replace(/\}/g, '<span class="hl-brace">}</span>');
			result = result.replace(/__HL_BRACE_OPEN__/g, '<span class="hl-brace">{</span>');

			result = restoreTokens(result, tokens);

			if (commentPart) {
				result += `<span class="hl-comment">${esc(commentPart)}</span>`;
			}

			return result;
		})
		.join('\n');
}
