<script lang="ts" context="module">
	import type { renderToString as katexRenderToString } from 'katex';

	// Module-level singleton: load katex once, share across all KatexRenderer instances
	let katexRenderer: Promise<typeof katexRenderToString> | null = null;
	function getKatexRenderer(): Promise<typeof katexRenderToString> {
		if (!katexRenderer) {
			katexRenderer = Promise.all([
				import('katex'),
				import('katex/contrib/mhchem'),
				import('katex/dist/katex.min.css')
			]).then(([katex]) => katex.renderToString);
		}
		return katexRenderer;
	}
</script>

<script lang="ts">
	import { onMount, getContext } from 'svelte';
	import { copyToClipboard } from '$lib/utils';
	import { toast } from 'svelte-sonner';

	const i18n = getContext('i18n');

	export let content: string;
	export let displayMode: boolean = false;

	let renderToString: typeof katexRenderToString | null = null;

	onMount(async () => {
		renderToString = await getKatexRenderer();
	});

	// Cache rendered HTML — only re-compute when content, displayMode, or renderToString changes,
	// not on every parent re-render during streaming
	let renderedHTML: string = '';
	$: if (renderToString) {
		try {
			renderedHTML = renderToString(content, { displayMode, throwOnError: false });
		} catch {
			renderedHTML = content;
		}
	}
</script>

{#if renderToString && renderedHTML}
	<!-- svelte-ignore a11y-click-events-have-key-events -->
	<!-- svelte-ignore a11y-no-static-element-interactions -->
	<svelte:element
		this={displayMode ? 'div' : 'span'}
		class="cursor-pointer"
		on:click={() => {
			copyToClipboard(content);
			toast.success($i18n.t('Copied to clipboard'));
		}}
	>
		{@html renderedHTML}
	</svelte:element>
{/if}
