'use client';
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
import { createPortal } from 'react-dom';
import { ActionBarPrimitive, ComposerPrimitive, MessagePrimitive, ThreadPrimitive, useMessage, } from '@assistant-ui/react';
import Markdown from 'react-markdown';
import remarkGfm from 'remark-gfm';
import { useTranslation } from 'react-i18next';
import { cn } from '../../lib/utils.js';
import { ToolBubble, parseToolEvent } from '../features/chat/tool-bubble/index.js';
import { SendHorizontal, CircleStop, Copy, Paperclip, Bot, User, Maximize2, X, ChevronDown, ChevronUp, Loader2, Check, } from 'lucide-react';
// ── Markdown components for assistant messages ──────────────────────────────
const markdownComponents = {
    p: ({ children }) => _jsx("p", { className: "mb-2 leading-relaxed last:mb-0", children: children }),
    strong: ({ children }) => _jsx("strong", { className: "font-semibold", children: children }),
    em: ({ children }) => _jsx("em", { className: "italic", children: children }),
    code: ({ children, className }) => className ? (_jsx("code", { className: `${className} text-[11px]`, children: children })) : (_jsx("code", { className: "bg-background/50 rounded-md px-1.5 py-0.5 font-mono text-xs", children: children })),
    pre: ({ children }) => {
        // Extract language and raw text from the nested <code> element
        const codeEl = children;
        const lang = codeEl?.props?.className?.replace('language-', '') ?? '';
        const rawText = typeof codeEl?.props?.children === 'string' ? codeEl.props.children : '';
        const isPreviewable = ['html', 'svg'].includes(lang) && rawText.length > 0;
        if (isPreviewable) {
            return _jsx(HtmlPreviewBlock, { code: rawText, language: lang });
        }
        return _jsx(CollapsibleCode, { language: lang, children: children });
    },
    ul: ({ children }) => _jsx("ul", { className: "mb-2 list-disc ps-4 last:mb-0", children: children }),
    ol: ({ children }) => _jsx("ol", { className: "mb-2 list-decimal ps-4 last:mb-0", children: children }),
    li: ({ children }) => _jsx("li", { className: "mb-0.5", children: children }),
    h1: ({ children }) => _jsx("h1", { className: "mb-1 text-base font-bold", children: children }),
    h2: ({ children }) => _jsx("h2", { className: "mb-1 text-sm font-bold", children: children }),
    h3: ({ children }) => _jsx("h3", { className: "mb-1 text-sm font-semibold", children: children }),
    a: ({ children, href }) => (_jsx("a", { href: href, className: "text-blue-500 underline", target: "_blank", rel: "noopener noreferrer", children: children })),
    blockquote: ({ children }) => (_jsx("blockquote", { className: "border-muted-foreground/30 my-1 border-s-2 ps-3 italic opacity-80", children: children })),
    table: ({ children }) => (_jsx("div", { className: "my-2 overflow-x-auto", children: _jsx("table", { className: "min-w-full border-collapse text-xs", children: children }) })),
    thead: ({ children }) => _jsx("thead", { className: "bg-muted/50 border-b", children: children }),
    th: ({ children }) => _jsx("th", { className: "px-2 py-1 text-start font-semibold", children: children }),
    td: ({ children }) => _jsx("td", { className: "border-muted border-t px-2 py-1", children: children }),
    tr: ({ children }) => _jsx("tr", { children: children }),
    hr: () => _jsx("hr", { className: "border-border/40 my-3 border-t" }),
};
// ── Thread ──────────────────────────────────────────────────────────────────
export function Thread({ className, beforeMessages, afterMessages, composer, hideEmpty, hideMessages, }) {
    return (_jsxs(ThreadPrimitive.Root, { className: cn('flex h-full flex-col', className), children: [_jsxs(ThreadPrimitive.Viewport, { className: "flex flex-1 flex-col overflow-y-auto pt-4", children: [hideEmpty ? null : (_jsx(ThreadPrimitive.Empty, { children: _jsx(ThreadEmpty, {}) })), beforeMessages, hideMessages ? null : (_jsx(ThreadPrimitive.Messages, { components: {
                            UserMessage,
                            AssistantMessage,
                        } })), afterMessages] }), composer ?? _jsx(Composer, {})] }));
}
// ── Empty state ─────────────────────────────────────────────────────────────
function ThreadEmpty() {
    return (_jsxs("div", { className: "flex flex-1 flex-col items-center justify-center gap-2 p-8 text-center", children: [_jsx(Bot, { className: "text-muted-foreground/40 h-10 w-10" }), _jsx("p", { className: "text-muted-foreground text-sm", children: "Send a message to start chatting with the agent." })] }));
}
// ── User message ────────────────────────────────────────────────────────────
const INTERACTION_PREFIX = '{{interaction}}';
const UserMessage = () => {
    const message = useMessage();
    // Check if this is an interaction response message
    const firstPart = message?.content?.[0];
    const text = firstPart && 'text' in firstPart ? firstPart.text : '';
    if (text.startsWith(INTERACTION_PREFIX)) {
        return _jsx(InteractionResponseMessage, { text: text });
    }
    return (_jsxs(MessagePrimitive.Root, { className: "group animate-in fade-in-0 slide-in-from-bottom-1 flex w-full items-start gap-2.5 px-4 py-0.5 duration-300 ease-out", children: [_jsx("div", { className: "mt-0.5 flex h-6 w-6 shrink-0 items-center justify-center rounded-full bg-violet-500/15", children: _jsx(User, { className: "h-3.5 w-3.5 text-violet-500" }) }), _jsxs("div", { className: "flex max-w-[85%] min-w-0 flex-col gap-0.5", children: [_jsx("div", { className: "text-foreground mt-px overflow-hidden rounded-2xl rounded-tl-sm border border-violet-500/15 bg-violet-500/8 px-4 py-2 text-sm leading-relaxed break-words shadow-sm backdrop-blur-md dark:bg-violet-500/15", children: _jsx(MessagePrimitive.Content, { components: { Text: UserMessageText } }) }), _jsxs("div", { className: "flex items-center gap-1.5 opacity-0 transition-opacity group-hover:opacity-100", children: [_jsx(MessageMeta, {}), _jsx(ActionBarPrimitive.Root, { className: "flex items-center gap-1", children: _jsx(ActionBarPrimitive.Copy, { asChild: true, children: _jsx(IconButton, { tooltip: "Copy", children: _jsx(Copy, {}) }) }) })] })] })] }));
};
/** Compact green bubble showing the user's selections from an AskUserQuestion interaction. */
function InteractionResponseMessage({ text }) {
    const parsed = useMemo(() => {
        try {
            const json = text.slice(INTERACTION_PREFIX.length);
            return JSON.parse(json);
        }
        catch {
            return null;
        }
    }, [text]);
    if (!parsed)
        return null;
    return (_jsxs(MessagePrimitive.Root, { className: "group animate-in fade-in-0 slide-in-from-bottom-1 flex w-full items-start gap-2.5 px-4 py-0.5 duration-300 ease-out", children: [_jsx("div", { className: "bg-muted flex h-6 w-6 shrink-0 items-center justify-center rounded-full", children: _jsx(Check, { className: "h-3.5 w-3.5 text-emerald-600 dark:text-emerald-400" }) }), _jsxs("div", { className: "flex min-w-0 flex-1 flex-col gap-0.5", children: [_jsx("div", { className: "text-foreground mt-px flex flex-wrap items-center gap-x-4 gap-y-1 rounded-2xl rounded-tl-sm border border-emerald-600/20 bg-emerald-50/50 px-4 py-2 text-sm shadow-sm dark:border-emerald-500/20 dark:bg-emerald-950/20", children: parsed.questions.map((q) => (_jsxs("span", { className: "flex items-center gap-2", children: [_jsx("span", { className: "inline-flex shrink-0 items-center rounded-full bg-emerald-100 px-2 py-0.5 text-[10px] font-semibold tracking-wider text-emerald-700 uppercase dark:bg-emerald-900/50 dark:text-emerald-400", children: q.header }), _jsx("span", { className: "text-muted-foreground text-xs", children: parsed.answers[q.question] || 'No answer' })] }, q.question))) }), _jsxs("div", { className: "flex items-center gap-1.5 opacity-0 transition-opacity group-hover:opacity-100", children: [_jsx(MessageMeta, {}), _jsx(ActionBarPrimitive.Root, { className: "flex items-center gap-1", children: _jsx(ActionBarPrimitive.Copy, { asChild: true, children: _jsx(IconButton, { tooltip: "Copy", children: _jsx(Copy, {}) }) }) })] })] })] }));
}
function UserMessageText({ text }) {
    return _jsx("span", { className: "whitespace-pre-wrap", children: text });
}
// ── Assistant message ───────────────────────────────────────────────────────
const AssistantMessage = () => {
    // Peek at the raw message content to decide whether this is a
    // tool-event message (Bash / Read / Write / Edit / …). Tool events
    // render as a compact chip + expanded preview — they should NOT be
    // wrapped in the normal assistant bubble shell (that adds bulky
    // padding, avatar, background, and copy button). Everything else
    // falls through to the regular bubble.
    const message = useMessage();
    const firstPart = message?.content?.[0];
    const rawText = firstPart && 'text' in firstPart ? firstPart.text : '';
    const toolEvent = rawText ? parseToolEvent(rawText) : null;
    if (toolEvent) {
        return (_jsxs(MessagePrimitive.Root, { className: "group animate-in fade-in-0 slide-in-from-bottom-1 flex w-full items-start gap-2.5 px-4 py-0.5 duration-300 ease-out", children: [_jsx("div", { className: "text-muted-foreground/40 mt-1 flex h-6 w-6 shrink-0 items-center justify-center", children: _jsx(Bot, { className: "h-3 w-3" }) }), _jsx("div", { className: "flex min-w-0 flex-1 items-center py-0.5", children: _jsx(ToolBubble, { text: rawText }) })] }));
    }
    return (_jsxs(MessagePrimitive.Root, { className: "group animate-in fade-in-0 slide-in-from-bottom-1 flex w-full items-start gap-2.5 px-4 py-0.5 duration-300 ease-out", children: [_jsx("div", { className: "bg-muted flex h-6 w-6 shrink-0 items-center justify-center rounded-full", children: _jsx(Bot, { className: "text-muted-foreground h-3.5 w-3.5" }) }), _jsxs("div", { className: "flex min-w-0 flex-1 flex-col gap-0.5", children: [_jsx("div", { className: "bg-muted/50 text-foreground mt-px overflow-hidden rounded-2xl rounded-tl-sm border border-white/5 px-4 py-2 text-sm leading-relaxed break-words shadow-sm backdrop-blur-md dark:bg-neutral-800/60", children: _jsx(MessagePrimitive.Content, { components: { Text: AssistantMessageText } }) }), _jsxs("div", { className: "flex items-center gap-1.5 opacity-0 transition-opacity group-hover:opacity-100", children: [_jsx(MessageMeta, {}), _jsx(ActionBarPrimitive.Root, { className: "flex items-center gap-1", children: _jsx(ActionBarPrimitive.Copy, { asChild: true, children: _jsx(IconButton, { tooltip: "Copy", children: _jsx(Copy, {}) }) }) })] })] })] }));
};
// ── Collapsible code block ───────────────────────────────────────────────
const CODE_COLLAPSED_HEIGHT = 200; // px
function CollapsibleCode({ children, language }) {
    const { t } = useTranslation('web');
    const [expanded, setExpanded] = useState(false);
    const [needsCollapse, setNeedsCollapse] = useState(false);
    const ref = useRef(null);
    useEffect(() => {
        if (ref.current && ref.current.scrollHeight > CODE_COLLAPSED_HEIGHT + 40) {
            setNeedsCollapse(true);
        }
    }, [children]);
    return (_jsxs("div", { className: "bg-background/50 relative my-2 overflow-hidden rounded-md", children: [language ? (_jsx("div", { className: "text-muted-foreground/50 border-b border-white/5 px-3 py-1 font-mono text-[10px] uppercase", children: language })) : null, _jsx("pre", { ref: ref, className: "overflow-x-auto p-3 font-mono text-xs leading-relaxed transition-[max-height] duration-300 ease-in-out", style: {
                    maxHeight: expanded
                        ? 'min(60vh, 500px)'
                        : !needsCollapse
                            ? 'min(60vh, 500px)'
                            : `${CODE_COLLAPSED_HEIGHT}px`,
                    overflow: expanded ? 'auto' : undefined,
                }, children: children }), needsCollapse && !expanded ? (_jsx("div", { className: "absolute inset-x-0 bottom-0 flex items-end justify-center bg-gradient-to-t from-black/60 via-black/30 to-transparent pt-12 pb-3", children: _jsxs("button", { type: "button", onClick: () => setExpanded(true), className: "inline-flex items-center gap-1 rounded-full border border-white/10 bg-white/10 px-3 py-1 text-[11px] font-medium text-white/80 shadow-lg backdrop-blur-md transition-all hover:bg-white/20 hover:text-white", children: [_jsx(ChevronDown, { className: "h-3 w-3" }), t('chat.showMore')] }) })) : null, needsCollapse && expanded ? (_jsx("div", { className: "flex justify-center border-t border-white/5 py-1.5", children: _jsxs("button", { type: "button", onClick: () => setExpanded(false), className: "inline-flex items-center gap-1 rounded-full px-3 py-0.5 text-[11px] text-white/50 transition-colors hover:text-white/80", children: [_jsx(ChevronUp, { className: "h-3 w-3" }), t('chat.showLess')] }) })) : null] }));
}
// ── HTML preview block with code/preview toggle ─────────────────────────
function HtmlPreviewBlock({ code, language }) {
    const { t } = useTranslation('web');
    const [showPreview, setShowPreview] = useState(false);
    const [maximized, setMaximized] = useState(false);
    const [fullscreenCode, setFullscreenCode] = useState(false);
    const lines = code.split('\n').length;
    const chars = code.length;
    return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "bg-background/50 my-2 overflow-hidden rounded-md border", children: [_jsxs("div", { className: "flex items-center justify-between border-b px-3 py-1", children: [_jsx("span", { className: "text-muted-foreground font-mono text-xs uppercase", children: language }), _jsxs("div", { className: "flex items-center gap-1", children: [_jsx("button", { type: "button", onClick: () => setShowPreview(false), className: cn('rounded px-2.5 py-0.5 text-xs font-medium transition-colors', !showPreview
                                            ? 'bg-muted text-foreground'
                                            : 'text-muted-foreground hover:text-foreground'), children: t('chat.code') }), _jsx("button", { type: "button", onClick: () => setShowPreview(true), className: cn('rounded px-2.5 py-0.5 text-xs font-medium transition-colors', showPreview
                                            ? 'bg-muted text-foreground'
                                            : 'text-muted-foreground hover:text-foreground'), children: t('chat.preview') }), _jsx("button", { type: "button", onClick: () => {
                                            setFullscreenCode(!showPreview);
                                            setMaximized(true);
                                        }, className: "text-muted-foreground hover:text-foreground ms-1 rounded p-0.5 transition-colors", title: t('chat.openFullscreen'), children: _jsx(Maximize2, { className: "h-3 w-3" }) })] })] }), _jsx("div", { style: { height: 'min(55vh, 450px)' }, children: showPreview ? (_jsx("iframe", { srcDoc: code, sandbox: "allow-scripts", className: "h-full w-full border-0 bg-white", title: t('chat.htmlPreview') })) : (_jsx("pre", { className: "h-full overflow-auto p-3 font-mono text-xs leading-relaxed", children: _jsx("code", { children: code }) })) })] }), maximized && typeof document !== 'undefined'
                ? createPortal(_jsx("div", { className: "fixed inset-0 z-[9999] flex items-center justify-center bg-black/70 backdrop-blur-sm", onClick: () => setMaximized(false), children: _jsxs("div", { className: "bg-background relative flex h-[95vh] w-[95vw] flex-col overflow-hidden rounded-xl border shadow-2xl", onClick: (e) => e.stopPropagation(), children: [_jsxs("div", { className: "bg-muted/80 flex h-12 shrink-0 items-center justify-between border-b px-5", children: [_jsxs("div", { className: "bg-muted flex items-center gap-0.5 rounded-lg p-1", children: [_jsx("button", { type: "button", onClick: () => setFullscreenCode(false), className: cn('rounded-md px-4 py-1.5 text-sm font-medium transition-all', !fullscreenCode
                                                    ? 'bg-background text-foreground shadow-sm'
                                                    : 'text-muted-foreground hover:text-foreground'), children: t('chat.preview') }), _jsx("button", { type: "button", onClick: () => setFullscreenCode(true), className: cn('rounded-md px-4 py-1.5 text-sm font-medium transition-all', fullscreenCode
                                                    ? 'bg-background text-foreground shadow-sm'
                                                    : 'text-muted-foreground hover:text-foreground'), children: t('chat.code') })] }), _jsxs("div", { className: "text-muted-foreground/60 flex items-center gap-4 text-xs", children: [_jsxs("span", { children: [lines, " lines"] }), _jsxs("span", { children: [chars.toLocaleString(), " chars"] }), _jsx("span", { className: "font-mono uppercase", children: language })] }), _jsx("button", { type: "button", onClick: () => setMaximized(false), className: "text-muted-foreground hover:bg-muted hover:text-foreground rounded-lg p-2 transition-colors", children: _jsx(X, { className: "h-5 w-5" }) })] }), fullscreenCode ? (_jsx("pre", { className: "flex-1 overflow-auto p-4 font-mono text-xs leading-relaxed", children: _jsx("code", { children: code }) })) : (_jsx("iframe", { srcDoc: code, sandbox: "allow-scripts", className: "flex-1 border-0 bg-white dark:bg-neutral-900", title: t('chat.htmlPreviewFullscreen') }))] }) }), document.body)
                : null] }));
}
const ACTIVITY_MARKER_RE = /^\*⏳ (.+)\*$/;
function AssistantMessageText({ text }) {
    if (text === '*Thinking...*' || text === '*Agent is waking up...*') {
        return _jsx(ThinkingIndicator, { booting: text.includes('waking') });
    }
    // Live activity indicator (e.g. "Using tool: Bash", "Running: Read")
    const activityMatch = ACTIVITY_MARKER_RE.exec(text);
    if (activityMatch) {
        return _jsx(ActivityIndicator, { label: activityMatch[1] });
    }
    return (_jsx(Markdown, { remarkPlugins: [remarkGfm], components: markdownComponents, children: text }));
}
function ActivityIndicator({ label }) {
    return (_jsxs("span", { className: "text-muted-foreground inline-flex items-center gap-2 text-sm italic", children: [_jsx(Loader2, { className: "h-3.5 w-3.5 animate-spin" }), _jsx("span", { children: label })] }));
}
// ── Thinking indicator with cycling words ────────────────────────────────
const THINKING_WORDS = [
    'Thinking',
    'Reasoning',
    'Analyzing',
    'Processing',
    'Evaluating',
    'Considering',
    'Reflecting',
    'Pondering',
];
const BOOTING_WORDS = ['Waking up', 'Initializing', 'Loading tools', 'Preparing', 'Connecting'];
import { useEffect, useRef, useState } from 'react';
function ThinkingIndicator({ booting }) {
    const words = booting ? BOOTING_WORDS : THINKING_WORDS;
    const [index, setIndex] = useState(0);
    const [fade, setFade] = useState(true);
    useEffect(() => {
        const interval = setInterval(() => {
            setFade(false);
            setTimeout(() => {
                setIndex((i) => (i + 1) % words.length);
                setFade(true);
            }, 200);
        }, 2000);
        return () => clearInterval(interval);
    }, [words]);
    return (_jsxs("span", { className: "text-muted-foreground inline-flex w-32 items-center gap-1.5 text-sm italic", children: [_jsx("span", { className: "inline-block transition-all duration-300 ease-in-out", style: { opacity: fade ? 1 : 0, transform: fade ? 'translateY(0)' : 'translateY(-4px)' }, children: words[index] }), _jsxs("span", { className: "inline-flex gap-0.5", children: [_jsx("span", { className: "bg-muted-foreground/60 h-1 w-1 animate-bounce rounded-full", style: { animationDelay: '0ms' } }), _jsx("span", { className: "bg-muted-foreground/60 h-1 w-1 animate-bounce rounded-full", style: { animationDelay: '150ms' } }), _jsx("span", { className: "bg-muted-foreground/60 h-1 w-1 animate-bounce rounded-full", style: { animationDelay: '300ms' } })] })] }));
}
// ── Message metadata (timestamp + relative time) ────────────────────────────
function MessageMeta() {
    const message = useMessage();
    // Tick every 30s so relative timestamps stay fresh
    const [tick, setTick] = useState(0);
    useEffect(() => {
        const id = setInterval(() => setTick((t) => t + 1), 30_000);
        return () => clearInterval(id);
    }, []);
    const meta = useMemo(() => {
        if (!message?.createdAt)
            return null;
        const date = new Date(message.createdAt);
        if (isNaN(date.getTime()))
            return null;
        return {
            time: date.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }),
            relative: formatRelativeTime(date),
        };
        // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [message?.createdAt, tick]);
    if (!meta)
        return null;
    return (_jsx("span", { className: "text-muted-foreground/60 text-[10px]", title: meta.time, children: meta.relative }));
}
function formatRelativeTime(date) {
    const diff = Date.now() - date.getTime();
    if (diff < 0 || diff < 5000)
        return 'just now';
    const seconds = Math.floor(diff / 1000);
    if (seconds < 60)
        return `${seconds}s ago`;
    const minutes = Math.floor(seconds / 60);
    if (minutes < 60)
        return `${minutes}m ago`;
    const hours = Math.floor(minutes / 60);
    if (hours < 24)
        return `${hours}h ago`;
    return date.toLocaleDateString();
}
// ── Icon button helper ──────────────────────────────────────────────────────
import { forwardRef, useMemo } from 'react';
const IconButton = forwardRef(({ tooltip, children, className, ...props }, ref) => (_jsx("button", { ref: ref, type: "button", title: tooltip, className: cn('text-muted-foreground hover:text-foreground hover:bg-muted inline-flex h-7 w-7 items-center justify-center rounded-md transition-colors', '[&>svg]:h-3.5 [&>svg]:w-3.5', className), ...props, children: children })));
IconButton.displayName = 'IconButton';
// ── Composer ────────────────────────────────────────────────────────────────
function Composer() {
    return (_jsxs(ComposerPrimitive.Root, { className: "flex items-end gap-2 border-t p-3", children: [_jsx(ComposerPrimitive.AddAttachment, { asChild: true, children: _jsx(IconButton, { tooltip: "Attach file", className: "mb-0.5", children: _jsx(Paperclip, {}) }) }), _jsx(ComposerPrimitive.Input, { rows: 1, autoFocus: true, placeholder: "Write a message...", className: cn('bg-muted min-h-[40px] flex-1 resize-none rounded-xl border-0 px-4 py-2.5 text-sm', 'focus:ring-ring/30 focus:ring-2 focus:outline-none', 'placeholder:text-muted-foreground/60', 'max-h-40 overflow-y-auto') }), _jsx(ComposerAction, {})] }));
}
function ComposerAction() {
    return (_jsxs(_Fragment, { children: [_jsx(ThreadPrimitive.If, { running: false, children: _jsx(ComposerPrimitive.Send, { className: cn('bg-primary text-primary-foreground inline-flex h-[40px] w-[40px] shrink-0 items-center justify-center rounded-xl', 'hover:bg-primary/90 disabled:pointer-events-none disabled:opacity-30', 'transition-colors'), children: _jsx(SendHorizontal, { className: "size-4" }) }) }), _jsx(ThreadPrimitive.If, { running: true, children: _jsx(ComposerPrimitive.Cancel, { className: cn('bg-destructive/10 text-destructive inline-flex h-[40px] w-[40px] shrink-0 items-center justify-center rounded-xl', 'hover:bg-destructive/20', 'transition-colors'), children: _jsx(CircleStop, { className: "size-4" }) }) })] }));
}
