import { r as registerInstance, c as createEvent, h } from './index-BIwHMk6j.js';

/**
 * Process a single property value and add to items array
 * @param items Array to add items to
 * @param fullPath Full property path
 * @param value Property value to process
 */
function processPropertyValue(items, fullPath, value) {
    if (value === null) {
        items.push({ path: fullPath });
        return;
    }
    // Cast to record for checking
    const valueObj = value;
    const keys = Object.keys(valueObj);
    const hasAlias = '_alias' in valueObj;
    const hasDescription = '#description' in valueObj;
    const otherKeys = keys.filter((k) => k !== '_alias' && k !== '#description');
    // If it's {} or only has metadata (_alias, #description), treat as simple property
    if (otherKeys.length === 0) {
        const aliasValue = valueObj._alias;
        const descriptionValue = valueObj['#description'];
        if (aliasValue || descriptionValue) {
            items.push({
                path: fullPath,
                alias: aliasValue,
                description: descriptionValue,
            });
        }
        else {
            items.push({ path: fullPath });
        }
        return;
    }
    // If has metadata + other properties, we need to handle both
    // Add the nested properties (metadata is preserved in conversion back)
    if (hasAlias || hasDescription) {
        // Build a PropertySelection without the metadata for recursion
        const nestedSelection = {};
        for (const key of otherKeys) {
            nestedSelection[key] = valueObj[key];
        }
        items.push(...propertySelectionToItems(nestedSelection, fullPath));
        return;
    }
    // Nested property selection without metadata
    items.push(...propertySelectionToItems(value, fullPath));
}
/**
 * Convert a nested PropertySelection to a flat list of property items
 * @param selection The nested PropertySelection object
 * @param prefix Current path prefix (used for recursion)
 * @returns Flat array of PropertySelectionItem objects
 */
function propertySelectionToItems(selection, prefix = '') {
    if (!selection) {
        return [];
    }
    const items = [];
    for (const [key, value] of Object.entries(selection)) {
        const fullPath = prefix ? `${prefix}.${key}` : key;
        if (typeof value === 'object') {
            // NOTE: We want to send null values to the processPropertyValue
            // function but we don't need a special check for null, since
            // `typeof null === 'object'`
            processPropertyValue(items, fullPath, value);
        }
    }
    return items;
}
/**
 * Set the final property value (with or without alias/description)
 * @param current Current PropertySelection object
 * @param part Property name/key
 * @param item Property selection item with path and optional alias/description
 */
function setPropertyValue(current, part, item) {
    // Check if there's already a nested PropertySelection with properties
    const existing = current[part];
    if (existing &&
        typeof existing === 'object' &&
        !('_alias' in existing) &&
        !('#description' in existing)) {
        // There's already a nested PropertySelection object with properties
        // Don't overwrite it - preserve the nested selections
        return;
    }
    // Build metadata object, stripping empty values
    const metadata = {};
    if (item.alias && item.alias.trim() !== '') {
        metadata._alias = item.alias;
    }
    if (item.description && item.description.trim() !== '') {
        metadata['#description'] = item.description;
    }
    // If we have metadata, use it; otherwise use null
    if (Object.keys(metadata).length > 0) {
        current[part] = metadata;
    }
    else {
        current[part] = null;
    }
}
/**
 * Ensure a nested object exists and return it
 * Preserves any existing _alias and #description when converting to nested object
 * @param current Current PropertySelection object
 * @param part Property name/key
 * @returns The nested PropertySelection object
 */
function ensureNestedObject(current, part) {
    const existing = current[part];
    // If doesn't exist or is null, create empty object
    if (!existing) {
        current[part] = {};
        return current[part];
    }
    // If it's already a PropertySelection object, check for metadata
    if (typeof existing === 'object') {
        const existingObj = existing;
        // If it has metadata but no other properties, preserve the metadata
        const keys = Object.keys(existingObj);
        const hasMetadata = '_alias' in existingObj || '#description' in existingObj;
        const otherKeys = keys.filter((k) => k !== '_alias' && k !== '#description');
        if (hasMetadata && otherKeys.length === 0) {
            // Convert { _alias: "...", "#description": "..." } to { _alias: "...", "#description": "...", ...nested }
            // Keep the existing object and return it (caller will add nested props)
            return existingObj;
        }
        // Already has nested properties, return as is
        return existingObj;
    }
    // Shouldn't reach here, but fallback to creating new object
    current[part] = {};
    return current[part];
}
/**
 * Convert a flat list of property items to a nested PropertySelection structure
 * @param items Array of PropertySelectionItem objects
 * @returns Nested PropertySelection object
 */
function itemsToPropertySelection(items) {
    const result = {};
    for (const item of items) {
        const parts = item.path.split('.');
        let current = result;
        for (let i = 0; i < parts.length; i++) {
            const part = parts[i];
            const isLast = i === parts.length - 1;
            if (isLast) {
                setPropertyValue(current, part, item);
            }
            else {
                current = ensureNestedObject(current, part);
            }
        }
    }
    return result;
}

const responseFormatEditorCss = () => `:host(limebb-lime-query-response-format-editor){display:block;width:100%}.response-format-editor{display:flex;flex-direction:column;padding:1rem 0}limel-badge[slot=actions]{--badge-background-color:rgb(var(--contrast-200));margin-right:0.25rem}.property-list{display:flex;flex-direction:column;border-radius:0 0 0.75rem 0.75rem;padding:0.25rem;background-color:rgb(var(--contrast-300))}.empty-state{padding:2rem;text-align:center;color:rgb(var(--contrast-700));font-style:italic}.empty-state p{margin:0}.empty-state .empty-state-message{margin-bottom:1rem;font-size:0.875rem}.empty-state limel-button{margin:0 auto;max-width:200px}`;

const ResponseFormatEditor = class {
    constructor(hostRef) {
        registerInstance(this, hostRef);
        this.change = createEvent(this, "change");
        /**
         * Optional label
         */
        this.label = 'Properties';
        this.items = [];
        this.handleItemChange = (index) => (event) => {
            event.stopPropagation();
            const newItems = [...this.items];
            if (event.detail === null) {
                // Remove item
                newItems.splice(index, 1);
            }
            else {
                // Update item
                newItems[index] = event.detail;
            }
            // Allow empty items - users can remove all properties
            this.items = newItems;
            this.emitChange();
        };
        this.handleAddProperty = () => {
            this.items = [...this.items, { path: '' }];
            this.emitChange();
        };
    }
    componentWillLoad() {
        if (!this.value) {
            // No value provided at all, use default _id
            this.items = [{ path: '_id' }];
            return;
        }
        if (this.isEmptyResponseFormat(this.value)) {
            // Show empty state for explicit empty objects
            this.items = [];
        }
        else if (this.value.object) {
            // Has object property with actual properties
            this.items = propertySelectionToItems(this.value.object);
        }
        else {
            // If value has aggregates but no object property, initialize items to empty array
            this.items = [];
        }
    }
    componentWillUpdate() {
        if (!this.value) {
            return;
        }
        if (this.value.object && !this.isEmptyResponseFormat(this.value)) {
            const currentItems = propertySelectionToItems(this.value.object);
            // Check if items have changed
            const itemsChanged = currentItems.length !== this.items.length ||
                !currentItems.every((item, index) => {
                    const current = this.items[index];
                    return (current &&
                        item.path === current.path &&
                        item.alias === current.alias &&
                        item.description === current.description);
                });
            if (itemsChanged) {
                this.items = currentItems;
            }
        }
        else {
            // Either empty response format or no object property - clear items
            if (this.items.length > 0) {
                this.items = [];
            }
        }
    }
    render() {
        if (!this.limetype) {
            return (h("div", { class: "empty-state" }, h("p", null, "Select a limetype to choose properties")));
        }
        // Render empty state when no properties are selected
        if (this.items.length === 0) {
            return (h("div", { class: "response-format-editor" }, h("h4", { class: "header" }, this.label), h("div", { class: "empty-state" }, h("p", { class: "empty-state-message" }, "No properties selected. The response will return empty objects."), h("limel-button", { label: "Add Property", icon: "plus_math", onClick: this.handleAddProperty }))));
        }
        return (h("div", { class: "response-format-editor" }, h("limel-header", { subheading: this.label }, this.renderPropertyCount()), h("div", { class: "property-list" }, this.items.map((item, index) => this.renderItem(item, index)), h("limel-button", { label: "Property", disabled: this.items.some((item) => !item.path || item.path.trim() === ''), icon: {
                name: 'plus_math',
                title: 'Add',
            }, onClick: this.handleAddProperty }))));
    }
    renderPropertyCount() {
        return [
            h("limel-badge", { slot: "actions", id: "counter-badge", label: this.items.length.toString() }),
            h("limel-tooltip", { elementId: "counter-badge", slot: "actions", label: "Number of selected properties" }),
        ];
    }
    renderItem(item, index) {
        return (h("limebb-lime-query-response-format-item", { key: `${item.path}-${index}`, class: "property-item", platform: this.platform, context: this.context, limetype: this.limetype, item: item, onItemChange: this.handleItemChange(index) }));
    }
    emitChange() {
        const propertySelection = itemsToPropertySelection(this.items);
        const responseFormat = {
            object: propertySelection,
        };
        this.change.emit(responseFormat);
    }
    /**
     * Check if the response format is empty
     *
     * A response format is considered empty in the following cases:
     * - Empty object: `{}`
     * - Object with empty object property and no aggregates: `{ object: {} }`
     *
     * Returns false for:
     * - `null` or `undefined`
     * - Objects with properties: `{ object: { _id: null } }`
     * - Objects with aggregates: `{ aggregates: {...} }`
     *
     * @param value - The ResponseFormat to check
     * @returns True if the response format is empty, false otherwise
     */
    isEmptyResponseFormat(value) {
        if (!value) {
            return false;
        }
        if (Object.keys(value).length === 0) {
            return true;
        }
        return !!(value.object &&
            Object.keys(value.object).length === 0 &&
            !value.aggregates);
    }
};
ResponseFormatEditor.style = responseFormatEditorCss();

const responseFormatItemCss = () => `@charset "UTF-8";*{box-sizing:border-box;min-width:0}:host(limebb-lime-query-response-format-item){display:flex;flex-direction:column;gap:0.5rem}.property-controls{transition:box-shadow 0.4s ease, background-color 0.6s ease;display:flex;align-items:flex-start;gap:0.5rem;width:100%;padding:0.75rem 0.75rem 0 0.75rem;border-radius:0.75rem}.property-controls:hover,.property-controls:focus,.property-controls:focus-within{transition-duration:0.2s;background-color:rgb(var(--contrast-100));box-shadow:var(--shadow-inflated-16)}.property-controls limel-icon-button{margin-top:0.125rem}.property-path{flex-grow:1;display:flex;flex-direction:column;padding-bottom:0.25rem}.button-group,.input-group{padding-left:1rem}.button-group:not(:empty),.input-group:not(:empty){padding-top:0.25rem;padding-bottom:0.25rem}.button-group{display:flex;gap:0.5rem;align-items:center}.button-group button{appearance:none;background:none;border:none;padding:0;margin:0;font:inherit;color:inherit;text-align:inherit;transition:color var(--limel-clickable-transition-speed, 0.4s) ease, background-color var(--limel-clickable-transition-speed, 0.4s) ease, box-shadow var(--limel-clickable-transform-speed, 0.4s) ease, transform var(--limel-clickable-transform-speed, 0.4s) var(--limel-clickable-transform-timing-function, ease);cursor:pointer;color:var(--limel-theme-on-surface-color);background-color:transparent;font-size:0.625rem;padding:0 0.5rem 0 0.25rem;display:flex;align-items:center;gap:0.25rem;border-radius:0.25rem}.button-group button:hover,.button-group button:focus,.button-group button:focus-visible{will-change:color, background-color, box-shadow, transform}.button-group button:hover,.button-group button:focus-visible{transform:translate3d(0, 0.01rem, 0);color:var(--limel-theme-on-surface-color);background-color:var(--lime-elevated-surface-background-color)}.button-group button:hover{box-shadow:var(--button-shadow-hovered)}.button-group button:active{--limel-clickable-transform-timing-function:cubic-bezier(       0.83,       -0.15,       0.49,       1.16   );transform:translate3d(0, 0.05rem, 0);box-shadow:var(--button-shadow-pressed)}.button-group button:hover,.button-group button:active{--limel-clickable-transition-speed:0.2s;--limel-clickable-transform-speed:0.16s}.button-group button:focus{outline:none}.button-group button:focus-visible{outline:none;box-shadow:var(--shadow-depth-8-focused)}.button-group button:hover{transform:scale(1.2)}.button-group limel-icon{width:1rem}.input-group{display:flex;align-items:center}.input-group limel-input-field{flex-grow:1}.input-group limel-icon-button{transform:scale(0.85)}.metadata{flex-grow:1;padding-left:1rem}@media (max-width: 768px){.property-controls{flex-direction:column;gap:0.5rem}}.input-grid{--limebb-l-q-r-f-i--opacity-transition-speed:0.1s;--limebb-l-q-r-f-i--opacity-transition-delay:0s;--limebb-l-q-r-f-i--grid-template-rows-transition-speed:0.3s;transition:grid-template-rows var(--limebb-l-q-r-f-i--grid-template-rows-transition-speed) ease;display:grid;grid-template-rows:0fr}.input-grid .input-group{transition:opacity var(--limebb-l-q-r-f-i--opacity-transition-speed) ease var(--limebb-l-q-r-f-i--opacity-transition-delay), padding var(--limebb-l-q-r-f-i--opacity-transition-speed) ease var(--limebb-l-q-r-f-i--opacity-transition-delay);overflow:hidden;opacity:0}.input-grid:not(:empty){--limebb-l-q-r-f-i--opacity-transition-speed:0.2s;--limebb-l-q-r-f-i--opacity-transition-delay:0.1s;--limebb-l-q-r-f-i--grid-template-rows-transition-speed:0.2s;grid-template-rows:1fr}.input-grid:not(:empty) .input-group{opacity:1}.button-group:hover .input-grid{will-change:grid-template-rows}.button-group:hover .input-group{will-change:opacity, padding}`;

const ResponseFormatItem = class {
    constructor(hostRef) {
        registerInstance(this, hostRef);
        this.itemChange = createEvent(this, "itemChange");
        this.showAliasInput = false;
        this.showDescriptionInput = false;
        this.handlePathChange = (event) => {
            event.stopPropagation();
            this.itemChange.emit(Object.assign(Object.assign({}, this.item), { path: event.detail }));
        };
        this.toggleAliasInput = () => {
            this.showAliasInput = !this.showAliasInput;
        };
        this.toggleDescriptionInput = () => {
            this.showDescriptionInput = !this.showDescriptionInput;
        };
        this.handleAliasChange = (event) => {
            event.stopPropagation();
            const alias = event.detail;
            this.itemChange.emit(Object.assign(Object.assign({}, this.item), { alias: alias || undefined }));
        };
        this.handleDescriptionChange = (event) => {
            event.stopPropagation();
            const description = event.detail;
            this.itemChange.emit(Object.assign(Object.assign({}, this.item), { description: description || undefined }));
        };
        this.handleAliasBlur = () => {
            if (this.item.alias) {
                const trimmed = this.item.alias.trim();
                if (trimmed !== this.item.alias) {
                    this.itemChange.emit(Object.assign(Object.assign({}, this.item), { alias: trimmed || undefined }));
                }
            }
        };
        this.handleDescriptionBlur = () => {
            if (this.item.description) {
                const trimmed = this.item.description.trim();
                if (trimmed !== this.item.description) {
                    this.itemChange.emit(Object.assign(Object.assign({}, this.item), { description: trimmed || undefined }));
                }
            }
        };
        this.handleRemove = () => {
            this.itemChange.emit(null);
        };
    }
    componentWillLoad() {
        // Initialize visibility based on whether fields have values
        this.showAliasInput = !!this.item.alias;
        this.showDescriptionInput = !!this.item.description;
    }
    componentWillUpdate() {
        // Keep inputs visible if they have values
        if (this.item.alias && !this.showAliasInput) {
            this.showAliasInput = true;
        }
        if (this.item.description && !this.showDescriptionInput) {
            this.showDescriptionInput = true;
        }
    }
    render() {
        return [
            h("div", { key: '1fc4a0dbdaa2b362e56a53a82483ca3afe21f6bf', class: "property-controls" }, h("div", { key: '5269250030c559943d4f610734d1ac490a8355ad', class: "property-path" }, h("limebb-property-selector", { key: '2602b66035849922fc413cbc0c82b8163a928ecd', platform: this.platform, context: this.context, limetype: this.limetype, label: "Property", value: this.item.path, required: true, onChange: this.handlePathChange }), h("div", { key: '4974a2c7ff30c527b0328d0fbed3b8bac519fdcd', class: "input-grid" }, this.renderAliasInput()), h("div", { key: 'fb058b3a5d5599c387b852e409bd5ac8e8afbc30', class: "input-grid" }, this.renderDescriptionInput()), h("div", { key: '97a5e7e2ed68fdbac160bdd60498541f3a16371d', class: "button-group" }, this.renderAliasButton(), this.renderDescriptionButton())), h("limel-icon-button", { key: '42ab29e5e8e5fc08e90bc4afe6c6d504e434d33e', icon: "trash", label: "Remove property", onClick: this.handleRemove })),
        ];
    }
    renderAliasButton() {
        if (this.showAliasInput) {
            return;
        }
        return (h("button", { type: "button", class: "alias", onClick: this.toggleAliasInput }, "+ Alias"));
    }
    renderDescriptionButton() {
        if (this.showDescriptionInput) {
            return;
        }
        return (h("button", { type: "button", class: "description", onClick: this.toggleDescriptionInput }, "+ Description"));
    }
    renderAliasInput() {
        if (!this.showAliasInput) {
            return;
        }
        return (h("div", { class: "input-group" }, h("limel-input-field", { label: "Alias", value: this.item.alias || '', placeholder: "Custom property name...", onChange: this.handleAliasChange, onBlur: this.handleAliasBlur, leadingIcon: "add_tag" }), h("limel-icon-button", { class: "remove-alias", icon: "multiply", onClick: this.toggleAliasInput, label: "Remove alias", disabled: !!this.item.alias })));
    }
    renderDescriptionInput() {
        if (!this.showDescriptionInput) {
            return;
        }
        return (h("div", { class: "input-group" }, h("limel-input-field", { label: "Description", value: this.item.description || '', placeholder: "Describe this property for AI...", onChange: this.handleDescriptionChange, onBlur: this.handleDescriptionBlur, leadingIcon: "comments" }), h("limel-icon-button", { class: "remove-description", icon: "multiply", onClick: this.toggleDescriptionInput, label: "Remove description", disabled: !!this.item.description })));
    }
};
ResponseFormatItem.style = responseFormatItemCss();

export { ResponseFormatEditor as limebb_lime_query_response_format_editor, ResponseFormatItem as limebb_lime_query_response_format_item };
