import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
/**
 * @license
 * Copyright 2025 Vybestack LLC
 * SPDX-License-Identifier: Apache-2.0
 */
import React, { useState, useMemo } from 'react';
import { Box, Text, useInput } from 'ink';
import { SemanticColors } from '../colors.js';
import { useResponsive } from '../hooks/useResponsive.js';
import { truncateStart } from '../utils/responsive.js';
export const ProviderModelDialog = ({ models, currentModel, onSelect, onClose, }) => {
    const { isNarrow, isWide, width } = useResponsive();
    const [searchTerm, setSearchTerm] = useState('');
    const [isSearching, setIsSearching] = useState(true);
    // Sort models alphabetically by ID
    const sortedModels = useMemo(() => [...models].sort((a, b) => a.id.toLowerCase().localeCompare(b.id.toLowerCase())), [models]);
    // Filter models based on search term
    const filteredModels = useMemo(() => sortedModels.filter((m) => m.id.toLowerCase().includes(searchTerm.toLowerCase())), [sortedModels, searchTerm]);
    const [index, setIndex] = useState(() => Math.max(0, sortedModels.findIndex((m) => m.id === currentModel)));
    // Reset index when search term changes
    React.useEffect(() => {
        const currentIndex = filteredModels.findIndex((m) => m.id === currentModel);
        setIndex(Math.max(0, currentIndex));
    }, [searchTerm, filteredModels, currentModel]);
    // Calculate optimal layout based on available width and content
    const calculateLayout = () => {
        // Calculate minimum column width needed
        const longestModelName = filteredModels.reduce((len, m) => Math.max(len, m.id.length), 0);
        if (isNarrow) {
            return { columns: 1, colWidth: Math.max(longestModelName + 4, 25) };
        }
        // Step 1: Get actual content width - responsive to screen size
        // For narrow screens, use full width; for wider screens, use 80% of width
        const maxDialogWidth = isNarrow ? width : Math.floor(width * 0.8);
        const contentWidth = maxDialogWidth - 4; // 4 for padding/borders
        // Step 2: Calculate column width needed (model name + marker + small buffer)
        const markerWidth = 2; // "● " or "○ "
        const spacingBetweenCols = 4; // Fixed spacing between columns
        const colWidthNeeded = longestModelName + markerWidth + 1; // +1 for a tiny buffer
        // Step 3: Determine optimal column count
        // Try to fit as many columns as possible without truncation
        let optimalColumns = 1;
        for (let cols = 5; cols >= 1; cols--) {
            // Calculate total width needed for this many columns
            const totalWidthNeeded = colWidthNeeded * cols + spacingBetweenCols * (cols - 1);
            if (totalWidthNeeded <= contentWidth) {
                optimalColumns = cols;
                break;
            }
        }
        // If even 1 column doesn't fit, we'll need to truncate
        const columns = optimalColumns;
        // Step 4: Calculate actual column width
        if (columns === 1) {
            // Single column: use all available width
            return { columns: 1, colWidth: contentWidth };
        }
        else {
            // Multiple columns: use exact width needed + spacing
            return { columns, colWidth: colWidthNeeded };
        }
    };
    const layout = calculateLayout();
    const { columns, colWidth } = layout;
    const rows = Math.ceil(filteredModels.length / columns);
    const maxDialogWidth = isNarrow ? width : Math.floor(width * 0.8);
    const move = (delta) => {
        let next = index + delta;
        if (next < 0)
            next = 0;
        if (next >= filteredModels.length)
            next = filteredModels.length - 1;
        setIndex(next);
    };
    useInput((input, key) => {
        // Guard against undefined input to prevent Ink library errors
        if (!key)
            return;
        if (key.escape) {
            if (isSearching && searchTerm.length > 0) {
                setSearchTerm('');
            }
            else {
                return onClose();
            }
        }
        if (isSearching) {
            if (key.return) {
                if (filteredModels.length > 0) {
                    setIsSearching(false);
                }
            }
            else if (key.tab || (key.downArrow && searchTerm.length === 0)) {
                setIsSearching(false);
            }
            else if (key.backspace || key.delete) {
                setSearchTerm((prev) => prev.slice(0, -1));
            }
            else if (input && typeof input === 'string' && !key.ctrl && !key.meta) {
                setSearchTerm((prev) => prev + input);
            }
        }
        else {
            if (key.return && filteredModels.length > 0) {
                return onSelect(filteredModels[index].id);
            }
            if (key.tab || (key.upArrow && index === 0)) {
                setIsSearching(true);
            }
            if (key.leftArrow)
                move(-1);
            if (key.rightArrow)
                move(1);
            if (key.upArrow)
                move(-columns);
            if (key.downArrow)
                move(columns);
        }
    });
    const renderItem = (m, i, isLastInRow) => {
        const selected = i === index;
        // Calculate display name - truncate from start to preserve model name
        let displayName;
        const maxLength = colWidth - 3; // Account for marker and space
        if (m.id.length > maxLength) {
            // Truncate from start to preserve the important model name at the end
            displayName = truncateStart(m.id, maxLength);
        }
        else {
            displayName = m.id;
        }
        return (_jsx(Box, { width: colWidth, marginRight: isLastInRow ? 0 : 1, children: _jsxs(Text, { color: selected
                    ? SemanticColors.text.accent
                    : isSearching && !isNarrow
                        ? SemanticColors.text.secondary
                        : SemanticColors.text.primary, children: [selected ? '● ' : '○ ', displayName] }) }, m.id));
    };
    // Calculate visible items for scrolling (limit to reasonable amount)
    const maxVisibleRows = Math.min(rows, 10);
    const currentRow = Math.floor(index / columns);
    const scrollOffset = Math.max(0, Math.min(currentRow - Math.floor(maxVisibleRows / 2), rows - maxVisibleRows));
    const startIndex = scrollOffset * columns;
    const endIndex = Math.min(startIndex + maxVisibleRows * columns, filteredModels.length);
    const visibleModels = filteredModels.slice(startIndex, endIndex);
    // Create the model grid with proper row/column layout
    const renderModelGrid = () => {
        const gridRows = [];
        for (let row = 0; row < maxVisibleRows; row++) {
            const rowItems = [];
            for (let col = 0; col < columns; col++) {
                const idx = row * columns + col;
                if (idx < visibleModels.length) {
                    const isLastInRow = col === columns - 1;
                    rowItems.push(renderItem(visibleModels[idx], startIndex + idx, isLastInRow));
                }
            }
            if (rowItems.length > 0) {
                gridRows.push(_jsx(Box, { flexDirection: "row", children: rowItems }, row));
            }
        }
        return _jsx(Box, { flexDirection: "column", children: gridRows });
    };
    const renderContent = () => {
        if (isNarrow) {
            return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { bold: true, color: SemanticColors.text.primary, children: "Select Model" }), _jsxs(Box, { marginY: 1, children: [_jsxs(Text, { color: SemanticColors.text.primary, children: ["search: ", _jsx(Text, { color: SemanticColors.text.accent, children: "\u258C" })] }), _jsx(Text, { color: SemanticColors.text.primary, children: searchTerm })] }), _jsx(Text, { color: SemanticColors.text.secondary, children: "Tab to switch modes, Enter to select, Esc to cancel" }), _jsxs(Text, { color: SemanticColors.text.secondary, children: [filteredModels.length, " models", searchTerm && ` found`] }), filteredModels.length > 0 ? (renderModelGrid()) : (_jsx(Box, { marginY: 1, children: _jsxs(Text, { color: SemanticColors.text.secondary, children: ["No models match \"", searchTerm, "\""] }) }))] }));
        }
        return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { bold: true, color: SemanticColors.text.primary, children: isSearching
                        ? 'Search Models'
                        : 'Select Model (Tab to switch modes, Enter to select, Esc to cancel)' }), _jsxs(Box, { marginY: 1, children: [_jsxs(Text, { color: isSearching
                                ? SemanticColors.text.primary
                                : SemanticColors.text.secondary, children: ["search:", ' ', isSearching && _jsx(Text, { color: SemanticColors.text.accent, children: "\u258C" })] }), _jsx(Text, { color: SemanticColors.text.primary, children: searchTerm })] }), _jsxs(Text, { color: SemanticColors.text.secondary, children: ["Found ", filteredModels.length, " of ", sortedModels.length, " models"] }), isWide && rows > maxVisibleRows && (_jsxs(Text, { color: SemanticColors.text.secondary, children: ["Showing ", scrollOffset + 1, "-", Math.min(scrollOffset + maxVisibleRows, rows), " of ", rows, " rows"] })), filteredModels.length > 0 ? (renderModelGrid()) : (_jsx(Box, { marginY: 1, children: _jsxs(Text, { color: SemanticColors.text.secondary, children: ["No models match \"", searchTerm, "\""] }) })), filteredModels.length > 0 && !isSearching && (_jsxs(Text, { color: SemanticColors.text.secondary, children: ["Selected: ", filteredModels[index].id] })), _jsx(Text, { color: SemanticColors.text.secondary, children: "Tab to switch modes" })] }));
    };
    return isNarrow ? (_jsx(Box, { flexDirection: "column", padding: 1, children: renderContent() })) : (_jsx(Box, { borderStyle: "round", borderColor: SemanticColors.border.default, flexDirection: "column", padding: 1, width: maxDialogWidth, children: renderContent() }));
};
//# sourceMappingURL=ProviderModelDialog.js.map