import { app } from "../../scripts/app.js";
import {
    PROMPT_TAG_AUTOCOMPLETE_SETTING_ID,
    getPromptTagAutocompletePreference,
    setLoraManagerSettingValue,
} from "./settings.js";
import { showToast } from "./utils.js";

/**
 * Extension for PromptLM node to support dynamic trigger_words inputs.
 * Based on the dynamic input pattern from Impact Pack's Switch (Any) node.
 */
app.registerExtension({
    name: "Comfy.LoraManager.PromptLM",

    async beforeRegisterNodeDef(nodeType, nodeData, app) {
        if (nodeData.name !== "Prompt (LoraManager)") {
            return;
        }

        const onConnectionsChange = nodeType.prototype.onConnectionsChange;
        
        nodeType.prototype.onConnectionsChange = function(type, index, connected, link_info) {
            const stackTrace = new Error().stack;
            
            // Skip during graph loading/pasting to avoid interference
            if (stackTrace.includes('loadGraphData') || stackTrace.includes('pasteFromClipboard')) {
                return onConnectionsChange?.apply?.(this, arguments);
            }
            
            // Skip subgraph operations
            if (stackTrace.includes('convertToSubgraph') || stackTrace.includes('Subgraph.configure')) {
                return onConnectionsChange?.apply?.(this, arguments);
            }
            
            if (!link_info) {
                return onConnectionsChange?.apply?.(this, arguments);
            }

            // Handle input connections (type === 1)
            if (type === 1) {
                const input = this.inputs[index];
                
                // Only process trigger_words inputs
                if (!input || !input.name.startsWith('trigger_words')) {
                    return onConnectionsChange?.apply?.(this, arguments);
                }

                // Count existing trigger_words inputs
                let triggerWordCount = 0;
                for (const inp of this.inputs) {
                    if (inp.name.startsWith('trigger_words')) {
                        triggerWordCount++;
                    }
                }

                // Renumber all trigger_words inputs sequentially
                let slotIndex = 1;
                for (const inp of this.inputs) {
                    if (inp.name.startsWith('trigger_words')) {
                        inp.name = `trigger_words${slotIndex}`;
                        slotIndex++;
                    }
                }

                // Add new input slot if connected and this was the last one
                if (connected) {
                    const lastTriggerIndex = triggerWordCount;
                    if (index === lastTriggerIndex || index === this.inputs.findIndex(i => i.name === `trigger_words${lastTriggerIndex}`)) {
                        this.addInput(`trigger_words${slotIndex}`, "STRING", { 
                            forceInput: true,
                            tooltip: "Trigger words to prepend. Connect to add more inputs."
                        });
                    }
                }

                // Remove disconnected empty input slots (but keep at least one)
                if (!connected && triggerWordCount > 1) {
                    // Check if this input is now empty and can be removed
                    const disconnectedInput = this.inputs[index];
                    if (disconnectedInput && disconnectedInput.name.startsWith('trigger_words')) {
                        // Only remove if it has no link and is not the last trigger_words input
                        const isLastTriggerSlot = index === this.inputs.findLastIndex(i => i.name.startsWith('trigger_words'));
                        if (!isLastTriggerSlot && !disconnectedInput.link) {
                            this.removeInput(index);
                            
                            // Renumber again after removal
                            let newSlotIndex = 1;
                            for (const inp of this.inputs) {
                                if (inp.name.startsWith('trigger_words')) {
                                    inp.name = `trigger_words${newSlotIndex}`;
                                    newSlotIndex++;
                                }
                            }
                        }
                    }
                }
            }

            return onConnectionsChange?.apply?.(this, arguments);
        };

        // Expose the tag autocomplete toggle in the node's right-click menu so
        // users can discover the switch where the behavior actually happens,
        // instead of only via slash commands or the global settings dialog.
        const getExtraMenuOptions = nodeType.prototype.getExtraMenuOptions;
        nodeType.prototype.getExtraMenuOptions = function(_, options) {
            getExtraMenuOptions?.apply?.(this, arguments);

            options.push(null);

            const autocompleteEnabled = getPromptTagAutocompletePreference();
            options.push({
                content: autocompleteEnabled
                    ? "Tag Autocomplete: ON (/noautocomplete to disable)"
                    : "Tag Autocomplete: OFF (/autocomplete to enable)",
                callback: async () => {
                    const newValue = !autocompleteEnabled;
                    try {
                        const success = await setLoraManagerSettingValue(PROMPT_TAG_AUTOCOMPLETE_SETTING_ID, newValue);
                        if (!success) {
                            throw new Error("settings API unavailable");
                        }
                        showToast({
                            severity: newValue ? 'success' : 'secondary',
                            summary: newValue ? 'Autocomplete Enabled' : 'Autocomplete Disabled',
                            detail: newValue
                                ? 'Tag autocomplete is now ON. Type to see suggestions.'
                                : 'Tag autocomplete is now OFF. Type /autocomplete in the prompt field to re-enable.',
                            life: 3000
                        });
                    } catch (error) {
                        console.error('[Lora Manager] Failed to toggle setting:', error);
                        showToast({
                            severity: 'error',
                            summary: 'Error',
                            detail: 'Failed to toggle autocomplete setting',
                            life: 3000
                        });
                    }
                }
            });
        };
    },

    nodeCreated(node, app) {
        if (node.comfyClass !== "Prompt (LoraManager)") {
            return;
        }

        // Ensure at least one trigger_words input exists on creation
        const hasTriggerWords = node.inputs.some(inp => inp.name.startsWith('trigger_words'));
        if (!hasTriggerWords) {
            node.addInput("trigger_words1", "STRING", { 
                forceInput: true,
                tooltip: "Trigger words to prepend. Connect to add more inputs."
            });
        }
    }
});
