import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
/**
 * @license
 * Copyright 2025 Vybestack LLC
 * SPDX-License-Identifier: Apache-2.0
 */
import { useCallback, useState } from 'react';
import { Box, Text } from 'ink';
import { DiffRenderer } from './DiffRenderer.js';
import { Colors, SemanticColors } from '../../colors.js';
import { RenderInline } from '../../utils/InlineMarkdownRenderer.js';
import { ToolConfirmationOutcome, MessageBusType, DebugLogger, } from '@vybestack/llxprt-code-core';
import { RadioButtonSelect, } from '../shared/RadioButtonSelect.js';
import { MaxSizedBox } from '../shared/MaxSizedBox.js';
import { useResponsive } from '../../hooks/useResponsive.js';
import { truncateEnd } from '../../utils/responsive.js';
import { useKeypress } from '../../hooks/useKeypress.js';
const confirmationLogger = new DebugLogger('llxprt:ui:selection');
export const ToolConfirmationMessage = ({ confirmationDetails, config, isFocused = true, availableTerminalHeight, terminalWidth, }) => {
    const childWidth = terminalWidth - 2; // 2 for padding
    const { breakpoint } = useResponsive();
    // State to track whether details are shown
    const [showDetails, setShowDetails] = useState(false);
    const handleConfirm = useCallback((outcome) => {
        if (confirmationLogger.enabled) {
            confirmationLogger.debug(() => `ToolConfirmationMessage handleConfirm outcome=${outcome} correlationId=${confirmationDetails.correlationId}`);
        }
        const correlationId = confirmationDetails.correlationId;
        if (!correlationId) {
            console.error('Tool confirmation missing correlationId; falling back to direct confirmation callback.');
            void confirmationDetails.onConfirm(outcome);
            return;
        }
        const messageBus = config.getMessageBus();
        messageBus.publish({
            type: MessageBusType.TOOL_CONFIRMATION_RESPONSE,
            correlationId,
            outcome,
            confirmed: outcome !== ToolConfirmationOutcome.Cancel &&
                outcome !== ToolConfirmationOutcome.ModifyWithEditor,
            requiresUserConfirmation: false,
        });
        // Handle IDE operations asynchronously without blocking
        if (confirmationDetails.type === 'edit') {
            const ideClient = config.getIdeClient();
            if (config.getIdeMode()) {
                const cliOutcome = outcome === ToolConfirmationOutcome.Cancel
                    ? 'rejected'
                    : 'accepted';
                // Fire and forget with error handling to ensure it never blocks
                setTimeout(() => {
                    ideClient
                        ?.resolveDiffFromCli(confirmationDetails.filePath, cliOutcome)
                        .catch((err) => {
                        console.error('Failed to resolve IDE diff:', err);
                    });
                }, 0);
            }
        }
    }, [confirmationDetails, config]);
    const isTrustedFolder = config.isTrustedFolder();
    useKeypress((key) => {
        if (!isFocused)
            return;
        if (key.name === 'escape' || (key.ctrl && key.name === 'c')) {
            handleConfirm(ToolConfirmationOutcome.Cancel);
        }
        // Handle 'd' key for details toggle
        if (key.name === 'd') {
            setShowDetails(!showDetails);
        }
    }, { isActive: isFocused });
    const handleSelect = useCallback((item) => handleConfirm(item), [handleConfirm]);
    // Helper function to determine if we should show details toggle
    const shouldShowDetailsToggle = (type) => {
        if (type === 'edit')
            return false; // Edit diffs always show full content
        // For exec commands, show toggle if command is long
        if (type === 'exec') {
            const execDetails = confirmationDetails;
            return execDetails.command.length > 50;
        }
        // For info commands, show toggle if there are multiple URLs or long prompt
        if (type === 'info') {
            const infoDetails = confirmationDetails;
            const hasMultipleUrls = infoDetails.urls && infoDetails.urls.length > 2;
            const hasLongPrompt = infoDetails.prompt && infoDetails.prompt.length > 80;
            return Boolean(hasMultipleUrls || hasLongPrompt);
        }
        // For MCP commands, always allow details toggle
        return true;
    };
    // Helper function to create summary content
    const createSummary = (type) => {
        if (type === 'exec') {
            const execDetails = confirmationDetails;
            return `Execute: ${execDetails.rootCommand}`;
        }
        if (type === 'info') {
            const infoDetails = confirmationDetails;
            return truncateEnd(infoDetails.prompt || 'Web fetch operation', 60);
        }
        if (type === 'mcp') {
            const mcpDetails = confirmationDetails;
            return `MCP Tool: ${mcpDetails.toolName} from ${mcpDetails.serverName}`;
        }
        return 'Operation details';
    };
    let bodyContent = null;
    let question;
    const options = new Array();
    const enableDetailsToggle = shouldShowDetailsToggle(confirmationDetails.type);
    // Different detail levels based on width
    const shouldShowSummary = enableDetailsToggle && !showDetails && breakpoint === 'NARROW';
    const shouldShowPartialDetails = enableDetailsToggle &&
        !showDetails &&
        (breakpoint === 'STANDARD' || breakpoint === 'WIDE');
    // Body content is now the DiffRenderer, passing filename to it
    // The bordered box is removed from here and handled within DiffRenderer
    function availableBodyContentHeight() {
        if (options.length === 0) {
            // This should not happen in practice as options are always added before this is called.
            throw new Error('Options not provided for confirmation message');
        }
        if (availableTerminalHeight === undefined) {
            return undefined;
        }
        // Calculate the vertical space (in lines) consumed by UI elements
        // surrounding the main body content.
        const PADDING_OUTER_Y = 2; // Main container has `padding={1}` (top & bottom).
        const MARGIN_BODY_BOTTOM = 1; // margin on the body container.
        const HEIGHT_QUESTION = 1; // The question text is one line.
        const MARGIN_QUESTION_BOTTOM = 1; // Margin on the question container.
        const HEIGHT_OPTIONS = options.length; // Each option in the radio select takes one line.
        const surroundingElementsHeight = PADDING_OUTER_Y +
            MARGIN_BODY_BOTTOM +
            HEIGHT_QUESTION +
            MARGIN_QUESTION_BOTTOM +
            HEIGHT_OPTIONS;
        return Math.max(availableTerminalHeight - surroundingElementsHeight, 1);
    }
    if (confirmationDetails.type === 'edit') {
        if (confirmationDetails.isModifying) {
            return (_jsxs(Box, { minWidth: "90%", borderStyle: "round", borderColor: Colors.Gray, justifyContent: "space-around", padding: 1, overflow: "hidden", children: [_jsx(Text, { children: "Modify in progress: " }), _jsx(Text, { color: Colors.AccentGreen, children: "Save and close external editor to continue" })] }));
        }
        question = `Apply this change?`;
        options.push({
            label: 'Yes, allow once',
            value: ToolConfirmationOutcome.ProceedOnce,
            key: 'Yes, allow once',
        });
        if (isTrustedFolder) {
            options.push({
                label: 'Yes, allow always',
                value: ToolConfirmationOutcome.ProceedAlways,
                key: 'Yes, allow always',
            });
        }
        if (config.getIdeMode()) {
            options.push({
                label: 'No (esc)',
                value: ToolConfirmationOutcome.Cancel,
                key: 'No (esc)',
            });
        }
        else {
            options.push({
                label: 'Modify with external editor',
                value: ToolConfirmationOutcome.ModifyWithEditor,
                key: 'Modify with external editor',
            });
            options.push({
                label: 'No, suggest changes (esc)',
                value: ToolConfirmationOutcome.Cancel,
                key: 'No, suggest changes (esc)',
            });
        }
        bodyContent = (_jsx(DiffRenderer, { diffContent: confirmationDetails.fileDiff, filename: confirmationDetails.fileName, availableTerminalHeight: availableBodyContentHeight(), terminalWidth: childWidth }));
    }
    else if (confirmationDetails.type === 'exec') {
        const executionProps = confirmationDetails;
        question = `Allow execution of: '${executionProps.rootCommand}'?`;
        options.push({
            label: 'Yes, allow once',
            value: ToolConfirmationOutcome.ProceedOnce,
            key: 'Yes, allow once',
        });
        if (isTrustedFolder) {
            options.push({
                label: `Yes, allow always ...`,
                value: ToolConfirmationOutcome.ProceedAlways,
                key: `Yes, allow always ...`,
            });
        }
        options.push({
            label: 'No, suggest changes (esc)',
            value: ToolConfirmationOutcome.Cancel,
            key: 'No, suggest changes (esc)',
        });
        let bodyContentHeight = availableBodyContentHeight();
        if (bodyContentHeight !== undefined) {
            bodyContentHeight -= 2; // Account for padding;
        }
        if (shouldShowSummary) {
            // Show summary with details toggle
            bodyContent = (_jsxs(Box, { flexDirection: "column", paddingX: 1, marginLeft: 1, children: [_jsx(Text, { color: SemanticColors.text.primary, children: createSummary('exec') }), _jsx(Text, { color: SemanticColors.text.secondary, dimColor: true, children: "Press 'd' to see full details" })] }));
        }
        else if (shouldShowPartialDetails) {
            // Show partial details with toggle for full details (at wide width)
            const commandPreview = executionProps.command.length > 50
                ? executionProps.command.substring(0, 50) + '...'
                : executionProps.command;
            bodyContent = (_jsxs(Box, { flexDirection: "column", paddingX: 1, marginLeft: 1, children: [_jsx(Text, { color: Colors.AccentCyan, children: commandPreview }), _jsx(Text, { color: SemanticColors.text.secondary, dimColor: true, children: "Press 'd' to see full details" })] }));
        }
        else {
            // Show full details
            bodyContent = (_jsxs(Box, { flexDirection: "column", children: [enableDetailsToggle && showDetails && (_jsx(Box, { paddingX: 1, marginLeft: 1, marginBottom: 1, children: _jsx(Text, { color: SemanticColors.text.secondary, children: "Full Parameters:" }) })), _jsx(Box, { paddingX: 1, marginLeft: 1, children: _jsx(MaxSizedBox, { maxHeight: bodyContentHeight, maxWidth: Math.max(childWidth - 4, 1), children: _jsx(Box, { children: _jsx(Text, { color: Colors.AccentCyan, children: executionProps.command }) }) }) })] }));
        }
    }
    else if (confirmationDetails.type === 'info') {
        const infoProps = confirmationDetails;
        const displayUrls = infoProps.urls &&
            !(infoProps.urls.length === 1 && infoProps.urls[0] === infoProps.prompt);
        question = `Do you want to proceed?`;
        options.push({
            label: 'Yes, allow once',
            value: ToolConfirmationOutcome.ProceedOnce,
            key: 'Yes, allow once',
        });
        if (isTrustedFolder) {
            options.push({
                label: 'Yes, allow always',
                value: ToolConfirmationOutcome.ProceedAlways,
                key: 'Yes, allow always',
            });
        }
        options.push({
            label: 'No, suggest changes (esc)',
            value: ToolConfirmationOutcome.Cancel,
            key: 'No, suggest changes (esc)',
        });
        if (shouldShowSummary) {
            // Show summary with details toggle
            bodyContent = (_jsxs(Box, { flexDirection: "column", paddingX: 1, marginLeft: 1, children: [_jsx(Text, { color: SemanticColors.text.primary, children: createSummary('info') }), _jsx(Text, { color: SemanticColors.text.secondary, dimColor: true, children: "Press 'd' to see full details" })] }));
        }
        else {
            // Show full details
            bodyContent = (_jsxs(Box, { flexDirection: "column", paddingX: 1, marginLeft: 1, children: [enableDetailsToggle && showDetails && (_jsx(Box, { marginBottom: 1, children: _jsx(Text, { color: SemanticColors.text.secondary, children: "Full Parameters:" }) })), _jsx(Text, { color: Colors.AccentCyan, children: _jsx(RenderInline, { text: infoProps.prompt }) }), displayUrls && infoProps.urls && infoProps.urls.length > 0 && (_jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsx(Text, { children: "URLs to fetch:" }), infoProps.urls.map((url) => (_jsxs(Text, { children: [' ', "- ", _jsx(RenderInline, { text: url })] }, url)))] }))] }));
        }
    }
    else {
        // mcp tool confirmation
        const mcpProps = confirmationDetails;
        if (shouldShowSummary) {
            // Show summary with details toggle
            bodyContent = (_jsxs(Box, { flexDirection: "column", paddingX: 1, marginLeft: 1, children: [_jsx(Text, { color: SemanticColors.text.primary, children: createSummary('mcp') }), _jsx(Text, { color: SemanticColors.text.secondary, dimColor: true, children: "Press 'd' to see full details" })] }));
        }
        else {
            // Show full details
            bodyContent = (_jsxs(Box, { flexDirection: "column", paddingX: 1, marginLeft: 1, children: [enableDetailsToggle && showDetails && (_jsx(Box, { marginBottom: 1, children: _jsx(Text, { color: SemanticColors.text.secondary, children: "Full Parameters:" }) })), _jsxs(Text, { color: Colors.AccentCyan, children: ["MCP Server: ", mcpProps.serverName] }), _jsxs(Text, { color: Colors.AccentCyan, children: ["Tool: ", mcpProps.toolName] })] }));
        }
        question = `Allow execution of MCP tool "${mcpProps.toolName}" from server "${mcpProps.serverName}"?`;
        options.push({
            label: 'Yes, allow once',
            value: ToolConfirmationOutcome.ProceedOnce,
            key: 'Yes, allow once',
        });
        if (isTrustedFolder) {
            options.push({
                label: `Yes, always allow tool "${mcpProps.toolName}" from server "${mcpProps.serverName}"`,
                value: ToolConfirmationOutcome.ProceedAlwaysTool, // Cast until types are updated
                key: `Yes, always allow tool "${mcpProps.toolName}" from server "${mcpProps.serverName}"`,
            });
            options.push({
                label: `Yes, always allow all tools from server "${mcpProps.serverName}"`,
                value: ToolConfirmationOutcome.ProceedAlwaysServer,
                key: `Yes, always allow all tools from server "${mcpProps.serverName}"`,
            });
        }
        options.push({
            label: 'No, suggest changes (esc)',
            value: ToolConfirmationOutcome.Cancel,
            key: 'No, suggest changes (esc)',
        });
    }
    return (_jsxs(Box, { flexDirection: "column", padding: 1, width: childWidth, children: [_jsx(Box, { flexGrow: 1, flexShrink: 1, overflow: "hidden", marginBottom: 1, children: bodyContent }), _jsx(Box, { marginBottom: 1, flexShrink: 0, children: _jsx(Text, { wrap: "truncate", color: SemanticColors.status.success, children: question }) }), _jsx(Box, { flexShrink: 0, children: _jsx(RadioButtonSelect, { items: options, onSelect: handleSelect, isFocused: isFocused }) })] }));
};
//# sourceMappingURL=ToolConfirmationMessage.js.map