/**
 * Renders an assistant (LLM) response — text, thinking blocks, and error/abort states.
 *
 * Thinking content can be collapsed to a single "Thinking..." label or expanded
 * as italic markdown. Abort/error messages are shown only when there are no tool
 * calls (tool components handle their own errors).
 */
import { Container, Markdown, Spacer, Text } from '../../../tui/index.js';
import { ERROR_MAX_CHARS_UI } from '../../../utils/truncate.js';
import { ABORT_UI_LABEL } from '../../abort-labels.js';
import { PREFIX_WIDTH, assistantPrefix, prefixLines } from '../../layout.js';
import { theme } from '../../theme/runtime.js';
import { getMarkdownTheme } from '../../theme/theme.js';
/**
 * Component that renders a complete assistant message
 */
export class AssistantMessageComponent extends Container {
    contentContainer;
    hideThinkingBlock;
    markdownTheme;
    lastMessage;
    constructor(message, hideThinkingBlock = false, markdownTheme = getMarkdownTheme()) {
        super();
        this.hideThinkingBlock = hideThinkingBlock;
        this.markdownTheme = markdownTheme;
        // Container for text/thinking content
        this.contentContainer = new Container();
        this.addChild(this.contentContainer);
        if (message) {
            this.updateContent(message);
        }
    }
    invalidate() {
        super.invalidate();
        if (this.lastMessage) {
            this.updateContent(this.lastMessage);
        }
    }
    render(width) {
        return prefixLines(super.render(width - PREFIX_WIDTH), assistantPrefix());
    }
    setHideThinkingBlock(hide) {
        this.hideThinkingBlock = hide;
    }
    updateContent(message) {
        this.lastMessage = message;
        // Clear content container
        this.contentContainer.clear();
        const hasVisibleContent = message.content.some((c) => (c.type === 'text' && c.text.trim()) || (c.type === 'thinking' && c.thinking.trim()));
        if (hasVisibleContent) {
            this.contentContainer.addChild(new Spacer(1));
        }
        // Render content in order
        for (let i = 0; i < message.content.length; i++) {
            const content = message.content[i];
            if (content.type === 'text' && content.text.trim()) {
                this.contentContainer.addChild(new Markdown(content.text.trim(), 0, 0, this.markdownTheme));
            }
            else if (content.type === 'thinking' && content.thinking.trim()) {
                // Add spacing only when another visible assistant content block follows.
                // This avoids a superfluous blank line before separately-rendered tool execution blocks.
                const hasVisibleContentAfter = message.content
                    .slice(i + 1)
                    .some((c) => (c.type === 'text' && c.text.trim()) || (c.type === 'thinking' && c.thinking.trim()));
                if (this.hideThinkingBlock) {
                    this.contentContainer.addChild(new Text(theme.italic(theme.fg('thinkingText', 'Thinking...')), 0, 0));
                    if (hasVisibleContentAfter) {
                        this.contentContainer.addChild(new Spacer(1));
                    }
                }
                else {
                    this.contentContainer.addChild(new Markdown(content.thinking.trim(), 0, 0, this.markdownTheme, {
                        color: (text) => theme.fg('thinkingText', text),
                        italic: true
                    }));
                    if (hasVisibleContentAfter) {
                        this.contentContainer.addChild(new Spacer(1));
                    }
                }
            }
        }
        // Check if aborted - show after partial content
        // But only if there are no tool calls (tool execution components will show the error)
        const hasToolCalls = message.content.some((c) => c.type === 'toolCall');
        if (!hasToolCalls) {
            if (message.stopReason === 'aborted') {
                const abortMessage = message.errorMessage && message.errorMessage !== 'Request was aborted'
                    ? message.errorMessage
                    : ABORT_UI_LABEL;
                this.contentContainer.addChild(new Text(`${theme.fg('muted', '⎿')}  ${theme.fg('success', abortMessage)}`, 0, 0));
            }
            else if (message.stopReason === 'error') {
                const raw = message.errorMessage || 'Unknown error';
                const errorMsg = raw.length > ERROR_MAX_CHARS_UI ? `${raw.slice(0, ERROR_MAX_CHARS_UI)}...` : raw;
                this.contentContainer.addChild(new Spacer(1));
                this.contentContainer.addChild(new Text(theme.fg('error', `Error: ${errorMsg}`), 0, 0));
            }
        }
    }
}
//# sourceMappingURL=assistant-message.js.map