'use client';
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
/**
 * Right panel editor for a single validation rule.
 * Tabs: Rule (main), Clarification, Technical.
 */
import { useState, useCallback, useEffect, useMemo } from 'react';
import { cn } from '../../../utils/cn.js';
import { slugify } from '../../../utils/slugify.js';
import { EditorSection, EditorLabel, EditorInput, EditorSelect, EditorHeader, EditorTabs, SwitchCard, StatusIndicator, EditorHelpText, } from '../../shared/editor_theme/index.js';
import { useValidationRuleEditor } from '../context.js';
import { ClarificationSettings } from './clarification_settings.js';
import { VariableChainInput } from './variable_chain_input.js';
import { HazoUiDialog, HazoUiTextarea } from 'hazo_ui';
import { LuTerminal, LuSave, LuTrash2, LuShieldCheck, LuFileText, LuHash, LuAtSign, LuCalendar, LuLayers, LuRepeat, LuCopy, } from 'react-icons/lu';
const EDITOR_TABS = [
    { id: 'rule', label: 'Rule', icon: 'basic' },
    { id: 'clarification', label: 'Clarification', icon: 'controls' },
    { id: 'technical', label: 'Technical', icon: 'basic' },
];
function create_default_rule(document_type) {
    return {
        rule_id: '',
        name: '',
        description: '',
        document_type: document_type ?? 'general',
        target_field_id: '',
        target_label: '',
        prompt: '',
        clarification_type: 'invalid_document',
        enabled: true,
        priority: 100,
    };
}
function default_coverage() {
    return {
        cadence: 'monthly',
        alignment: 'calendar_aligned',
        period_start: ['@Beginning_Of_Tax_Year'],
        period_end: ['@End_Of_Tax_Year'],
    };
}
export function RuleEditor({ className }) {
    const { rules_data, selected_id, set_selected_id, prompt_config, read_only, available_document_types, available_response_sets, } = useValidationRuleEditor();
    const [active_tab, set_active_tab] = useState('rule');
    const [local_rule, set_local_rule] = useState({});
    const [is_dirty, set_is_dirty] = useState(false);
    const [is_saving, set_is_saving] = useState(false);
    const [rule_id, set_rule_id] = useState('');
    const [id_manually_edited, set_id_manually_edited] = useState(false);
    const [description_auto_filled, set_description_auto_filled] = useState(false);
    const [delete_confirm_open, set_delete_confirm_open] = useState(false);
    const [show_reference, set_show_reference] = useState(null);
    const is_new = selected_id === '__new_rule';
    const existing_rule = useMemo(() => rules_data.rules.find(r => r.id === selected_id), [rules_data.rules, selected_id]);
    const is_global = existing_rule?.origin === 'global';
    // rule_id uniqueness validation
    const id_error = useMemo(() => {
        if (!rule_id)
            return undefined;
        if (!rules_data.is_rule_id_unique(rule_id, is_new ? undefined : selected_id ?? undefined)) {
            return 'This Rule ID is already in use by another rule';
        }
        return undefined;
    }, [rule_id, rules_data, is_new, selected_id]);
    // Build PrefixConfig for HazoUiTextarea
    // Strip leading / or @ from trigger since HazoUiTextarea prepends the prefix char
    const prefix_config = useMemo(() => [
        {
            char: '/',
            commands: prompt_config.commands.map(cmd => ({
                action: cmd.trigger.replace(/^\//, ''),
                action_label: cmd.label,
                action_description: cmd.description,
            })),
        },
        {
            char: '@',
            commands: prompt_config.variables.map(v => ({
                action: v.trigger.replace(/^@/, ''),
                action_label: v.label,
                action_description: v.description,
            })),
        },
    ], [prompt_config]);
    // Load rule data when selection changes
    useEffect(() => {
        if (is_new) {
            const default_type = rules_data.document_types[0] ?? 'general';
            set_local_rule(create_default_rule(default_type));
            set_rule_id('');
            set_id_manually_edited(false);
            set_description_auto_filled(true);
            set_is_dirty(true);
            set_active_tab('rule');
        }
        else if (existing_rule) {
            set_local_rule({ ...existing_rule });
            set_rule_id(existing_rule.rule_id);
            set_id_manually_edited(true);
            set_description_auto_filled(false);
            set_is_dirty(false);
            set_active_tab('rule');
        }
        else {
            set_local_rule({});
            set_rule_id('');
            set_id_manually_edited(false);
            set_description_auto_filled(false);
            set_is_dirty(false);
        }
    }, [selected_id, existing_rule, is_new, rules_data.document_types]);
    const update_field = useCallback((updates) => {
        set_local_rule(prev => ({ ...prev, ...updates }));
        set_is_dirty(true);
        // Auto-generate rule_id from name for new rules when ID hasn't been manually edited
        if (is_new && 'name' in updates && !id_manually_edited) {
            const slug = slugify(updates.name ?? '');
            set_rule_id(slug);
        }
    }, [is_new, id_manually_edited]);
    // Handle name change with description auto-fill
    const handle_name_change = useCallback((name) => {
        update_field({ name });
        if (description_auto_filled) {
            set_local_rule(prev => ({ ...prev, name, description: name }));
        }
    }, [update_field, description_auto_filled]);
    // Handle description change — stops auto-fill
    const handle_description_change = useCallback((description) => {
        update_field({ description });
        set_description_auto_filled(false);
    }, [update_field]);
    // Handle prompt change from HazoUiTextarea
    const handle_prompt_change = useCallback((output) => {
        update_field({ prompt: output.plain_text });
    }, [update_field]);
    const handle_save = useCallback(async () => {
        if (!local_rule.name?.trim())
            return;
        if (id_error)
            return;
        set_is_saving(true);
        try {
            if (is_new) {
                const rule_input = {
                    ...local_rule,
                    rule_id: rule_id || slugify(local_rule.name ?? ''),
                };
                const created = await rules_data.create_rule(rule_input);
                if (created) {
                    set_selected_id(created.id);
                    set_is_dirty(false);
                }
            }
            else if (selected_id) {
                // rule_id change is just a normal update now (UUID id stays stable)
                const updated = await rules_data.update_rule(selected_id, {
                    ...local_rule,
                    rule_id,
                });
                if (updated) {
                    set_is_dirty(false);
                }
            }
        }
        finally {
            set_is_saving(false);
        }
    }, [is_new, selected_id, local_rule, rules_data, set_selected_id, rule_id, id_error]);
    const handle_delete_confirm = useCallback(async () => {
        if (!selected_id || is_new)
            return;
        const success = await rules_data.delete_rule(selected_id);
        if (success) {
            set_selected_id(null);
        }
        set_delete_confirm_open(false);
    }, [selected_id, is_new, rules_data, set_selected_id]);
    const handle_clone_to_override = useCallback(async () => {
        if (!existing_rule)
            return;
        set_is_saving(true);
        try {
            const created = await rules_data.clone_to_override(existing_rule);
            if (created) {
                set_selected_id(created.id);
            }
        }
        finally {
            set_is_saving(false);
        }
    }, [existing_rule, rules_data, set_selected_id]);
    // Empty state
    if (!selected_id) {
        return (_jsxs("div", { className: cn('flex flex-col items-center justify-center h-full text-muted-foreground gap-3', className), children: [_jsx(LuShieldCheck, { className: "h-12 w-12 text-muted-foreground/30" }), _jsx("p", { className: "text-sm", children: "Select a rule to edit" }), _jsx("p", { className: "text-xs", children: "or click Add to create a new one" })] }));
    }
    const disabled = read_only || is_saving || is_global;
    const can_save = is_dirty && !!local_rule.name?.trim() && !!local_rule.document_type?.trim() && !id_error;
    return (_jsxs("div", { className: cn('flex flex-col h-full', className), children: [_jsx(EditorHeader, { children: _jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("div", { className: "flex-1 min-w-0", children: [_jsx("h3", { className: "text-sm font-semibold truncate", children: is_new ? 'New Rule' : local_rule.name || 'Untitled' }), !is_new && local_rule.document_type && (_jsxs("p", { className: "text-xs text-muted-foreground", children: [local_rule.document_type, is_global && _jsxs(_Fragment, { children: [" \u00B7 ", _jsx("span", { className: "text-amber-600 font-medium", children: "Default \u2014 read only" })] })] }))] }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(StatusIndicator, { saved: !is_dirty }), !read_only && (_jsx(_Fragment, { children: is_global ? (_jsxs("button", { type: "button", onClick: handle_clone_to_override, disabled: is_saving || !rules_data.can_clone_to_override, title: rules_data.can_clone_to_override
                                            ? 'Create an editable override of this default rule for the current scope'
                                            : 'on_clone_to_override callback was not provided', className: cn('inline-flex items-center gap-1 px-3 py-1.5 text-xs rounded-md transition-colors', rules_data.can_clone_to_override && !is_saving
                                            ? 'bg-primary text-primary-foreground hover:bg-primary/90'
                                            : 'bg-muted text-muted-foreground cursor-not-allowed'), children: [_jsx(LuCopy, { className: "h-3 w-3" }), is_saving ? 'Overriding...' : 'Override default'] })) : (_jsxs(_Fragment, { children: [_jsxs("button", { type: "button", onClick: handle_save, disabled: !can_save || is_saving, className: cn('inline-flex items-center gap-1 px-3 py-1.5 text-xs rounded-md transition-colors', can_save
                                                    ? 'bg-primary text-primary-foreground hover:bg-primary/90'
                                                    : 'bg-muted text-muted-foreground cursor-not-allowed'), children: [_jsx(LuSave, { className: "h-3 w-3" }), is_saving ? 'Saving...' : 'Save'] }), !is_new && (_jsx("button", { type: "button", onClick: () => set_delete_confirm_open(true), disabled: is_saving, className: "inline-flex items-center gap-1 px-2 py-1.5 text-xs rounded-md text-destructive hover:bg-destructive/10 transition-colors", children: _jsx(LuTrash2, { className: "h-3 w-3" }) }))] })) }))] })] }) }), _jsx(EditorTabs, { tabs: EDITOR_TABS, active_tab: active_tab, on_tab_change: set_active_tab }), _jsxs("div", { className: "flex-1 overflow-y-auto p-4", children: [active_tab === 'rule' && (_jsxs("div", { className: "space-y-0", children: [_jsx(EditorSection, { children: _jsxs("div", { className: "grid grid-cols-2 gap-4", children: [_jsxs("div", { className: "space-y-2", children: [_jsx(EditorLabel, { required: true, children: "Name" }), _jsx(EditorInput, { value: local_rule.name ?? '', onChange: e => handle_name_change(e.target.value), placeholder: "e.g., Check PAYG coverage period", disabled: disabled })] }), _jsxs("div", { className: "space-y-2", children: [_jsx(EditorLabel, { children: "Description" }), _jsx(EditorInput, { value: local_rule.description ?? '', onChange: e => handle_description_change(e.target.value), placeholder: "What does this rule check?", disabled: disabled })] })] }) }), _jsxs(EditorSection, { children: [_jsx(EditorLabel, { icon: LuFileText, required: true, children: "Document Type" }), available_document_types.length > 0 ? (_jsxs(EditorSelect, { value: local_rule.document_type ?? '', onChange: e => update_field({ document_type: e.target.value }), disabled: disabled, children: [_jsx("option", { value: "", children: "Select document type\u2026" }), _jsx("option", { value: "general", children: "All Documents (general)" }), available_document_types.map(dt => (_jsx("option", { value: dt.type_id, children: dt.type_label }, dt.type_id)))] })) : (_jsx(EditorInput, { value: local_rule.document_type ?? '', onChange: e => update_field({ document_type: e.target.value }), placeholder: "e.g., payg_summary", disabled: disabled })), _jsx(EditorHelpText, { children: "Category of document this rule validates." })] }), _jsxs(EditorSection, { children: [_jsx(EditorLabel, { icon: LuShieldCheck, required: true, children: "Validation Type" }), _jsxs(EditorSelect, { value: local_rule.validation_type ?? 'llm_prompt', onChange: e => update_field({ validation_type: e.target.value }), disabled: disabled, children: [_jsx("option", { value: "llm_prompt", children: "LLM Prompt" }), _jsx("option", { value: "periodic_coverage", children: "Periodic Coverage" })] }), _jsx(EditorHelpText, { children: "LLM Prompt rules execute via the LLM. Periodic Coverage rules detect missing files across a period using deterministic gap arithmetic." })] }), (local_rule.validation_type ?? 'llm_prompt') === 'llm_prompt' && (_jsxs(EditorSection, { last: true, children: [_jsxs("div", { className: "flex items-center justify-between mb-2", 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 mb-2", children: [_jsx("div", { className: "text-xs font-medium text-muted-foreground mb-2", children: show_reference === 'commands' ? 'Available commands' : 'Available variables' }), show_reference === 'commands' && prompt_config.commands.map(cmd => (_jsxs("div", { className: "px-2 py-1.5 text-sm rounded", 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' && prompt_config.variables.map(v => (_jsxs("div", { className: "px-2 py-1.5 text-sm rounded", children: [_jsx("span", { className: "font-mono text-primary", children: v.trigger }), _jsx("span", { className: "text-muted-foreground ml-2", children: v.description })] }, v.trigger)))] })), _jsx(HazoUiTextarea, { value: local_rule.prompt ?? '', prefixes: prefix_config, placeholder: "Enter validation prompt. Use / for commands or @ for variables...", on_change: handle_prompt_change, disabled: disabled, rows: 6, min_height: "150px", instance_id: "validation-rule-prompt" }), _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."] })] })), local_rule.validation_type === 'periodic_coverage' && (_jsxs(_Fragment, { children: [_jsxs(EditorSection, { children: [_jsx(EditorLabel, { icon: LuRepeat, required: true, children: "Cadence" }), _jsxs(EditorSelect, { value: local_rule.coverage?.cadence ?? 'monthly', onChange: e => update_field({
                                                    coverage: {
                                                        ...(local_rule.coverage ?? default_coverage()),
                                                        cadence: e.target.value,
                                                    },
                                                }), disabled: disabled, children: [_jsx("option", { value: "quarterly", children: "Quarterly" }), _jsx("option", { value: "monthly", children: "Monthly" }), _jsx("option", { value: "biweekly", children: "Biweekly" }), _jsx("option", { value: "fortnightly", children: "Fortnightly" })] }), _jsx(EditorHelpText, { children: "How often a document is expected within the period." })] }), _jsxs(EditorSection, { children: [_jsx(EditorLabel, { icon: LuLayers, required: true, children: "Alignment" }), _jsxs(EditorSelect, { value: local_rule.coverage?.alignment ?? 'calendar_aligned', onChange: e => update_field({
                                                    coverage: {
                                                        ...(local_rule.coverage ?? default_coverage()),
                                                        alignment: e.target.value,
                                                    },
                                                }), disabled: disabled, children: [_jsx("option", { value: "calendar_aligned", children: "Calendar Aligned" }), _jsx("option", { value: "flexible", children: "Flexible" })] }), _jsx(EditorHelpText, { children: "Calendar Aligned snaps cycles to calendar months/quarters. Flexible tiles cycles from period start (use for biweekly statements with arbitrary anchors)." })] }), _jsxs(EditorSection, { children: [_jsx(EditorLabel, { icon: LuCalendar, required: true, children: "Period Start" }), _jsx(VariableChainInput, { chain: local_rule.coverage?.period_start ?? [], variables: prompt_config.variables, on_change: chain => update_field({
                                                    coverage: {
                                                        ...(local_rule.coverage ?? default_coverage()),
                                                        period_start: chain,
                                                    },
                                                }), disabled: disabled, help: "First non-empty resolved value is used. Add fallbacks if a primary form-field variable might be empty." })] }), _jsxs(EditorSection, { last: true, children: [_jsx(EditorLabel, { icon: LuCalendar, required: true, children: "Period End" }), _jsx(VariableChainInput, { chain: local_rule.coverage?.period_end ?? [], variables: prompt_config.variables, on_change: chain => update_field({
                                                    coverage: {
                                                        ...(local_rule.coverage ?? default_coverage()),
                                                        period_end: chain,
                                                    },
                                                }), disabled: disabled, help: "First non-empty resolved value is used. Rule skips if both Period Start and Period End fail to resolve." })] })] }))] })), active_tab === 'clarification' && (_jsx(ClarificationSettings, { rule: local_rule, on_update: update_field, disabled: disabled, available_response_sets: available_response_sets })), active_tab === 'technical' && (_jsxs("div", { className: "space-y-0", children: [_jsxs(EditorSection, { children: [_jsx(EditorLabel, { icon: LuHash, children: "Rule ID" }), _jsx(EditorInput, { value: rule_id, onChange: e => {
                                            set_rule_id(e.target.value);
                                            set_id_manually_edited(true);
                                            set_is_dirty(true);
                                        }, placeholder: "e.g., check_payg_coverage", disabled: disabled }), id_error && (_jsx("p", { className: "text-xs text-destructive mt-1", children: id_error })), _jsx(EditorHelpText, { children: is_new
                                            ? 'Auto-generated from name. Edit to customize.'
                                            : 'Changing the ID may break form field references.' })] }), _jsxs(EditorSection, { children: [_jsx(EditorLabel, { children: "Priority" }), _jsx(EditorInput, { type: "number", value: local_rule.priority ?? 100, onChange: e => update_field({ priority: parseInt(e.target.value) || 100 }), disabled: disabled, field_width: "md" }), _jsx(EditorHelpText, { children: "Lower values execute first. Default: 100." })] }), _jsxs(EditorSection, { children: [_jsx(EditorLabel, { children: "Check Type" }), _jsxs(EditorSelect, { value: local_rule.check_type ?? '', onChange: e => update_field({ check_type: (e.target.value || undefined) }), disabled: disabled, field_width: "lg", children: [_jsx("option", { value: "", children: "Both (immediate & batch)" }), _jsx("option", { value: "immediate", children: "Immediate only (on upload)" }), _jsx("option", { value: "backoffice", children: "Back Office only (batch review)" })] }), _jsx(EditorHelpText, { children: "Immediate rules run when a file is uploaded (showing clarification popups). Back Office rules only run during batch review after submission. \"Both\" runs in both contexts." })] }), _jsx(EditorSection, { last: true, children: _jsx(SwitchCard, { icon: LuShieldCheck, label: "Enabled", description: "Active rules will be executed when documents are uploaded", children: _jsx("input", { type: "checkbox", checked: local_rule.enabled ?? true, onChange: e => update_field({ enabled: e.target.checked }), disabled: disabled, className: "h-4 w-4 rounded" }) }) })] }))] }), _jsx(HazoUiDialog, { open: delete_confirm_open, onOpenChange: set_delete_confirm_open, title: "Delete Rule", description: `Are you sure you want to delete "${local_rule.name}"? This action cannot be undone.`, variant: "destructive", actionButtonText: "Delete", cancelButtonText: "Cancel", onConfirm: handle_delete_confirm, onCancel: () => set_delete_confirm_open(false), children: null })] }));
}
//# sourceMappingURL=rule_editor.js.map