import { jsx } from "react/jsx-runtime";
import "katex/dist/katex.min.css";
import { useLingui } from "@lingui/react";
import { styled } from "@mui/material";
import apollo_core from "@uipath/apollo-core";
import react from "react";
import react_markdown from "react-markdown";
import rehype_katex from "rehype-katex";
import remark_gfm from "remark-gfm";
import remark_math from "remark-math";
import { useIsStreamingMessage } from "../../../hooks/use-is-streaming-message.js";
import { useChatService } from "../../../providers/chat-service.provider.js";
import { useChatState } from "../../../providers/chat-state-provider.js";
import { useStreaming } from "../../../providers/streaming-provider.js";
import { AutopilotChatEvent } from "../../../service/index.js";
import { Citation } from "./citation.js";
import { Code } from "./code.js";
import { Li, Ol, Ul } from "./lists.js";
import { citationPlugin, contentPartsToMarkdown } from "./parsers/citation-parser.js";
import { resourceTokenPlugin } from "./parsers/resource-token-parser.js";
import { ResourceChip } from "./resource-chip.js";
import { Cell, HeaderCell, Row, Table, TableHeader } from "./table.js";
import { Blockquote, Break, Del, Emphazised, Hr, Link, Pre, Strong, getTextForVariant } from "./text.js";
const MarkdownContainer = styled('div')(()=>({
        '&, & .katex': {
            color: 'var(--color-foreground)'
        },
        display: 'flex',
        flexDirection: 'column',
        gap: apollo_core.Spacing.SpacingL
    }));
const FAKE_STREAM_CHARS_COUNT = 10;
const FAKE_STREAM_INTERVAL = 50;
const CHUNK_QUEUE_PROCESS_INTERVAL = 50;
const INCOMPLETE_TOKEN_PATTERNS = [
    /\[\[resource-token:(?!.*\]\])/
];
function extractRenderableContent(content) {
    let earliestIndex = -1;
    for (const pattern of INCOMPLETE_TOKEN_PATTERNS){
        const match = content.match(pattern);
        if (match?.index !== void 0) {
            if (-1 === earliestIndex || match.index < earliestIndex) earliestIndex = match.index;
        }
    }
    if (-1 === earliestIndex) return {
        renderable: content,
        buffered: ''
    };
    return {
        renderable: content.slice(0, earliestIndex),
        buffered: content.slice(earliestIndex)
    };
}
function AutopilotChatMarkdownRendererComponent({ message }) {
    const { _ } = useLingui();
    const messageId = react.useRef(message.id);
    const getInitialContent = react.useCallback(()=>{
        if (message.contentParts && message.contentParts.length > 0) return contentPartsToMarkdown(messageId.current, message.contentParts);
        return message.content || '';
    }, [
        message.contentParts,
        message.content
    ]);
    const [content, setContent] = react.useState(message.fakeStream ? '' : getInitialContent());
    const chatService = useChatService();
    const { spacing } = useChatState();
    const { setStreaming } = useStreaming();
    const { isStreaming } = useIsStreamingMessage(message);
    const chunkQueue = react.useRef([]);
    const lastChunkQueueProcessedTime = react.useRef(0);
    const incompleteTokenBuffer = react.useRef('');
    react.useEffect(()=>{
        let unsubscribeStopResponse;
        let fakeStreamInterval;
        if (message.id !== messageId.current || !message.stream) {
            messageId.current = message.id;
            setContent(message.fakeStream ? '' : getInitialContent());
        }
        if (message.fakeStream) {
            unsubscribeStopResponse = chatService.on(AutopilotChatEvent.StopResponse, ()=>{
                clearInterval(fakeStreamInterval);
                setStreaming(false);
                setContent(getInitialContent());
                chunkQueue.current = [];
                incompleteTokenBuffer.current = '';
                lastChunkQueueProcessedTime.current = 0;
            });
            const characters = getInitialContent().split('');
            let charIndex = 0;
            setStreaming(true);
            fakeStreamInterval = setInterval(()=>{
                if (charIndex < characters.length) {
                    const chunkSize = FAKE_STREAM_CHARS_COUNT;
                    const endIndex = Math.min(charIndex + chunkSize, characters.length);
                    const chunk = characters.slice(charIndex, endIndex).join('');
                    setContent((prevContent)=>`${prevContent}${chunk}`);
                    charIndex = endIndex;
                } else {
                    clearInterval(fakeStreamInterval);
                    setStreaming(false);
                }
            }, FAKE_STREAM_INTERVAL);
        }
        return ()=>{
            unsubscribeStopResponse?.();
            if (fakeStreamInterval) clearInterval(fakeStreamInterval);
        };
    }, [
        message,
        chatService,
        setStreaming,
        getInitialContent
    ]);
    const handleSendChunk = react.useCallback((msg)=>{
        if (msg.id !== messageId.current) return;
        chunkQueue.current.push(msg.content);
        if (Date.now() - lastChunkQueueProcessedTime.current > CHUNK_QUEUE_PROCESS_INTERVAL) {
            lastChunkQueueProcessedTime.current = Date.now();
            if (msg.contentParts) {
                const fullContent = contentPartsToMarkdown(messageId.current, msg.contentParts);
                const { renderable } = extractRenderableContent(fullContent);
                setContent(renderable);
                return;
            }
            const accumulated = incompleteTokenBuffer.current + chunkQueue.current.join('');
            const { renderable, buffered } = extractRenderableContent(accumulated);
            incompleteTokenBuffer.current = buffered;
            chunkQueue.current = [];
            if (renderable) setContent((prevContent)=>`${prevContent}${renderable}`);
        } else if (msg.done) {
            lastChunkQueueProcessedTime.current = 0;
            if (msg.contentParts) return void setContent(contentPartsToMarkdown(messageId.current, msg.contentParts));
            const remaining = incompleteTokenBuffer.current + chunkQueue.current.join('');
            incompleteTokenBuffer.current = '';
            chunkQueue.current = [];
            setContent((prevContent)=>`${prevContent}${remaining}`);
        }
    }, []);
    react.useEffect(()=>{
        if (!chatService) return;
        const unsubscribe = chatService.on(AutopilotChatEvent.SendChunk, handleSendChunk);
        return ()=>{
            unsubscribe();
        };
    }, [
        chatService,
        handleSendChunk
    ]);
    const components = react.useMemo(()=>({
            ul: Ul,
            ol: Ol,
            li: Li,
            p: /*#__PURE__*/ react.memo(getTextForVariant(spacing.markdownTokens.p)),
            h1: /*#__PURE__*/ react.memo(getTextForVariant(spacing.markdownTokens.h1, 1)),
            h2: /*#__PURE__*/ react.memo(getTextForVariant(spacing.markdownTokens.h2, 2)),
            h3: /*#__PURE__*/ react.memo(getTextForVariant(spacing.markdownTokens.h3, 3)),
            h4: /*#__PURE__*/ react.memo(getTextForVariant(spacing.markdownTokens.h4, 4)),
            h5: /*#__PURE__*/ react.memo(getTextForVariant(spacing.markdownTokens.h5, 5)),
            h6: /*#__PURE__*/ react.memo(getTextForVariant(spacing.markdownTokens.h6, 6)),
            br: Break,
            table: Table,
            thead: TableHeader,
            tr: Row,
            th: HeaderCell,
            td: Cell,
            img: ({ src })=>src || '',
            code: (props)=>/*#__PURE__*/ jsx(Code, {
                    ...props,
                    isStreaming: isStreaming ?? false
                }),
            blockquote: Blockquote,
            em: Emphazised,
            del: Del,
            strong: Strong,
            hr: Hr,
            pre: Pre,
            a: Link,
            citation: Citation,
            'resource-chip': ResourceChip
        }), [
        spacing,
        isStreaming
    ]);
    return react.useMemo(()=>/*#__PURE__*/ jsx(MarkdownContainer, {
            children: /*#__PURE__*/ jsx(react_markdown, {
                remarkPlugins: [
                    citationPlugin,
                    resourceTokenPlugin,
                    remark_gfm,
                    [
                        remark_math,
                        {
                            singleDollarTextMath: false
                        }
                    ]
                ],
                rehypePlugins: [
                    [
                        rehype_katex,
                        {
                            output: 'mathml',
                            trust: false,
                            strict: true,
                            throwOnError: false
                        }
                    ]
                ],
                remarkRehypeOptions: {
                    footnoteLabel: _({
                        id: 'autopilot-chat.message.footnote-label'
                    })
                },
                components: components,
                children: content
            })
        }), [
        content,
        components,
        _
    ]);
}
const AutopilotChatMarkdownRenderer = /*#__PURE__*/ react.memo(AutopilotChatMarkdownRendererComponent);
export { AutopilotChatMarkdownRenderer };
