'use client';
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import javascriptLang from '@shikijs/langs/javascript';
import jsonLang from '@shikijs/langs/json';
import typescriptLang from '@shikijs/langs/typescript';
import themeDarkModule from '@shikijs/themes/dark-plus';
import themeLightModule from '@shikijs/themes/light-plus';
import { CheckIcon, CopyIcon } from 'lucide-react';
import { createContext, useContext, useEffect, useRef, useState, } from 'react';
import { createHighlighterCore } from 'shiki/core';
import { createOnigurumaEngine } from 'shiki/engine/oniguruma';
import { cn } from '../../lib/utils';
import { Button } from '../ui/button';
import { Tooltip, TooltipContent, TooltipTrigger } from '../ui/tooltip';
// Extract theme objects from default exports
const themeLight = ('default' in themeLightModule ? themeLightModule.default : themeLightModule);
const themeDark = ('default' in themeDarkModule ? themeDarkModule.default : themeDarkModule);
const CodeBlockContext = createContext({
    code: '',
});
// Initialize highlighter with only the languages and themes we need
let highlighterPromise = null;
function getHighlighter() {
    if (!highlighterPromise) {
        highlighterPromise = createHighlighterCore({
            themes: [themeLight, themeDark],
            langs: [jsonLang, javascriptLang, typescriptLang],
            engine: createOnigurumaEngine(import('shiki/wasm')),
        });
    }
    return highlighterPromise;
}
const lineNumberTransformer = {
    name: 'line-numbers',
    line(node, line) {
        node.children.unshift({
            type: 'element',
            tagName: 'span',
            properties: {
                className: [
                    'inline-block',
                    'min-w-10',
                    'mr-4',
                    'text-right',
                    'select-none',
                    'text-muted-foreground',
                ],
            },
            children: [{ type: 'text', value: String(line) }],
        });
    },
};
export async function highlightCode(code, language, showLineNumbers = false) {
    const highlighter = await getHighlighter();
    const transformers = showLineNumbers ? [lineNumberTransformer] : [];
    return [
        highlighter.codeToHtml(code, {
            lang: language,
            theme: themeLight.name ?? 'github-light',
            transformers,
        }),
        highlighter.codeToHtml(code, {
            lang: language,
            theme: themeDark.name ?? 'github-dark',
            transformers,
        }),
    ];
}
export const CodeBlock = ({ code, language, showLineNumbers = false, className, children, ...props }) => {
    const [lightHtml, setLightHtml] = useState('');
    const [darkHtml, setDarkHtml] = useState('');
    const mounted = useRef(false);
    useEffect(() => {
        highlightCode(code, language, showLineNumbers).then(([light, dark]) => {
            if (!mounted.current) {
                setLightHtml(light);
                setDarkHtml(dark);
                mounted.current = true;
            }
        });
        return () => {
            mounted.current = false;
        };
    }, [code, language, showLineNumbers]);
    const baseClass = 'overflow-hidden [&>pre]:m-0 [&>pre]:bg-background! [&>pre]:p-4 [&>pre]:text-foreground! [&>pre]:text-sm [&>pre]:whitespace-pre-wrap [&_code]:font-mono [&_code]:text-sm';
    return (_jsx(CodeBlockContext.Provider, { value: { code }, children: _jsx("div", { className: cn('group relative w-full overflow-hidden rounded-md border bg-background text-foreground', className), ...props, children: _jsxs("div", { className: "relative", children: [_jsx("div", { className: cn(baseClass, 'dark:hidden'), 
                        // biome-ignore lint/security/noDangerouslySetInnerHtml: must be added via this method as per the library
                        dangerouslySetInnerHTML: { __html: lightHtml } }), _jsx("div", { className: cn(baseClass, 'hidden dark:block'), 
                        // biome-ignore lint/security/noDangerouslySetInnerHtml: must be added via this method as per the library
                        dangerouslySetInnerHTML: { __html: darkHtml } }), children && (_jsx("div", { className: "absolute top-1 right-1 flex items-center gap-2", children: children }))] }) }) }));
};
export const CodeBlockCopyButton = ({ onCopy, onError, timeout = 2000, children, className, ...props }) => {
    const [isCopied, setIsCopied] = useState(false);
    const { code } = useContext(CodeBlockContext);
    const copyToClipboard = async () => {
        if (typeof window === 'undefined' || !navigator?.clipboard?.writeText) {
            onError?.(new Error('Clipboard API not available'));
            return;
        }
        try {
            await navigator.clipboard.writeText(code);
            setIsCopied(true);
            onCopy?.();
            setTimeout(() => setIsCopied(false), timeout);
        }
        catch (error) {
            onError?.(error);
        }
    };
    const Icon = isCopied ? CheckIcon : CopyIcon;
    return (_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx(Button, { className: cn('size-7 shrink-0 rounded-sm', className), onClick: copyToClipboard, size: "icon", variant: "ghost", ...props, children: children ?? _jsx(Icon, { size: 14 }) }) }), _jsx(TooltipContent, { children: "Copy to clipboard" })] }));
};
//# sourceMappingURL=code-block.js.map