import { jsxs as _jsxs, jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
/**
 * InkPicker — terminal port of the design's `oc-picker` overlay.
 *
 * Three grid variants mirror the design's three picker layouts:
 *
 *   slash:  16 + label + 1fr + auto    →  ▸ {cmd}    {desc}             {shortcut}
 *   at:     14 + 1fr + auto            →  ▸ {dir/}{file}                {tag pill}
 *   model:  16 + label + 1fr + auto    →  ▸ {label}  {meta: ctx · cost} {tag pill}
 *
 * Selected row gets a left ▎ accent bar + bg accent-soft + cmd swapped
 * from accent to shimmer (matches `.oc-picker-item.is-sel` rules).
 */
import { useEffect, useMemo, useState } from 'react';
import { Box, Text, useInput } from '../ink.js';
import { themeToInkHex } from './ink-theme.js';
import { fuzzyMatch } from './tui/picker.js';
import { stripAnsi } from './tui/colors.js';
import { padRight, truncate } from './tui/text.js';
export function InkPicker({ title, items, variant = 'generic', placeholder = 'Type to search…', initialQuery = '', queryPrefix = '', submitLabel = 'select', visibleCount = 10, onSelect, onCancel, }) {
    const terminalRows = process.stdout.rows || 24;
    const maxVisible = Math.max(3, Math.min(visibleCount, terminalRows - 10));
    const [query, setQuery] = useState(initialQuery);
    const [focusIndex, setFocusIndex] = useState(0);
    const [scrollOffset, setScrollOffset] = useState(0);
    useEffect(() => {
        setQuery(initialQuery);
        setFocusIndex(0);
        setScrollOffset(0);
    }, [initialQuery]);
    const filtered = useMemo(() => {
        if (!query.trim())
            return items;
        const haystackOf = (item) => {
            const parts = [stripAnsi(item.label)];
            if (item.description)
                parts.push(item.description);
            if (item.meta)
                parts.push(item.meta);
            if (item.tag)
                parts.push(item.tag);
            if (item.shortcut)
                parts.push(item.shortcut);
            return parts.join(' ');
        };
        return items
            .map((item) => ({ item, score: fuzzyMatch(query, haystackOf(item)) }))
            .filter((entry) => entry.score >= 0)
            .sort((left, right) => left.score - right.score)
            .map((entry) => entry.item);
    }, [items, query]);
    useEffect(() => {
        const bounded = Math.max(0, Math.min(focusIndex, Math.max(0, filtered.length - 1)));
        if (bounded !== focusIndex) {
            setFocusIndex(bounded);
        }
        if (bounded < scrollOffset) {
            setScrollOffset(bounded);
        }
        else if (bounded >= scrollOffset + maxVisible) {
            setScrollOffset(Math.max(0, bounded - maxVisible + 1));
        }
    }, [filtered.length, focusIndex, maxVisible, scrollOffset]);
    useInput((input, key) => {
        if (input === '\u0003') {
            onCancel();
            return;
        }
        if (key.escape) {
            onCancel();
            return;
        }
        if (key.return) {
            const selected = filtered[focusIndex];
            if (selected)
                onSelect(selected);
            return;
        }
        if (key.upArrow) {
            const next = Math.max(0, focusIndex - 1);
            setFocusIndex(next);
            if (next < scrollOffset)
                setScrollOffset(next);
            return;
        }
        if (key.downArrow) {
            const next = Math.min(Math.max(0, filtered.length - 1), focusIndex + 1);
            setFocusIndex(next);
            if (next >= scrollOffset + maxVisible) {
                setScrollOffset(Math.max(0, next - maxVisible + 1));
            }
            return;
        }
        if (key.backspace || key.delete) {
            setQuery((current) => current.slice(0, -1));
            setFocusIndex(0);
            setScrollOffset(0);
            return;
        }
        if (key.ctrl || key.meta || key.tab || !input) {
            return;
        }
        setQuery((current) => current + input);
        setFocusIndex(0);
        setScrollOffset(0);
    });
    const accent = themeToInkHex('owl');
    const shimmer = themeToInkHex('shimmer');
    const text = themeToInkHex('text');
    const textHi = themeToInkHex('textHi');
    const textDim = themeToInkHex('textDim');
    const textMute = themeToInkHex('textMute');
    const textSubtle = themeToInkHex('textSubtle');
    const accentSoftBg = themeToInkHex('accentSoft');
    const hairFaint = themeToInkHex('hairFaint');
    const visibleItems = filtered.slice(scrollOffset, scrollOffset + maxVisible);
    const displayedQuery = query ? `${queryPrefix}${query}` : (queryPrefix || placeholder);
    const matchSummary = query.trim().length > 0
        ? `${filtered.length}/${items.length} matches`
        : `${items.length} items`;
    return (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Box, { flexDirection: "row", justifyContent: "space-between", children: [_jsxs(Text, { color: textMute, bold: true, children: [title.toUpperCase(), _jsxs(Text, { color: textDim, children: ['  ', matchSummary] })] }), _jsxs(Text, { color: textDim, children: ["\u2191/\u2193 move \u00B7 \u21B5 ", submitLabel, " \u00B7 esc close"] })] }), _jsxs(Box, { flexDirection: "row", children: [_jsx(Text, { color: accent, children: "\u203A " }), _jsx(Text, { color: query || queryPrefix ? text : textMute, children: displayedQuery })] }), _jsx(Box, { flexDirection: "column", marginTop: 1, children: visibleItems.length > 0 ? visibleItems.map((item, index) => {
                    const absoluteIndex = scrollOffset + index;
                    const focused = absoluteIndex === focusIndex;
                    return (_jsx(PickerRow, { item: item, focused: focused, variant: variant, colors: { accent, shimmer, text, textHi, textDim, textMute, textSubtle, accentSoftBg, hairFaint } }, `${absoluteIndex}:${stripAnsi(item.label)}`));
                }) : (_jsx(Text, { color: textMute, children: "No matches" })) })] }));
}
function PickerRow({ item, focused, variant, colors }) {
    const terminalColumns = process.stdout.columns || 80;
    // Reserve cells per variant. Numbers track design grid templates:
    //   slash:  16 (▸+gutter) + 24 (cmd) + 1fr + 14 (shortcut)
    //   at:     14 (▸) + 1fr  + 8 (tag)
    //   model:  16 (▸) + 28 (label) + 1fr + 12 (tag)
    const labelCol = variant === 'model'
        ? Math.max(16, Math.min(32, Math.floor(terminalColumns * 0.30)))
        : variant === 'slash'
            ? Math.max(14, Math.min(28, Math.floor(terminalColumns * 0.22)))
            : 0; // at + generic let the path/label flex
    const tagCol = (variant === 'at' || variant === 'model') ? 12 : 0;
    const shortcutCol = variant === 'slash' ? 14 : 0;
    const reserved = 2 /* ▸ + space */ + labelCol + tagCol + shortcutCol + 4; /* gaps */
    const flexCol = Math.max(8, terminalColumns - reserved);
    // ComposerPanel already paints a ▎ on every row as its left border, so
    // the picker only renders ▸ for selection — avoids the ▎ ▎▸ double-bar
    // look reported in visual QA.
    const arrow = focused
        ? _jsx(Text, { color: colors.accent, children: '▸ ' })
        : _jsx(Text, { color: colors.textSubtle, children: '  ' });
    // Per-variant cell content.
    let cells;
    if (variant === 'slash') {
        const cmdColor = focused ? colors.shimmer : colors.accent;
        const descColor = focused ? colors.textHi : colors.textMute;
        const cmdCell = padRight(truncate(stripAnsi(item.label), labelCol), labelCol);
        const desc = item.description ?? '';
        const descCell = padRight(truncate(desc, flexCol), flexCol);
        const shortcut = item.shortcut ?? '';
        cells = (_jsxs(_Fragment, { children: [_jsx(Text, { color: cmdColor, bold: focused, children: cmdCell }), _jsxs(Text, { color: descColor, children: [" ", descCell] }), shortcut ? _jsxs(Text, { color: colors.textSubtle, children: [" ", shortcut] }) : null] }));
    }
    else if (variant === 'at') {
        // Path: split into directory portion (dim) and basename (ink).
        const path = stripAnsi(item.label);
        const slashIdx = path.lastIndexOf('/');
        const dir = slashIdx >= 0 ? path.slice(0, slashIdx + 1) : '';
        const base = slashIdx >= 0 ? path.slice(slashIdx + 1) : path;
        const tag = item.tag ?? item.description ?? '';
        cells = (_jsxs(_Fragment, { children: [dir ? _jsx(Text, { color: colors.textMute, children: dir }) : null, _jsx(Text, { color: focused ? colors.textHi : colors.text, children: base || ' ' }), _jsx(Box, { flexGrow: 1, children: _jsx(Text, { children: " " }) }), tag ? (_jsx(Box, { paddingX: 1, children: _jsx(Text, { color: focused ? colors.accent : colors.textMute, children: tag.toUpperCase() }) })) : null] }));
    }
    else if (variant === 'model') {
        const labelColor = focused ? colors.shimmer : colors.accent;
        const labelCell = padRight(truncate(stripAnsi(item.label), labelCol), labelCol);
        const meta = item.meta ?? item.description ?? '';
        const metaCell = padRight(truncate(meta, flexCol), flexCol);
        const tag = item.tag ?? '';
        cells = (_jsxs(_Fragment, { children: [_jsx(Text, { color: labelColor, bold: focused, children: labelCell }), _jsxs(Text, { color: focused ? colors.textHi : colors.textMute, children: [" ", metaCell] }), tag ? (_jsx(Box, { children: _jsx(Text, { color: focused ? colors.accent : colors.textSubtle, children: tag.toUpperCase() }) })) : null] }));
    }
    else {
        // generic / theme — single label + optional dim description.
        cells = (_jsxs(_Fragment, { children: [_jsx(Text, { color: focused ? colors.textHi : colors.text, bold: focused, children: stripAnsi(item.label) }), item.description ? _jsxs(Text, { color: colors.textMute, children: [" ", item.description] }) : null] }));
    }
    return (_jsxs(Box, { flexDirection: "row", backgroundColor: focused ? colors.accentSoftBg : undefined, children: [arrow, cells] }));
}
//# sourceMappingURL=ink-picker.js.map