'use client';
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
/**
 * Prompt editor with autocomplete for / commands and @ variables.
 *
 * Features:
 * - Textarea for editing LLM prompts
 * - Dropdown autocomplete for / (slash commands) and @ (variables)
 * - Click-to-insert from commands/variables reference panels
 */
import { useState, useCallback, useRef, useEffect } from 'react';
import { cn } from '../../../utils/cn.js';
import { EditorLabel, EditorHelpText } from '../../shared/editor_theme/index.js';
import { LuTerminal, LuAtSign } from 'react-icons/lu';
export function PromptEditor({ value, on_change, config, disabled = false, className, }) {
    const textarea_ref = useRef(null);
    const [suggestions, set_suggestions] = useState([]);
    const [suggestion_index, set_suggestion_index] = useState(0);
    const [suggestion_range, set_suggestion_range] = useState(null);
    const [show_reference, set_show_reference] = useState(null);
    // Detect / or @ triggers and build suggestions
    const update_suggestions = useCallback((text, cursor) => {
        // Find the word being typed (from last space/newline to cursor)
        const before = text.slice(0, cursor);
        const word_match = before.match(/(?:^|\s|^)(\/\S*)$/m) || before.match(/(?:^|\s|^)(@\S*)$/m);
        if (!word_match) {
            set_suggestions([]);
            set_suggestion_range(null);
            return;
        }
        const word = word_match[1];
        const start = cursor - word.length;
        if (word.startsWith('/')) {
            const query = word.toLowerCase();
            const matches = config.commands
                .filter(c => c.trigger.toLowerCase().startsWith(query))
                .map(c => ({ ...c, kind: 'command' }));
            set_suggestions(matches);
            set_suggestion_range({ start, end: cursor });
            set_suggestion_index(0);
        }
        else if (word.startsWith('@')) {
            const query = word.toLowerCase();
            const matches = config.variables
                .filter(v => v.trigger.toLowerCase().startsWith(query))
                .map(v => ({ ...v, kind: 'variable' }));
            set_suggestions(matches);
            set_suggestion_range({ start, end: cursor });
            set_suggestion_index(0);
        }
        else {
            set_suggestions([]);
            set_suggestion_range(null);
        }
    }, [config]);
    // Insert a suggestion at the trigger position
    const insert_suggestion = useCallback((item) => {
        if (!suggestion_range)
            return;
        const insert_text = item.kind === 'command'
            ? item.template
            : `{{${item.trigger.slice(1)}}}`;
        const new_value = value.slice(0, suggestion_range.start) + insert_text + value.slice(suggestion_range.end);
        on_change(new_value);
        set_suggestions([]);
        set_suggestion_range(null);
        // Focus and set cursor
        requestAnimationFrame(() => {
            if (textarea_ref.current) {
                const new_cursor = suggestion_range.start + insert_text.length;
                textarea_ref.current.focus();
                textarea_ref.current.setSelectionRange(new_cursor, new_cursor);
            }
        });
    }, [suggestion_range, value, on_change]);
    // Insert a reference item at current cursor position
    const insert_at_cursor = useCallback((text) => {
        const textarea = textarea_ref.current;
        if (!textarea)
            return;
        const start = textarea.selectionStart;
        const end = textarea.selectionEnd;
        const new_value = value.slice(0, start) + text + value.slice(end);
        on_change(new_value);
        requestAnimationFrame(() => {
            if (textarea_ref.current) {
                const new_cursor = start + text.length;
                textarea_ref.current.focus();
                textarea_ref.current.setSelectionRange(new_cursor, new_cursor);
            }
        });
    }, [value, on_change]);
    // Handle textarea changes
    const handle_change = useCallback((e) => {
        const new_value = e.target.value;
        on_change(new_value);
        update_suggestions(new_value, e.target.selectionStart);
    }, [on_change, update_suggestions]);
    // Handle keyboard navigation in suggestions
    const handle_keydown = useCallback((e) => {
        if (suggestions.length === 0)
            return;
        if (e.key === 'ArrowDown') {
            e.preventDefault();
            set_suggestion_index(prev => (prev + 1) % suggestions.length);
        }
        else if (e.key === 'ArrowUp') {
            e.preventDefault();
            set_suggestion_index(prev => (prev - 1 + suggestions.length) % suggestions.length);
        }
        else if (e.key === 'Enter' || e.key === 'Tab') {
            e.preventDefault();
            insert_suggestion(suggestions[suggestion_index]);
        }
        else if (e.key === 'Escape') {
            set_suggestions([]);
            set_suggestion_range(null);
        }
    }, [suggestions, suggestion_index, insert_suggestion]);
    // Close suggestions when clicking outside
    useEffect(() => {
        const handle_click = (e) => {
            if (textarea_ref.current && !textarea_ref.current.contains(e.target)) {
                set_suggestions([]);
                set_suggestion_range(null);
            }
        };
        document.addEventListener('mousedown', handle_click);
        return () => document.removeEventListener('mousedown', handle_click);
    }, []);
    return (_jsxs("div", { className: cn('space-y-2', className), children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsx(EditorLabel, { required: true, children: "Prompt" }), _jsxs("div", { className: "flex items-center gap-1", children: [_jsxs("button", { type: "button", onClick: () => set_show_reference(show_reference === 'commands' ? null : 'commands'), className: cn('inline-flex items-center gap-1 px-2 py-1 text-xs rounded-md transition-colors', show_reference === 'commands'
                                    ? 'bg-primary text-primary-foreground'
                                    : 'bg-muted text-muted-foreground hover:text-foreground'), disabled: disabled, children: [_jsx(LuTerminal, { className: "h-3 w-3" }), "Commands"] }), _jsxs("button", { type: "button", onClick: () => set_show_reference(show_reference === 'variables' ? null : 'variables'), className: cn('inline-flex items-center gap-1 px-2 py-1 text-xs rounded-md transition-colors', show_reference === 'variables'
                                    ? 'bg-primary text-primary-foreground'
                                    : 'bg-muted text-muted-foreground hover:text-foreground'), disabled: disabled, children: [_jsx(LuAtSign, { className: "h-3 w-3" }), "Variables"] })] })] }), show_reference && (_jsxs("div", { className: "border rounded-md bg-muted/30 p-3 space-y-1.5", children: [_jsx("div", { className: "text-xs font-medium text-muted-foreground mb-2", children: show_reference === 'commands' ? 'Click to insert command template' : 'Click to insert variable reference' }), show_reference === 'commands' && config.commands.map(cmd => (_jsxs("button", { type: "button", onClick: () => {
                            insert_at_cursor(cmd.template);
                            set_show_reference(null);
                        }, className: "w-full text-left px-2 py-1.5 text-sm rounded hover:bg-background transition-colors", disabled: disabled, children: [_jsx("span", { className: "font-mono text-primary", children: cmd.trigger }), _jsx("span", { className: "text-muted-foreground ml-2", children: cmd.label })] }, cmd.trigger))), show_reference === 'variables' && config.variables.map(v => (_jsxs("button", { type: "button", onClick: () => {
                            insert_at_cursor(`{{${v.trigger.slice(1)}}}`);
                            set_show_reference(null);
                        }, className: "w-full text-left px-2 py-1.5 text-sm rounded hover:bg-background transition-colors", disabled: disabled, children: [_jsx("span", { className: "font-mono text-primary", children: v.trigger }), _jsx("span", { className: "text-muted-foreground ml-2", children: v.description })] }, v.trigger)))] })), _jsxs("div", { className: "relative", children: [_jsx("textarea", { ref: textarea_ref, value: value, onChange: handle_change, onKeyDown: handle_keydown, disabled: disabled, placeholder: "Enter the LLM prompt for document validation. Use / for commands or @ for variables...", rows: 8, className: cn('w-full px-3 py-2 border rounded-md text-sm bg-background resize-y font-mono', 'focus:outline-none focus:ring-2 focus:ring-primary/40 focus:border-primary', 'transition-colors', 'disabled:bg-muted disabled:cursor-not-allowed') }), suggestions.length > 0 && (_jsx("div", { className: "absolute z-50 w-full bottom-full mb-1 border rounded-md bg-popover shadow-lg max-h-48 overflow-y-auto", style: { backgroundColor: 'hsl(var(--popover))' }, children: suggestions.map((item, idx) => (_jsxs("button", { type: "button", onClick: () => insert_suggestion(item), className: cn('w-full text-left px-3 py-2 text-sm flex items-center gap-2 transition-colors', idx === suggestion_index ? 'bg-accent text-accent-foreground' : 'hover:bg-accent/50'), children: [item.kind === 'command'
                                    ? _jsx(LuTerminal, { className: "h-3.5 w-3.5 text-primary flex-shrink-0" })
                                    : _jsx(LuAtSign, { className: "h-3.5 w-3.5 text-primary flex-shrink-0" }), _jsx("span", { className: "font-mono", children: item.trigger }), _jsx("span", { className: "text-muted-foreground ml-1", children: item.label })] }, item.trigger))) }))] }), _jsxs(EditorHelpText, { children: ["Type ", _jsx("code", { className: "text-xs bg-muted px-1 py-0.5 rounded", children: "/" }), " for commands or", ' ', _jsx("code", { className: "text-xs bg-muted px-1 py-0.5 rounded", children: "@" }), " for variables. Variables use ", _jsx("code", { className: "text-xs bg-muted px-1 py-0.5 rounded", children: '{{name}}' }), " syntax."] })] }));
}
//# sourceMappingURL=prompt_editor.js.map