import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { useCallback, useMemo, useRef, useEffect, useReducer, useContext, } from 'react';
import { Box, Text } from 'ink';
import { theme } from '../semantic-colors.js';
import { BaseSelectionList } from './shared/BaseSelectionList.js';
import { TabHeader } from './shared/TabHeader.js';
import { useKeypress } from '../hooks/useKeypress.js';
import { keyMatchers, Command } from '../keyMatchers.js';
import { checkExhaustive } from '@google/gemini-cli-core';
import { TextInput } from './shared/TextInput.js';
import { useTextBuffer } from './shared/text-buffer.js';
import { getCachedStringWidth } from '../utils/textUtils.js';
import { useTabbedNavigation } from '../hooks/useTabbedNavigation.js';
import { DialogFooter } from './shared/DialogFooter.js';
import { MarkdownDisplay } from '../utils/MarkdownDisplay.js';
import { RenderInline } from '../utils/InlineMarkdownRenderer.js';
import { MaxSizedBox } from './shared/MaxSizedBox.js';
import { UIStateContext } from '../contexts/UIStateContext.js';
import { useAlternateBuffer } from '../hooks/useAlternateBuffer.js';
/** Padding for dialog content to prevent text from touching edges. */
const DIALOG_PADDING = 4;
/**
 * Checks if text is a single line without markdown identifiers.
 */
function isPlainSingleLine(text) {
    // Must be a single line (no newlines)
    if (text.includes('\n') || text.includes('\r')) {
        return false;
    }
    // Check for common markdown identifiers
    const markdownPatterns = [
        /^#{1,6}\s/, // Headers
        /^[`~]{3,}/, // Code fences
        /^[-*+]\s/, // Unordered lists
        /^\d+\.\s/, // Ordered lists
        /^[-*_]{3,}$/, // Horizontal rules
        /\|/, // Tables
        /\*\*|__/, // Bold
        /(?<!\*)\*(?!\*)/, // Italic (single asterisk not part of bold)
        /(?<!_)_(?!_)/, // Italic (single underscore not part of bold)
        /`[^`]+`/, // Inline code
        /\[.*?\]\(.*?\)/, // Links
        /!\[/, // Images
    ];
    for (const pattern of markdownPatterns) {
        if (pattern.test(text)) {
            return false;
        }
    }
    return true;
}
/**
 * Auto-bolds plain single-line text by wrapping in **.
 * Returns the text unchanged if it already contains markdown.
 */
function autoBoldIfPlain(text) {
    if (isPlainSingleLine(text)) {
        return `**${text}**`;
    }
    return text;
}
const initialState = {
    answers: {},
    isEditingCustomOption: false,
    submitted: false,
};
function askUserDialogReducerLogic(state, action) {
    if (state.submitted) {
        return state;
    }
    switch (action.type) {
        case 'SET_ANSWER': {
            const { index, answer, submit } = action.payload;
            const hasAnswer = answer !== undefined && answer !== null && answer.trim() !== '';
            const newAnswers = { ...state.answers };
            if (hasAnswer) {
                newAnswers[index] = answer;
            }
            else {
                delete newAnswers[index];
            }
            return {
                ...state,
                answers: newAnswers,
                submitted: submit ? true : state.submitted,
            };
        }
        case 'SET_EDITING_CUSTOM': {
            if (state.isEditingCustomOption === action.payload.isEditing) {
                return state;
            }
            return {
                ...state,
                isEditingCustomOption: action.payload.isEditing,
            };
        }
        case 'SUBMIT': {
            return {
                ...state,
                submitted: true,
            };
        }
        default:
            checkExhaustive(action);
            return state;
    }
}
const ReviewView = ({ questions, answers, onSubmit, progressHeader, extraParts, }) => {
    const unansweredCount = questions.length - Object.keys(answers).length;
    const hasUnanswered = unansweredCount > 0;
    // Handle Enter to submit
    useKeypress((key) => {
        if (keyMatchers[Command.RETURN](key)) {
            onSubmit();
            return true;
        }
        return false;
    }, { isActive: true });
    return (_jsxs(Box, { flexDirection: "column", children: [progressHeader, _jsx(Box, { marginBottom: 1, children: _jsx(Text, { bold: true, color: theme.text.primary, children: "Review your answers:" }) }), hasUnanswered && (_jsx(Box, { marginBottom: 1, children: _jsxs(Text, { color: theme.status.warning, children: ["\u26A0 You have ", unansweredCount, " unanswered question", unansweredCount > 1 ? 's' : ''] }) })), _jsx(Box, { flexDirection: "column", children: questions.map((q, i) => (_jsxs(Box, { marginBottom: 0, children: [_jsx(Text, { color: theme.text.secondary, children: q.header }), _jsx(Text, { color: theme.text.secondary, children: " \u2192 " }), _jsx(Text, { color: answers[i] ? theme.text.primary : theme.status.warning, children: answers[i] || '(not answered)' })] }, i))) }), _jsx(DialogFooter, { primaryAction: "Enter to submit", navigationActions: "Tab/Shift+Tab to edit answers", extraParts: extraParts })] }));
};
const TextQuestionView = ({ question, onAnswer, onSelectionChange, onEditingCustomOption, availableWidth, availableHeight, initialAnswer, progressHeader, keyboardHints, }) => {
    const isAlternateBuffer = useAlternateBuffer();
    const prefix = '> ';
    const horizontalPadding = 1; // 1 for cursor
    const bufferWidth = availableWidth - getCachedStringWidth(prefix) - horizontalPadding;
    const buffer = useTextBuffer({
        initialText: initialAnswer,
        viewport: { width: Math.max(1, bufferWidth), height: 3 },
        singleLine: false,
    });
    const { text: textValue } = buffer;
    // Sync state change with parent - only when it actually changes
    const lastTextValueRef = useRef(textValue);
    useEffect(() => {
        if (textValue !== lastTextValueRef.current) {
            onSelectionChange?.(textValue);
            lastTextValueRef.current = textValue;
        }
    }, [textValue, onSelectionChange]);
    // Handle Ctrl+C to clear all text
    const handleExtraKeys = useCallback((key) => {
        if (keyMatchers[Command.QUIT](key)) {
            if (textValue === '') {
                return false;
            }
            buffer.setText('');
            return true;
        }
        return false;
    }, [buffer, textValue]);
    useKeypress(handleExtraKeys, { isActive: true, priority: true });
    const handleSubmit = useCallback((val) => {
        onAnswer(val.trim());
    }, [onAnswer]);
    // Notify parent that we're in text input mode (for Ctrl+C handling)
    useEffect(() => {
        onEditingCustomOption?.(true);
        return () => {
            onEditingCustomOption?.(false);
        };
    }, [onEditingCustomOption]);
    const placeholder = question.placeholder || 'Enter your response';
    const HEADER_HEIGHT = progressHeader ? 2 : 0;
    const INPUT_HEIGHT = 2; // TextInput + margin
    const FOOTER_HEIGHT = 2; // DialogFooter + margin
    const overhead = HEADER_HEIGHT + INPUT_HEIGHT + FOOTER_HEIGHT;
    const questionHeight = availableHeight && !isAlternateBuffer
        ? Math.max(1, availableHeight - overhead)
        : undefined;
    return (_jsxs(Box, { flexDirection: "column", children: [progressHeader, _jsx(Box, { marginBottom: 1, children: _jsx(MaxSizedBox, { maxHeight: questionHeight, maxWidth: availableWidth, overflowDirection: "bottom", children: _jsx(MarkdownDisplay, { text: autoBoldIfPlain(question.question), terminalWidth: availableWidth - DIALOG_PADDING, isPending: false }) }) }), _jsxs(Box, { flexDirection: "row", marginBottom: 1, children: [_jsx(Text, { color: theme.status.success, children: '> ' }), _jsx(TextInput, { buffer: buffer, placeholder: placeholder, onSubmit: handleSubmit })] }), keyboardHints] }));
};
function choiceQuestionReducer(state, action) {
    switch (action.type) {
        case 'TOGGLE_INDEX': {
            const { index, multiSelect } = action.payload;
            const newIndices = new Set(multiSelect ? state.selectedIndices : []);
            if (newIndices.has(index)) {
                newIndices.delete(index);
            }
            else {
                newIndices.add(index);
            }
            return {
                ...state,
                selectedIndices: newIndices,
                // In single select, selecting an option deselects custom
                isCustomOptionSelected: multiSelect
                    ? state.isCustomOptionSelected
                    : false,
            };
        }
        case 'SET_CUSTOM_SELECTED': {
            const { selected, multiSelect } = action.payload;
            return {
                ...state,
                isCustomOptionSelected: selected,
                // In single-select, selecting custom deselects others
                selectedIndices: multiSelect ? state.selectedIndices : new Set(),
            };
        }
        case 'TOGGLE_CUSTOM_SELECTED': {
            const { multiSelect } = action.payload;
            if (!multiSelect)
                return state;
            return {
                ...state,
                isCustomOptionSelected: !state.isCustomOptionSelected,
            };
        }
        case 'SET_CUSTOM_FOCUSED': {
            return {
                ...state,
                isCustomOptionFocused: action.payload.focused,
            };
        }
        default:
            checkExhaustive(action);
            return state;
    }
}
const ChoiceQuestionView = ({ question, onAnswer, onSelectionChange, onEditingCustomOption, availableWidth, availableHeight, initialAnswer, progressHeader, keyboardHints, }) => {
    const isAlternateBuffer = useAlternateBuffer();
    const numOptions = (question.options?.length ?? 0) + (question.type !== 'yesno' ? 1 : 0);
    const numLen = String(numOptions).length;
    const radioWidth = 2; // "● "
    const numberWidth = numLen + 2; // e.g., "1. "
    const checkboxWidth = question.multiSelect ? 4 : 1; // "[x] " or " "
    const checkmarkWidth = question.multiSelect ? 0 : 2; // "" or " ✓"
    const cursorPadding = 1; // Extra character for cursor at end of line
    const horizontalPadding = radioWidth + numberWidth + checkboxWidth + checkmarkWidth + cursorPadding;
    const bufferWidth = availableWidth - horizontalPadding;
    const questionOptions = useMemo(() => question.options ?? [], [question.options]);
    // Initialize state from initialAnswer if returning to a previously answered question
    const initialReducerState = useMemo(() => {
        if (!initialAnswer) {
            return {
                selectedIndices: new Set(),
                isCustomOptionSelected: false,
                isCustomOptionFocused: false,
            };
        }
        // Check if initialAnswer matches any option labels
        const selectedIndices = new Set();
        let isCustomOptionSelected = false;
        if (question.multiSelect) {
            const answers = initialAnswer.split(', ');
            answers.forEach((answer) => {
                const index = questionOptions.findIndex((opt) => opt.label === answer);
                if (index !== -1) {
                    selectedIndices.add(index);
                }
                else {
                    isCustomOptionSelected = true;
                }
            });
        }
        else {
            const index = questionOptions.findIndex((opt) => opt.label === initialAnswer);
            if (index !== -1) {
                selectedIndices.add(index);
            }
            else {
                isCustomOptionSelected = true;
            }
        }
        return {
            selectedIndices,
            isCustomOptionSelected,
            isCustomOptionFocused: false,
        };
    }, [initialAnswer, questionOptions, question.multiSelect]);
    const [state, dispatch] = useReducer(choiceQuestionReducer, initialReducerState);
    const { selectedIndices, isCustomOptionSelected, isCustomOptionFocused } = state;
    const initialCustomText = useMemo(() => {
        if (!initialAnswer)
            return '';
        if (question.multiSelect) {
            const answers = initialAnswer.split(', ');
            const custom = answers.find((a) => !questionOptions.some((opt) => opt.label === a));
            return custom || '';
        }
        else {
            const isPredefined = questionOptions.some((opt) => opt.label === initialAnswer);
            return isPredefined ? '' : initialAnswer;
        }
    }, [initialAnswer, questionOptions, question.multiSelect]);
    const customBuffer = useTextBuffer({
        initialText: initialCustomText,
        viewport: { width: Math.max(1, bufferWidth), height: 3 },
        singleLine: false,
    });
    const customOptionText = customBuffer.text;
    // Helper to build answer string from selections
    const buildAnswerString = useCallback((indices, includeCustomOption, customOption) => {
        const answers = [];
        questionOptions.forEach((opt, i) => {
            if (indices.has(i)) {
                answers.push(opt.label);
            }
        });
        if (includeCustomOption && customOption.trim()) {
            answers.push(customOption.trim());
        }
        return answers.join(', ');
    }, [questionOptions]);
    // Synchronize selection changes with parent - only when it actually changes
    const lastBuiltAnswerRef = useRef('');
    useEffect(() => {
        const newAnswer = buildAnswerString(selectedIndices, isCustomOptionSelected, customOptionText);
        if (newAnswer !== lastBuiltAnswerRef.current) {
            onSelectionChange?.(newAnswer);
            lastBuiltAnswerRef.current = newAnswer;
        }
    }, [
        selectedIndices,
        isCustomOptionSelected,
        customOptionText,
        buildAnswerString,
        onSelectionChange,
    ]);
    // Handle "Type-to-Jump" and Ctrl+C for custom buffer
    const handleExtraKeys = useCallback((key) => {
        // If focusing custom option, handle Ctrl+C
        if (isCustomOptionFocused && keyMatchers[Command.QUIT](key)) {
            if (customOptionText === '') {
                return false;
            }
            customBuffer.setText('');
            return true;
        }
        // Don't jump if a navigation or selection key is pressed
        if (keyMatchers[Command.DIALOG_NAVIGATION_UP](key) ||
            keyMatchers[Command.DIALOG_NAVIGATION_DOWN](key) ||
            keyMatchers[Command.DIALOG_NEXT](key) ||
            keyMatchers[Command.DIALOG_PREV](key) ||
            keyMatchers[Command.MOVE_LEFT](key) ||
            keyMatchers[Command.MOVE_RIGHT](key) ||
            keyMatchers[Command.RETURN](key) ||
            keyMatchers[Command.ESCAPE](key) ||
            keyMatchers[Command.QUIT](key)) {
            return false;
        }
        // Check if it's a numeric quick selection key (if numbers are shown)
        const isNumeric = /^[0-9]$/.test(key.sequence);
        if (isNumeric) {
            return false;
        }
        // Type-to-jump: if printable characters are typed and not focused, jump to custom
        const isPrintable = key.sequence &&
            !key.ctrl &&
            !key.alt &&
            (key.sequence.length > 1 || key.sequence.charCodeAt(0) >= 32);
        if (isPrintable && !isCustomOptionFocused) {
            dispatch({ type: 'SET_CUSTOM_FOCUSED', payload: { focused: true } });
            onEditingCustomOption?.(true);
            // For IME or multi-char sequences, we want to capture the whole thing.
            // If it's a single char, we start the buffer with it.
            customBuffer.setText(key.sequence);
            return true;
        }
        return false;
    }, [
        isCustomOptionFocused,
        customBuffer,
        onEditingCustomOption,
        customOptionText,
    ]);
    useKeypress(handleExtraKeys, { isActive: true, priority: true });
    const selectionItems = useMemo(() => {
        const list = questionOptions.map((opt, i) => {
            const item = {
                key: `opt-${i}`,
                label: opt.label,
                description: opt.description,
                type: 'option',
                index: i,
            };
            return { key: item.key, value: item };
        });
        // Only add custom option for choice type, not yesno
        if (question.type !== 'yesno') {
            const otherItem = {
                key: 'other',
                label: customOptionText || '',
                description: '',
                type: 'other',
                index: list.length,
            };
            list.push({ key: 'other', value: otherItem });
        }
        if (question.multiSelect) {
            const doneItem = {
                key: 'done',
                label: 'Done',
                description: 'Finish selection',
                type: 'done',
                index: list.length,
            };
            list.push({ key: doneItem.key, value: doneItem, hideNumber: true });
        }
        return list;
    }, [questionOptions, question.multiSelect, question.type, customOptionText]);
    const handleHighlight = useCallback((itemValue) => {
        const nowFocusingCustomOption = itemValue.type === 'other';
        dispatch({
            type: 'SET_CUSTOM_FOCUSED',
            payload: { focused: nowFocusingCustomOption },
        });
        // Notify parent when we start/stop focusing custom option (so navigation can resume)
        onEditingCustomOption?.(nowFocusingCustomOption);
    }, [onEditingCustomOption]);
    const handleSelect = useCallback((itemValue) => {
        if (question.multiSelect) {
            if (itemValue.type === 'option') {
                dispatch({
                    type: 'TOGGLE_INDEX',
                    payload: { index: itemValue.index, multiSelect: true },
                });
            }
            else if (itemValue.type === 'other') {
                dispatch({
                    type: 'TOGGLE_CUSTOM_SELECTED',
                    payload: { multiSelect: true },
                });
            }
            else if (itemValue.type === 'done') {
                // Done just triggers navigation, selections already saved via useEffect
                onAnswer(buildAnswerString(selectedIndices, isCustomOptionSelected, customOptionText));
            }
        }
        else {
            if (itemValue.type === 'option') {
                onAnswer(itemValue.label);
            }
            else if (itemValue.type === 'other') {
                // In single select, selecting other submits it if it has text
                if (customOptionText.trim()) {
                    onAnswer(customOptionText.trim());
                }
            }
        }
    }, [
        question.multiSelect,
        selectedIndices,
        isCustomOptionSelected,
        customOptionText,
        onAnswer,
        buildAnswerString,
    ]);
    // Auto-select custom option when typing in it
    useEffect(() => {
        if (customOptionText.trim() && !isCustomOptionSelected) {
            dispatch({
                type: 'SET_CUSTOM_SELECTED',
                payload: { selected: true, multiSelect: !!question.multiSelect },
            });
        }
    }, [customOptionText, isCustomOptionSelected, question.multiSelect]);
    const HEADER_HEIGHT = progressHeader ? 2 : 0;
    const TITLE_MARGIN = 1;
    const FOOTER_HEIGHT = 2; // DialogFooter + margin
    const overhead = HEADER_HEIGHT + TITLE_MARGIN + FOOTER_HEIGHT;
    const listHeight = availableHeight
        ? Math.max(1, availableHeight - overhead)
        : undefined;
    const questionHeightLimit = listHeight && !isAlternateBuffer
        ? question.unconstrainedHeight
            ? Math.max(1, listHeight - selectionItems.length * 2)
            : Math.min(15, Math.max(1, listHeight - DIALOG_PADDING))
        : undefined;
    const maxItemsToShow = listHeight && questionHeightLimit
        ? Math.max(1, Math.floor((listHeight - questionHeightLimit) / 2))
        : selectionItems.length;
    return (_jsxs(Box, { flexDirection: "column", children: [progressHeader, _jsx(Box, { marginBottom: TITLE_MARGIN, children: _jsx(MaxSizedBox, { maxHeight: questionHeightLimit, maxWidth: availableWidth, overflowDirection: "bottom", children: _jsxs(Box, { flexDirection: "column", children: [_jsx(MarkdownDisplay, { text: autoBoldIfPlain(question.question), terminalWidth: availableWidth - DIALOG_PADDING, isPending: false }), question.multiSelect && (_jsx(Text, { color: theme.text.secondary, italic: true, children: "(Select all that apply)" }))] }) }) }), _jsx(BaseSelectionList, { items: selectionItems, onSelect: handleSelect, onHighlight: handleHighlight, focusKey: isCustomOptionFocused ? 'other' : undefined, maxItemsToShow: maxItemsToShow, showScrollArrows: true, renderItem: (item, context) => {
                    const optionItem = item.value;
                    const isChecked = selectedIndices.has(optionItem.index) ||
                        (optionItem.type === 'other' && isCustomOptionSelected);
                    const showCheck = question.multiSelect &&
                        (optionItem.type === 'option' || optionItem.type === 'other');
                    // Render inline text input for custom option
                    if (optionItem.type === 'other') {
                        const placeholder = question.placeholder || 'Enter a custom value';
                        return (_jsxs(Box, { flexDirection: "row", children: [showCheck && (_jsxs(Text, { color: isChecked ? theme.status.success : theme.text.secondary, children: ["[", isChecked ? 'x' : ' ', "]"] })), _jsx(Text, { color: theme.text.primary, children: " " }), _jsx(TextInput, { buffer: customBuffer, placeholder: placeholder, focus: context.isSelected, onSubmit: (val) => {
                                        if (question.multiSelect) {
                                            const fullAnswer = buildAnswerString(selectedIndices, true, val);
                                            if (fullAnswer) {
                                                onAnswer(fullAnswer);
                                            }
                                        }
                                        else if (val.trim()) {
                                            onAnswer(val.trim());
                                        }
                                    } }), isChecked && !question.multiSelect && !context.isSelected && (_jsx(Text, { color: theme.status.success, children: " \u2713" }))] }));
                    }
                    // Determine label color: checked (previously answered) uses success, selected uses accent, else primary
                    const labelColor = isChecked && !question.multiSelect
                        ? theme.status.success
                        : context.isSelected
                            ? context.titleColor
                            : theme.text.primary;
                    return (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Box, { flexDirection: "row", children: [showCheck && (_jsxs(Text, { color: isChecked ? theme.status.success : theme.text.secondary, children: ["[", isChecked ? 'x' : ' ', "]"] })), _jsxs(Text, { color: labelColor, bold: optionItem.type === 'done', children: [' ', optionItem.label] }), isChecked && !question.multiSelect && (_jsx(Text, { color: theme.status.success, children: " \u2713" }))] }), optionItem.description && (_jsxs(Text, { color: theme.text.secondary, wrap: "wrap", children: [' ', _jsx(RenderInline, { text: optionItem.description, defaultColor: theme.text.secondary })] }))] }));
                } }), keyboardHints] }));
};
export const AskUserDialog = ({ questions, onSubmit, onCancel, onActiveTextInputChange, width, availableHeight: availableHeightProp, extraParts, }) => {
    const uiState = useContext(UIStateContext);
    const availableHeight = availableHeightProp ??
        (uiState?.constrainHeight !== false
            ? uiState?.availableTerminalHeight
            : undefined);
    const [state, dispatch] = useReducer(askUserDialogReducerLogic, initialState);
    const { answers, isEditingCustomOption, submitted } = state;
    const reviewTabIndex = questions.length;
    const tabCount = questions.length > 1 ? questions.length + 1 : questions.length;
    const { currentIndex, goToNextTab, goToPrevTab } = useTabbedNavigation({
        tabCount,
        isActive: !submitted && questions.length > 1,
        enableArrowNavigation: false, // We'll handle arrows via textBuffer callbacks or manually
        enableTabKey: false, // We'll handle tab manually to match existing behavior
    });
    const currentQuestionIndex = currentIndex;
    const handleEditingCustomOption = useCallback((isEditing) => {
        dispatch({ type: 'SET_EDITING_CUSTOM', payload: { isEditing } });
    }, []);
    useEffect(() => {
        onActiveTextInputChange?.(isEditingCustomOption);
        return () => {
            onActiveTextInputChange?.(false);
        };
    }, [isEditingCustomOption, onActiveTextInputChange]);
    const handleCancel = useCallback((key) => {
        if (submitted)
            return false;
        if (keyMatchers[Command.ESCAPE](key)) {
            onCancel();
            return true;
        }
        else if (keyMatchers[Command.QUIT](key)) {
            if (!isEditingCustomOption) {
                onCancel();
            }
            // Return false to let ctrl-C bubble up to AppContainer for exit flow
            return false;
        }
        return false;
    }, [onCancel, submitted, isEditingCustomOption]);
    useKeypress(handleCancel, {
        isActive: !submitted,
    });
    const isOnReviewTab = currentQuestionIndex === reviewTabIndex;
    const handleNavigation = useCallback((key) => {
        if (submitted || questions.length <= 1)
            return false;
        const isNextKey = keyMatchers[Command.DIALOG_NEXT](key);
        const isPrevKey = keyMatchers[Command.DIALOG_PREV](key);
        const isRight = keyMatchers[Command.MOVE_RIGHT](key);
        const isLeft = keyMatchers[Command.MOVE_LEFT](key);
        // Tab keys always trigger navigation.
        // Arrows trigger navigation if NOT in a text input OR if the input bubbles the event (already at edge).
        const shouldGoNext = isNextKey || isRight;
        const shouldGoPrev = isPrevKey || isLeft;
        if (shouldGoNext) {
            goToNextTab();
            return true;
        }
        else if (shouldGoPrev) {
            goToPrevTab();
            return true;
        }
        return false;
    }, [questions.length, submitted, goToNextTab, goToPrevTab]);
    useKeypress(handleNavigation, {
        isActive: questions.length > 1 && !submitted,
    });
    useEffect(() => {
        if (submitted) {
            onSubmit(answers);
        }
    }, [submitted, answers, onSubmit]);
    const handleAnswer = useCallback((answer) => {
        if (submitted)
            return;
        if (questions.length > 1) {
            dispatch({
                type: 'SET_ANSWER',
                payload: {
                    index: currentQuestionIndex,
                    answer,
                },
            });
            goToNextTab();
        }
        else {
            dispatch({
                type: 'SET_ANSWER',
                payload: {
                    index: currentQuestionIndex,
                    answer,
                    submit: true,
                },
            });
        }
    }, [currentQuestionIndex, questions, submitted, goToNextTab]);
    const handleReviewSubmit = useCallback(() => {
        if (submitted)
            return;
        dispatch({ type: 'SUBMIT' });
    }, [submitted]);
    const handleSelectionChange = useCallback((answer) => {
        if (submitted)
            return;
        dispatch({
            type: 'SET_ANSWER',
            payload: {
                index: currentQuestionIndex,
                answer,
            },
        });
    }, [submitted, currentQuestionIndex]);
    const answeredIndices = useMemo(() => new Set(Object.keys(answers).map(Number)), [answers]);
    const currentQuestion = questions[currentQuestionIndex];
    const effectiveQuestion = useMemo(() => {
        if (currentQuestion?.type === 'yesno') {
            return {
                ...currentQuestion,
                options: [
                    { label: 'Yes', description: '' },
                    { label: 'No', description: '' },
                ],
                multiSelect: false,
            };
        }
        return currentQuestion;
    }, [currentQuestion]);
    const tabs = useMemo(() => {
        const questionTabs = questions.map((q, i) => ({
            key: String(i),
            header: q.header,
        }));
        if (questions.length > 1) {
            questionTabs.push({
                key: 'review',
                header: 'Review',
                isSpecial: true,
            });
        }
        return questionTabs;
    }, [questions]);
    const progressHeader = questions.length > 1 ? (_jsx(TabHeader, { tabs: tabs, currentIndex: currentQuestionIndex, completedIndices: answeredIndices })) : null;
    if (isOnReviewTab) {
        return (_jsx(Box, { "aria-label": "Review your answers", children: _jsx(ReviewView, { questions: questions, answers: answers, onSubmit: handleReviewSubmit, progressHeader: progressHeader, extraParts: extraParts }) }));
    }
    if (!currentQuestion)
        return null;
    const keyboardHints = (_jsx(DialogFooter, { primaryAction: currentQuestion.type === 'text' || isEditingCustomOption
            ? 'Enter to submit'
            : 'Enter to select', navigationActions: questions.length > 1
            ? currentQuestion.type === 'text' || isEditingCustomOption
                ? 'Tab/Shift+Tab to switch questions'
                : '←/→ to switch questions'
            : currentQuestion.type === 'text' || isEditingCustomOption
                ? undefined
                : '↑/↓ to navigate', extraParts: extraParts }));
    const questionView = currentQuestion.type === 'text' ? (_jsx(TextQuestionView, { question: currentQuestion, onAnswer: handleAnswer, onSelectionChange: handleSelectionChange, onEditingCustomOption: handleEditingCustomOption, availableWidth: width, availableHeight: availableHeight, initialAnswer: answers[currentQuestionIndex], progressHeader: progressHeader, keyboardHints: keyboardHints }, currentQuestionIndex)) : (_jsx(ChoiceQuestionView, { question: effectiveQuestion, onAnswer: handleAnswer, onSelectionChange: handleSelectionChange, onEditingCustomOption: handleEditingCustomOption, availableWidth: width, availableHeight: availableHeight, initialAnswer: answers[currentQuestionIndex], progressHeader: progressHeader, keyboardHints: keyboardHints }, currentQuestionIndex));
    return (_jsx(Box, { flexDirection: "column", width: width, "aria-label": `Question ${currentQuestionIndex + 1} of ${questions.length}: ${currentQuestion.question}`, children: questionView }));
};
//# sourceMappingURL=AskUserDialog.js.map