import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
import React from 'react';
import Markdown from 'markdown-to-jsx';
import { ToolCallCard } from '../../ToolCallCard';
import { useTheme } from '../../../theme';
import { stringifyPromptContent } from '../../../lib/promptUtils';
const formatFileSize = (size) => {
    if (size <= 0)
        return '0 B';
    const units = ['B', 'KB', 'MB', 'GB', 'TB'];
    const exponent = Math.min(Math.floor(Math.log(size) / Math.log(1024)), units.length - 1);
    const quotient = size / Math.pow(1024, exponent);
    const formatted = quotient >= 10 ? quotient.toFixed(0) : quotient.toFixed(1);
    return `${formatted} ${units[exponent]}`;
};
const DocumentIcon = (props) => (_jsxs("svg", { viewBox: '0 0 24 24', fill: 'none', stroke: 'currentColor', strokeWidth: 1.5, strokeLinecap: 'round', strokeLinejoin: 'round', ...props, children: [_jsx("path", { d: 'M7 3h7l5 5v13a1 1 0 0 1-1 1H7a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z' }), _jsx("path", { d: 'M14 3v5h5' }), _jsx("path", { d: 'M9 13h6' }), _jsx("path", { d: 'M9 17h6' })] }));
const ChevronDownIcon = (props) => (_jsx("svg", { viewBox: '0 0 12 8', fill: 'none', stroke: 'currentColor', strokeWidth: 1.5, strokeLinecap: 'round', strokeLinejoin: 'round', ...props, children: _jsx("path", { d: 'M1 1.5 6 6.5 11 1.5' }) }));
const SlashCommandResolvedPrompt = ({ resolvedPrompt }) => {
    const theme = useTheme();
    const [isOpen, setIsOpen] = React.useState(false);
    const contentId = React.useId();
    if (!resolvedPrompt)
        return null;
    const { description, messages = [] } = resolvedPrompt;
    const trimmedDescription = description?.trim();
    const hasDescription = Boolean(trimmedDescription);
    const hasMessages = messages.length > 0;
    if (!hasDescription && !hasMessages) {
        return null;
    }
    const toggle = React.useCallback(() => {
        setIsOpen((prev) => !prev);
    }, []);
    return (_jsxs(_Fragment, { children: [_jsxs("button", { type: 'button', onClick: toggle, "aria-expanded": isOpen, "aria-controls": contentId, className: theme.message.slashCommandPromptToggle, children: [_jsx("span", { className: [theme.message.slashCommandMeta, 'hover:underline'].filter(Boolean).join(' '), children: isOpen ? 'Hide resolved prompt' : 'Show resolved prompt' }), _jsxs("span", { className: 'flex items-center gap-2', children: [hasMessages ? (_jsxs("span", { className: theme.message.slashCommandMeta, children: [messages.length, " ", messages.length === 1 ? 'message' : 'messages'] })) : null, _jsx(ChevronDownIcon, { className: [theme.message.slashCommandPromptToggleIcon, isOpen ? theme.message.slashCommandPromptToggleIconOpen : ''].filter(Boolean).join(' '), "aria-hidden": 'true' })] })] }), _jsxs("div", { id: contentId, hidden: !isOpen, className: 'space-y-2', children: [hasDescription ? (_jsx("p", { className: theme.message.slashCommandPromptDescription, children: trimmedDescription })) : null, hasMessages ? (_jsx("ol", { className: [theme.message.slashCommandPromptList, 'list-none space-y-1 pl-0'].filter(Boolean).join(' '), children: messages.map((message, index) => {
                            const contentText = stringifyPromptContent(message.content);
                            return (_jsxs("li", { className: theme.message.slashCommandPromptItem, children: [_jsxs("div", { className: theme.message.slashCommandPromptRole, children: [index + 1, ". ", message.role ?? 'message'] }), contentText ? (_jsx("div", { className: theme.message.slashCommandPromptContent, children: contentText })) : null] }, `${message.role ?? 'message'}-${index}`));
                        }) })) : null] })] }));
};
export const MessageList = ({ messages, configError, emptyStateMessage, isShowingStream, streamingContent, streamingToolCalls, reasoningEvents, messageEvents, showToolCalls, expandedToolCalls, onToggleToolCallExpansion, formatStatusLabel, summarizeValue, interruptions, onApproveInterruption, onDenyInterruption }) => {
    const messagesEndRef = React.useRef(null);
    const theme = useTheme();
    const resolveAttachmentPreview = React.useCallback((attachment) => {
        if (attachment.dataUrl) {
            return attachment.dataUrl;
        }
        if (attachment.url) {
            if (attachment.url.startsWith('blob:')) {
                return null;
            }
            return attachment.url;
        }
        if (attachment.sourceUrl) {
            if (attachment.sourceUrl.startsWith('blob:')) {
                return null;
            }
            return attachment.sourceUrl;
        }
        return null;
    }, []);
    const renderSlashCommandSection = React.useCallback((slashCommand) => {
        if (!slashCommand)
            return null;
        const { name, title, serverName, description, args = {}, resolvedPrompt } = slashCommand;
        const argEntries = Object.entries(args)
            .map(([key, value]) => [key, value?.toString() ?? ''])
            .filter(([, value]) => value.trim().length > 0);
        const hasPromptDetails = Boolean(resolvedPrompt?.description?.trim()) || ((resolvedPrompt?.messages?.length ?? 0) > 0);
        return (_jsxs("div", { className: [theme.message.toolActivityContainer, 'space-y-1'].filter(Boolean).join(' '), children: [_jsx("p", { className: theme.message.label, children: "Slash command" }), _jsxs("div", { className: [theme.message.slashCommandCard, 'space-y-1'].filter(Boolean).join(' '), children: [_jsxs("div", { className: theme.message.slashCommandHeader, children: [_jsx("span", { className: theme.message.slashCommandName, children: title ?? `/${name}` }), _jsxs("div", { className: 'flex flex-wrap items-center gap-2', children: [_jsxs("span", { className: theme.message.slashCommandMeta, children: ["/", name] }), serverName ? (_jsx("span", { className: theme.message.slashCommandMeta, children: serverName })) : null] })] }), description ? (_jsx("p", { className: theme.message.slashCommandDescription, children: description })) : null, argEntries.length > 0 ? (_jsx("dl", { className: [theme.message.slashCommandArgList, 'gap-1'].filter(Boolean).join(' '), children: argEntries.map(([key, value]) => (_jsxs("div", { className: theme.message.slashCommandArgItem, children: [_jsx("dt", { className: theme.message.slashCommandArgKey, children: key }), _jsx("dd", { className: theme.message.slashCommandArgValue, children: value })] }, key))) })) : (_jsx("p", { className: theme.message.slashCommandEmpty, children: "No arguments provided." })), hasPromptDetails ? (_jsx(SlashCommandResolvedPrompt, { resolvedPrompt: resolvedPrompt })) : null] })] }));
    }, [
        theme.message.label,
        theme.message.slashCommandArgItem,
        theme.message.slashCommandArgKey,
        theme.message.slashCommandArgList,
        theme.message.slashCommandArgValue,
        theme.message.slashCommandCard,
        theme.message.slashCommandDescription,
        theme.message.slashCommandEmpty,
        theme.message.slashCommandHeader,
        theme.message.slashCommandMeta,
        theme.message.slashCommandName,
        theme.message.toolActivityContainer
    ]);
    const renderAttachmentList = React.useCallback((attachments) => {
        if (attachments.length === 0)
            return null;
        return (_jsx("div", { className: theme.chatInput.attachmentList, children: attachments.map((attachment) => {
                const previewSrc = resolveAttachmentPreview(attachment);
                const isImage = Boolean(previewSrc && attachment.mimeType?.startsWith('image/'));
                return (_jsxs("div", { className: theme.chatInput.attachmentItem, children: [_jsx("div", { className: theme.chatInput.attachmentThumbnail, "aria-hidden": 'true', children: isImage && previewSrc ? (_jsx("img", { src: previewSrc, alt: attachment.name, className: theme.chatInput.attachmentImage })) : (_jsx(DocumentIcon, { className: theme.chatInput.attachmentIcon })) }), _jsxs("div", { className: theme.chatInput.attachmentMeta, children: [_jsx("span", { className: theme.chatInput.attachmentName, title: attachment.name, children: attachment.name }), _jsx("span", { className: theme.chatInput.attachmentSize, children: formatFileSize(attachment.size) })] })] }, attachment.id));
            }) }));
    }, [resolveAttachmentPreview, theme.chatInput.attachmentIcon, theme.chatInput.attachmentImage, theme.chatInput.attachmentItem, theme.chatInput.attachmentList, theme.chatInput.attachmentMeta, theme.chatInput.attachmentName, theme.chatInput.attachmentSize, theme.chatInput.attachmentThumbnail]);
    const renderAttachmentsSection = React.useCallback((attachments) => {
        if (attachments.length === 0)
            return null;
        const attachmentList = renderAttachmentList(attachments);
        if (!attachmentList)
            return null;
        return (_jsxs("div", { className: theme.message.toolActivityContainer, children: [_jsx("p", { className: theme.message.label, children: "Attachments" }), attachmentList] }));
    }, [renderAttachmentList, theme.message.label, theme.message.toolActivityContainer]);
    const isToolCallExpanded = React.useCallback((id) => {
        return expandedToolCalls[id] ?? false;
    }, [expandedToolCalls]);
    const interruptionIndex = React.useMemo(() => {
        const byCallId = new Map();
        const byToolName = new Map();
        interruptions.forEach((interruption) => {
            if (interruption.callId) {
                byCallId.set(interruption.callId, interruption);
            }
            if (interruption.toolName) {
                byToolName.set(interruption.toolName, interruption);
            }
        });
        return { byCallId, byToolName };
    }, [interruptions]);
    const renderToolCallCard = React.useCallback((toolCall, index, context) => {
        const cardId = toolCall.id?.length ? toolCall.id : `${context}-${toolCall.name}-${index}`;
        const expanded = isToolCallExpanded(cardId);
        const interruption = (toolCall.id?.length ? interruptionIndex.byCallId.get(toolCall.id) : undefined)
            ?? interruptionIndex.byToolName.get(toolCall.name);
        return (_jsx(ToolCallCard, { toolCall: toolCall, index: index, context: context, expanded: expanded, onToggleExpansion: onToggleToolCallExpansion, formatStatusLabel: formatStatusLabel, summarizeValue: summarizeValue, pendingInterruption: interruption, onApproveInterruption: onApproveInterruption, onDenyInterruption: onDenyInterruption }, cardId));
    }, [formatStatusLabel, interruptionIndex, isToolCallExpanded, onApproveInterruption, onDenyInterruption, onToggleToolCallExpansion, summarizeValue]);
    const renderMessageCard = React.useCallback((sections) => {
        if (sections.length === 0)
            return null;
        return (_jsx("div", { className: theme.message.cardContainer, children: _jsx("div", { className: theme.message.cardSections, children: sections.map((section, index) => (_jsx(React.Fragment, { children: section }, index))) }) }));
    }, [theme.message.cardContainer, theme.message.cardSections]);
    const renderToolActivitySection = React.useCallback((toolCalls, context) => {
        if (toolCalls.length === 0)
            return null;
        return (_jsxs("div", { className: theme.message.toolActivityContainer, children: [_jsx("p", { className: theme.message.toolActivityLabel, children: "Tool activity" }), _jsx("div", { className: theme.message.toolActivityBody, children: toolCalls.map((toolCall, index) => renderToolCallCard(toolCall, index, context)) })] }));
    }, [renderToolCallCard, theme.message.toolActivityBody, theme.message.toolActivityContainer, theme.message.toolActivityLabel]);
    const renderUserMessageSection = React.useCallback((content) => {
        if (!content?.trim())
            return null;
        return (_jsxs("div", { className: theme.message.toolActivityContainer, children: [_jsx("p", { className: theme.message.label, children: "Your message" }), _jsx("div", { className: theme.message.userText, children: content })] }));
    }, [theme.message.label, theme.message.toolActivityContainer, theme.message.userText]);
    const renderModelResponseSection = React.useCallback((content, context) => {
        if (!content?.trim())
            return null;
        const label = context === 'stream' ? 'Model response (draft)' : 'Model response';
        return (_jsxs("div", { className: theme.message.toolActivityContainer, children: [_jsx("p", { className: theme.message.label, children: label }), _jsx("div", { className: theme.message.modelContent, children: _jsx(Markdown, { children: content }) })] }));
    }, [theme.message.label, theme.message.modelContent, theme.message.toolActivityContainer]);
    const messageStatusNode = React.useMemo(() => {
        if (messageEvents.length === 0)
            return null;
        const label = messageEvents.length === 1
            ? 'Assistant is composing a response…'
            : `Assistant is composing ${messageEvents.length} responses…`;
        return (_jsxs("div", { className: theme.message.messageStatus, "aria-live": 'polite', children: [_jsx("span", { className: 'inline-flex h-3 w-3 items-center justify-center', children: _jsx("span", { className: theme.message.messageStatusSpinner, "aria-hidden": 'true' }) }), _jsx("span", { children: label })] }));
    }, [messageEvents, theme.message.messageStatus, theme.message.messageStatusSpinner]);
    const reasoningStatusNode = React.useMemo(() => {
        if (reasoningEvents.length === 0)
            return null;
        const label = reasoningEvents.length === 1
            ? 'Model is reasoning…'
            : `Model is reasoning (${reasoningEvents.length} steps)…`;
        return (_jsxs("div", { className: theme.message.reasoningStatus, "aria-live": 'polite', children: [_jsx("span", { className: 'inline-flex h-3 w-3 items-center justify-center', children: _jsx("span", { className: theme.message.reasoningStatusSpinner, "aria-hidden": 'true' }) }), _jsx("span", { children: label })] }));
    }, [reasoningEvents, theme.message.reasoningStatus, theme.message.reasoningStatusSpinner]);
    React.useEffect(() => {
        messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });
    }, [messages, streamingContent, streamingToolCalls.length, reasoningEvents.length]);
    if (configError) {
        return (_jsx("div", { className: 'flex h-full items-center justify-center', children: _jsxs("div", { className: theme.message.configErrorContainer, children: [_jsx("p", { className: theme.message.configErrorTitle, children: "Configuration Required" }), _jsx("p", { className: theme.message.configErrorBody, children: configError }), _jsx("p", { className: theme.message.configErrorHelper, children: "Please configure a model in the settings panel to start chatting." })] }) }));
    }
    if (messages.length === 0) {
        return (_jsx("div", { className: theme.message.emptyState, children: emptyStateMessage }));
    }
    return (_jsxs("div", { className: theme.message.listContainer, children: [messages.flatMap((message, index) => {
                const key = `${message.role}-${message.timestamp ?? index}`;
                const isUser = message.role === 'user';
                const nextMessage = messages[index + 1];
                const isFollowedByUser = !isUser && nextMessage?.role === 'user';
                const toolCalls = !isUser && message.toolCalls ? message.toolCalls : [];
                const attachments = message.attachments ?? [];
                const messageSections = [];
                const slashCommandSection = renderSlashCommandSection(message.slashCommand);
                if (slashCommandSection)
                    messageSections.push(slashCommandSection);
                if (attachments.length > 0) {
                    const attachmentSection = renderAttachmentsSection(attachments);
                    if (attachmentSection)
                        messageSections.push(attachmentSection);
                }
                if (isUser) {
                    const userSection = renderUserMessageSection(message.content);
                    if (userSection)
                        messageSections.push(userSection);
                }
                else {
                    if (showToolCalls && toolCalls.length > 0) {
                        const toolActivity = renderToolActivitySection(toolCalls, 'history');
                        if (toolActivity)
                            messageSections.push(toolActivity);
                    }
                    const modelSection = renderModelResponseSection(message.content, 'history');
                    if (modelSection)
                        messageSections.push(modelSection);
                }
                const messageCard = renderMessageCard(messageSections);
                if (!messageCard) {
                    return [];
                }
                return (_jsx("div", { className: isUser ? theme.message.userRow : theme.message.assistantRow, children: _jsxs("div", { className: 'relative max-w-xl flex-1', children: [messageCard, isFollowedByUser && (_jsx("div", { className: theme.message.dividerWrapper, children: _jsx("span", { className: theme.message.dividerLine, "aria-hidden": 'true' }) }))] }) }, key));
            }), isShowingStream && (_jsx("div", { className: 'flex justify-start', "aria-live": 'polite', children: _jsx("div", { className: 'max-w-xl flex-1', children: renderMessageCard([
                        showToolCalls && streamingToolCalls.length > 0
                            ? renderToolActivitySection(streamingToolCalls, 'stream')
                            : null,
                        renderModelResponseSection(streamingContent, 'stream'),
                        (messageStatusNode || reasoningStatusNode) && (_jsxs("div", { className: theme.message.streamingContainer, children: [_jsx("p", { className: theme.message.streamingLabel, children: "In progress" }), _jsxs("div", { className: theme.message.streamingStatusBlock, children: [messageStatusNode, reasoningStatusNode] }), _jsx("p", { className: theme.message.streamingStatusText, children: "Streaming\u2026" })] }))
                    ].filter(Boolean)) }) })), _jsx("div", { ref: messagesEndRef })] }));
};
