import { app } from "../../scripts/app.js";

// ============================================================================
// Setting IDs and Defaults
// ============================================================================

const TRIGGER_WORD_WHEEL_SENSITIVITY_ID = "loramanager.trigger_word_wheel_sensitivity";
const TRIGGER_WORD_WHEEL_SENSITIVITY_DEFAULT = 0.02;

const AUTO_PATH_CORRECTION_SETTING_ID = "loramanager.auto_path_correction";
const AUTO_PATH_CORRECTION_DEFAULT = true;

const PROMPT_TAG_AUTOCOMPLETE_SETTING_ID = "loramanager.prompt_tag_autocomplete";
const PROMPT_TAG_AUTOCOMPLETE_DEFAULT = true;

const AUTOCOMPLETE_APPEND_COMMA_SETTING_ID = "loramanager.autocomplete_append_comma";
const AUTOCOMPLETE_APPEND_COMMA_DEFAULT = true;

const AUTOCOMPLETE_AUTO_FORMAT_SETTING_ID = "loramanager.autocomplete_auto_format";
const AUTOCOMPLETE_AUTO_FORMAT_DEFAULT = true;

const AUTOCOMPLETE_ACCEPT_KEY_SETTING_ID = "loramanager.autocomplete_accept_key";
const AUTOCOMPLETE_ACCEPT_KEY_DEFAULT = "both";
const AUTOCOMPLETE_ACCEPT_KEY_OPTION_BOTH = "Tab or Enter";
const AUTOCOMPLETE_ACCEPT_KEY_OPTION_TAB_ONLY = "Tab only";
const AUTOCOMPLETE_ACCEPT_KEY_OPTION_ENTER_ONLY = "Enter only";

const TAG_SPACE_REPLACEMENT_SETTING_ID = "loramanager.tag_space_replacement";
const TAG_SPACE_REPLACEMENT_DEFAULT = false;

const USAGE_STATISTICS_SETTING_ID = "loramanager.usage_statistics";
const USAGE_STATISTICS_DEFAULT = true;

const NEW_TAB_TEMPLATE_ID = "loramanager.new_tab_template";
const NEW_TAB_TEMPLATE_DEFAULT = "Default";

const NEW_TAB_ZOOM_LEVEL = 0.8;

const STRENGTH_STEP_SETTING_ID = "loramanager.strength_step";
const STRENGTH_STEP_DEFAULT = 0.05;

const LORA_ACTIVE_FILTERS_AUTOCOMPLETE_SETTING_ID = "loramanager.lora_active_filters_autocomplete";
const LORA_ACTIVE_FILTERS_AUTOCOMPLETE_DEFAULT = false;

// ============================================================================
// Helper Functions
// ============================================================================

let workflowOptions = [NEW_TAB_TEMPLATE_DEFAULT];
let workflowOptionsFull = [{ value: "Default", label: "Default (Blank)", path: null }];
let workflowOptionsLoaded = false;

const loadWorkflowOptions = async () => {
    if (workflowOptionsLoaded) {
        return;
    }
    try {
        const response = await fetch("/api/lm/example-workflows");
        const data = await response.json();
        if (data.success && data.workflows) {
            workflowOptionsFull = data.workflows;
            workflowOptions = data.workflows.map((w) => w.label);
            workflowOptionsLoaded = true;
        }
    } catch (error) {
        console.warn("LoRA Manager: Failed to fetch workflow options", error);
    }
};

const getWorkflowOptions = () => {
    // Function may be called with or without parameters
    // Return the current workflow options array
    return workflowOptions;
};

const loadTemplateWorkflow = async (templateName) => {
    if (!templateName || templateName === NEW_TAB_TEMPLATE_DEFAULT) {
        return null;
    }
    try {
        const workflow = workflowOptionsFull.find((w) => w.label === templateName);
        if (workflow && workflow.value) {
            const workflowResponse = await fetch(
                `/api/lm/example-workflows/${encodeURIComponent(workflow.value)}`
            );
            const workflowData = await workflowResponse.json();
            if (workflowData.success && workflowData.workflow) {
                return workflowData.workflow;
            }
        }
    } catch (error) {
        console.error("LoRA Manager: Failed to load template workflow", error);
    }
    return null;
};

const getWheelSensitivity = (() => {
    let settingsUnavailableLogged = false;

    return () => {
        const settingManager = app?.extensionManager?.setting;
        if (!settingManager || typeof settingManager.get !== "function") {
            if (!settingsUnavailableLogged) {
                console.warn("LoRA Manager: settings API unavailable, using default wheel sensitivity.");
                settingsUnavailableLogged = true;
            }
            return TRIGGER_WORD_WHEEL_SENSITIVITY_DEFAULT;
        }

        try {
            const value = settingManager.get(TRIGGER_WORD_WHEEL_SENSITIVITY_ID);
            return value ?? TRIGGER_WORD_WHEEL_SENSITIVITY_DEFAULT;
        } catch (error) {
            if (!settingsUnavailableLogged) {
                console.warn("LoRA Manager: unable to read wheel sensitivity setting, using default.", error);
                settingsUnavailableLogged = true;
            }
            return TRIGGER_WORD_WHEEL_SENSITIVITY_DEFAULT;
        }
    };
})();

const getAutoPathCorrectionPreference = (() => {
    let settingsUnavailableLogged = false;

    return () => {
        const settingManager = app?.extensionManager?.setting;
        if (!settingManager || typeof settingManager.get !== "function") {
            if (!settingsUnavailableLogged) {
                console.warn("LoRA Manager: settings API unavailable, defaulting auto path correction to enabled.");
                settingsUnavailableLogged = true;
            }
            return AUTO_PATH_CORRECTION_DEFAULT;
        }

        try {
            const value = settingManager.get(AUTO_PATH_CORRECTION_SETTING_ID);
            return value ?? AUTO_PATH_CORRECTION_DEFAULT;
        } catch (error) {
            if (!settingsUnavailableLogged) {
                console.warn("LoRA Manager: unable to read auto path correction setting, defaulting to enabled.", error);
                settingsUnavailableLogged = true;
            }
            return AUTO_PATH_CORRECTION_DEFAULT;
        }
    };
})();

const getPromptTagAutocompletePreference = (() => {
    let settingsUnavailableLogged = false;

    return () => {
        const settingManager = app?.extensionManager?.setting;
        if (!settingManager || typeof settingManager.get !== "function") {
            if (!settingsUnavailableLogged) {
                console.warn("LoRA Manager: settings API unavailable, using default tag autocomplete setting.");
                settingsUnavailableLogged = true;
            }
            return PROMPT_TAG_AUTOCOMPLETE_DEFAULT;
        }

        try {
            const value = settingManager.get(PROMPT_TAG_AUTOCOMPLETE_SETTING_ID);
            return value ?? PROMPT_TAG_AUTOCOMPLETE_DEFAULT;
        } catch (error) {
            if (!settingsUnavailableLogged) {
                console.warn("LoRA Manager: unable to read tag autocomplete setting, using default.", error);
                settingsUnavailableLogged = true;
            }
            return PROMPT_TAG_AUTOCOMPLETE_DEFAULT;
        }
    };
})();

/**
 * Persist a LoRA Manager setting through ComfyUI's setting API.
 * Returns true when the setting was written successfully.
 */
const setLoraManagerSettingValue = async (settingId, value) => {
    const settingManager = app?.extensionManager?.setting;
    if (settingManager && typeof settingManager.set === "function") {
        await settingManager.set(settingId, value);
        return true;
    }

    const setting = app?.ui?.settings?.settingsById?.[settingId];
    if (setting) {
        app.ui.settings.setSettingValue(settingId, value);
        return true;
    }

    return false;
};

const getAutocompleteAppendCommaPreference = (() => {
    let settingsUnavailableLogged = false;

    return () => {
        const settingManager = app?.extensionManager?.setting;
        if (!settingManager || typeof settingManager.get !== "function") {
            if (!settingsUnavailableLogged) {
                console.warn("LoRA Manager: settings API unavailable, using default append comma setting.");
                settingsUnavailableLogged = true;
            }
            return AUTOCOMPLETE_APPEND_COMMA_DEFAULT;
        }

        try {
            const value = settingManager.get(AUTOCOMPLETE_APPEND_COMMA_SETTING_ID);
            return value ?? AUTOCOMPLETE_APPEND_COMMA_DEFAULT;
        } catch (error) {
            if (!settingsUnavailableLogged) {
                console.warn("LoRA Manager: unable to read append comma setting, using default.", error);
                settingsUnavailableLogged = true;
            }
            return AUTOCOMPLETE_APPEND_COMMA_DEFAULT;
        }
    };
})();

const getAutocompleteAutoFormatPreference = (() => {
    let settingsUnavailableLogged = false;

    return () => {
        const settingManager = app?.extensionManager?.setting;
        if (!settingManager || typeof settingManager.get !== "function") {
            if (!settingsUnavailableLogged) {
                console.warn("LoRA Manager: settings API unavailable, using default autocomplete auto format setting.");
                settingsUnavailableLogged = true;
            }
            return AUTOCOMPLETE_AUTO_FORMAT_DEFAULT;
        }

        try {
            const value = settingManager.get(AUTOCOMPLETE_AUTO_FORMAT_SETTING_ID);
            return value ?? AUTOCOMPLETE_AUTO_FORMAT_DEFAULT;
        } catch (error) {
            if (!settingsUnavailableLogged) {
                console.warn("LoRA Manager: unable to read autocomplete auto format setting, using default.", error);
                settingsUnavailableLogged = true;
            }
            return AUTOCOMPLETE_AUTO_FORMAT_DEFAULT;
        }
    };
})();

const getAutocompleteAcceptKeyPreference = (() => {
    let settingsUnavailableLogged = false;

    return () => {
        const settingManager = app?.extensionManager?.setting;
        if (!settingManager || typeof settingManager.get !== "function") {
            if (!settingsUnavailableLogged) {
                console.warn("LoRA Manager: settings API unavailable, using default autocomplete accept key setting.");
                settingsUnavailableLogged = true;
            }
            return AUTOCOMPLETE_ACCEPT_KEY_DEFAULT;
        }

        try {
            const value = settingManager.get(AUTOCOMPLETE_ACCEPT_KEY_SETTING_ID);
            if (value === AUTOCOMPLETE_ACCEPT_KEY_OPTION_TAB_ONLY) {
                return "tab_only";
            }
            if (value === AUTOCOMPLETE_ACCEPT_KEY_OPTION_ENTER_ONLY) {
                return "enter_only";
            }
            if (value === AUTOCOMPLETE_ACCEPT_KEY_OPTION_BOTH || value == null) {
                return AUTOCOMPLETE_ACCEPT_KEY_DEFAULT;
            }
            return value;
        } catch (error) {
            if (!settingsUnavailableLogged) {
                console.warn("LoRA Manager: unable to read autocomplete accept key setting, using default.", error);
                settingsUnavailableLogged = true;
            }
            return AUTOCOMPLETE_ACCEPT_KEY_DEFAULT;
        }
    };
})();

const getTagSpaceReplacementPreference = (() => {
    let settingsUnavailableLogged = false;

    return () => {
        const settingManager = app?.extensionManager?.setting;
        if (!settingManager || typeof settingManager.get !== "function") {
            if (!settingsUnavailableLogged) {
                console.warn("LoRA Manager: settings API unavailable, using default tag space replacement setting.");
                settingsUnavailableLogged = true;
            }
            return TAG_SPACE_REPLACEMENT_DEFAULT;
        }

        try {
            const value = settingManager.get(TAG_SPACE_REPLACEMENT_SETTING_ID);
            return value ?? TAG_SPACE_REPLACEMENT_DEFAULT;
        } catch (error) {
            if (!settingsUnavailableLogged) {
                console.warn("LoRA Manager: unable to read tag space replacement setting, using default.", error);
                settingsUnavailableLogged = true;
            }
            return TAG_SPACE_REPLACEMENT_DEFAULT;
        }
    };
})();

const getUsageStatisticsPreference = (() => {
    let settingsUnavailableLogged = false;

    return () => {
        const settingManager = app?.extensionManager?.setting;
        if (!settingManager || typeof settingManager.get !== "function") {
            if (!settingsUnavailableLogged) {
                console.warn("LoRA Manager: settings API unavailable, using default usage statistics setting.");
                settingsUnavailableLogged = true;
            }
            return USAGE_STATISTICS_DEFAULT;
        }

        try {
            const value = settingManager.get(USAGE_STATISTICS_SETTING_ID);
            return value ?? USAGE_STATISTICS_DEFAULT;
        } catch (error) {
            if (!settingsUnavailableLogged) {
                console.warn("LoRA Manager: unable to read usage statistics setting, using default.", error);
                settingsUnavailableLogged = true;
            }
            return USAGE_STATISTICS_DEFAULT;
        }
    };
})();

const getNewTabTemplatePreference = (() => {
    let settingsUnavailableLogged = false;

    return () => {
        const settingManager = app?.extensionManager?.setting;
        if (!settingManager || typeof settingManager.get !== "function") {
            if (!settingsUnavailableLogged) {
                console.warn("LoRA Manager: settings API unavailable, using default new tab template.");
                settingsUnavailableLogged = true;
            }
            return NEW_TAB_TEMPLATE_DEFAULT;
        }

        try {
            const value = settingManager.get(NEW_TAB_TEMPLATE_ID);
            return value ?? NEW_TAB_TEMPLATE_DEFAULT;
        } catch (error) {
            if (!settingsUnavailableLogged) {
                console.warn("LoRA Manager: unable to read new tab template setting, using default.", error);
                settingsUnavailableLogged = true;
            }
            return NEW_TAB_TEMPLATE_DEFAULT;
        }
    };
})();

const getStrengthStepPreference = (() => {
    let settingsUnavailableLogged = false;

    return () => {
        const settingManager = app?.extensionManager?.setting;
        if (!settingManager || typeof settingManager.get !== "function") {
            if (!settingsUnavailableLogged) {
                console.warn("LoRA Manager: settings API unavailable, using default strength step.");
                settingsUnavailableLogged = true;
            }
            return STRENGTH_STEP_DEFAULT;
        }

        try {
            const value = settingManager.get(STRENGTH_STEP_SETTING_ID);
            return value ?? STRENGTH_STEP_DEFAULT;
        } catch (error) {
            if (!settingsUnavailableLogged) {
                console.warn("LoRA Manager: unable to read strength step setting, using default.", error);
                settingsUnavailableLogged = true;
            }
            return STRENGTH_STEP_DEFAULT;
        }
    };
})();

const getLoraActiveFiltersAutocompletePreference = (() => {
    let settingsUnavailableLogged = false;

    return () => {
        const settingManager = app?.extensionManager?.setting;
        if (!settingManager || typeof settingManager.get !== "function") {
            if (!settingsUnavailableLogged) {
                console.warn("LoRA Manager: settings API unavailable, using default lora active filters autocomplete setting.");
                settingsUnavailableLogged = true;
            }
            return LORA_ACTIVE_FILTERS_AUTOCOMPLETE_DEFAULT;
        }

        try {
            const value = settingManager.get(LORA_ACTIVE_FILTERS_AUTOCOMPLETE_SETTING_ID);
            return value ?? LORA_ACTIVE_FILTERS_AUTOCOMPLETE_DEFAULT;
        } catch (error) {
            if (!settingsUnavailableLogged) {
                console.warn("LoRA Manager: unable to read lora active filters autocomplete setting, using default.", error);
                settingsUnavailableLogged = true;
            }
            return LORA_ACTIVE_FILTERS_AUTOCOMPLETE_DEFAULT;
        }
    };
})();

// ============================================================================
// Register Extension with All Settings
// ============================================================================

app.registerExtension({
    name: "LoraManager.Settings",
    settings: [
        {
            id: TRIGGER_WORD_WHEEL_SENSITIVITY_ID,
            name: "Trigger Word Wheel Sensitivity",
            type: "slider",
            attrs: {
                min: 0.01,
                max: 0.1,
                step: 0.01,
            },
            defaultValue: TRIGGER_WORD_WHEEL_SENSITIVITY_DEFAULT,
            tooltip: "Mouse wheel sensitivity for adjusting trigger word strength (default: 0.02)",
            category: ["LoRA Manager", "Trigger Word Toggle", "Wheel Sensitivity"],
        },
        {
            id: AUTO_PATH_CORRECTION_SETTING_ID,
            name: "Auto path correction",
            type: "boolean",
            defaultValue: AUTO_PATH_CORRECTION_DEFAULT,
            tooltip: "Automatically update model paths to their current file locations.",
            category: ["LoRA Manager", "Automation", "Auto path correction"],
        },
        {
            id: PROMPT_TAG_AUTOCOMPLETE_SETTING_ID,
            name: "Enable Tag Autocomplete in Prompt Nodes",
            type: "boolean",
            defaultValue: PROMPT_TAG_AUTOCOMPLETE_DEFAULT,
            tooltip: "When enabled, typing in a Prompt (LoraManager) node triggers tag autocomplete suggestions. You can also toggle it by typing /autocomplete or /noautocomplete in the node, or from the node's right-click menu. Slash commands (e.g., /character, /artist) always work regardless of this setting.",
            category: ["LoRA Manager", "Autocomplete", "Prompt"],
        },
        {
            id: LORA_ACTIVE_FILTERS_AUTOCOMPLETE_SETTING_ID,
            name: "Search LoRA autocomplete within active filters",
            type: "boolean",
            defaultValue: LORA_ACTIVE_FILTERS_AUTOCOMPLETE_DEFAULT,
            tooltip: "When enabled, LoRA autocomplete suggestions respect the active filters (folder/base model/tags) set in the LoRA Manager page. Commands /activefilters and /noactivefilters toggle this mode.",
            category: ["LoRA Manager", "Autocomplete", "LoRA Active Filters"],
        },
        {
            id: AUTOCOMPLETE_APPEND_COMMA_SETTING_ID,
            name: "Append comma after autocomplete",
            type: "boolean",
            defaultValue: AUTOCOMPLETE_APPEND_COMMA_DEFAULT,
            tooltip: "When enabled, accepted autocomplete suggestions append ', ' to the inserted text.",
            category: ["LoRA Manager", "Autocomplete", "Append comma"],
        },
        {
            id: AUTOCOMPLETE_AUTO_FORMAT_SETTING_ID,
            name: "Auto format autocomplete text on blur",
            type: "boolean",
            defaultValue: AUTOCOMPLETE_AUTO_FORMAT_DEFAULT,
            tooltip: "When enabled, leaving an autocomplete textarea removes duplicate commas and collapses unnecessary spaces.",
            category: ["LoRA Manager", "Autocomplete", "Auto Format"],
        },
        {
            id: AUTOCOMPLETE_ACCEPT_KEY_SETTING_ID,
            name: "Autocomplete accept key",
            type: "combo",
            options: [
                AUTOCOMPLETE_ACCEPT_KEY_OPTION_BOTH,
                AUTOCOMPLETE_ACCEPT_KEY_OPTION_TAB_ONLY,
                AUTOCOMPLETE_ACCEPT_KEY_OPTION_ENTER_ONLY,
            ],
            defaultValue: AUTOCOMPLETE_ACCEPT_KEY_OPTION_BOTH,
            tooltip: "Choose which key accepts the selected autocomplete suggestion. Keys not selected here keep their normal textarea behavior.",
            category: ["LoRA Manager", "Autocomplete", "Accept key"],
        },
        {
            id: TAG_SPACE_REPLACEMENT_SETTING_ID,
            name: "Replace underscores with spaces in tags",
            type: "boolean",
            defaultValue: TAG_SPACE_REPLACEMENT_DEFAULT,
            tooltip: "When enabled, tag names with underscores will have them replaced with spaces when inserted (e.g., 'blonde_hair' becomes 'blonde hair').",
            category: ["LoRA Manager", "Autocomplete", "Tag Formatting"],
        },
        {
            id: USAGE_STATISTICS_SETTING_ID,
            name: "Enable usage statistics tracking",
            type: "boolean",
            defaultValue: USAGE_STATISTICS_DEFAULT,
            tooltip: "When enabled, LoRA Manager will track model usage statistics during workflow execution. Disabling this will prevent unnecessary disk writes.",
            category: ["LoRA Manager", "Statistics", "Usage Tracking"],
        },
        {
            id: NEW_TAB_TEMPLATE_ID,
            name: "New Tab Template Workflow",
            type: "combo",
            options: getWorkflowOptions,
            defaultValue: NEW_TAB_TEMPLATE_DEFAULT,
            tooltip: "Choose a template workflow to load when creating a new workflow tab. 'Default (Blank)' keeps ComfyUI's original blank workflow behavior.",
            category: ["LoRA Manager", "Workflow", "New Tab Template"],
        },
        {
            id: STRENGTH_STEP_SETTING_ID,
            name: "Strength Adjustment Step",
            type: "slider",
            attrs: {
                min: 0.01,
                max: 0.1,
                step: 0.01,
            },
            defaultValue: STRENGTH_STEP_DEFAULT,
            tooltip: "Step size for adjusting LoRA strength via arrow buttons or keyboard (default: 0.05)",
            category: ["LoRA Manager", "LoRA Widget", "Strength Step"],
        },
    ],
    async setup() {
        await loadWorkflowOptions();

        const originalNewBlankWorkflow = async () => {
            const blankGraph = {
                last_node_id: 0,
                last_link_id: 0,
                nodes: [],
                links: [],
                groups: [],
                config: {},
                extra: {},
                version: 0.4,
            };
            await app.loadGraphData(blankGraph);
        };

        const waitForCommandStore = async (maxWaitMs = 5000) => {
            const startTime = Date.now();
            while (Date.now() - startTime < maxWaitMs) {
                if (app.extensionManager?.command?.commands) {
                    return true;
                }
                await new Promise((resolve) => setTimeout(resolve, 100));
            }
            return false;
        };

        const patchCommand = async () => {
            const storeReady = await waitForCommandStore();
            if (!storeReady) {
                console.warn("LoRA Manager: Could not access command store to patch NewBlankWorkflow");
                return;
            }

            const commands = app.extensionManager.command.commands;
            for (const cmd of commands) {
                if (cmd.id === "Comfy.NewBlankWorkflow") {
                    const originalFunc = cmd.function;
                    cmd.function = async (metadata) => {
                        const templateName = getNewTabTemplatePreference();
                        
                        if (templateName && templateName !== NEW_TAB_TEMPLATE_DEFAULT) {
                            const workflowData = await loadTemplateWorkflow(templateName);
                            if (workflowData) {
                                // Override the workflow's saved view settings with our custom zoom
                                if (!workflowData.extra) {
                                    workflowData.extra = {};
                                }
                                if (!workflowData.extra.ds) {
                                    workflowData.extra.ds = { offset: [0, 0], scale: 1 };
                                }
                                workflowData.extra.ds.scale = NEW_TAB_ZOOM_LEVEL;
                                
                                await app.loadGraphData(workflowData);
                                return;
                            }
                        }
                        
                        await originalNewBlankWorkflow();
                    };
                    break;
                }
            }
        };

        patchCommand();
    },
});

// ============================================================================
// Exports
// ============================================================================

export {
    PROMPT_TAG_AUTOCOMPLETE_SETTING_ID,
    getWheelSensitivity,
    getAutoPathCorrectionPreference,
    getAutocompleteAppendCommaPreference,
    getAutocompleteAutoFormatPreference,
    getAutocompleteAcceptKeyPreference,
    getPromptTagAutocompletePreference,
    getTagSpaceReplacementPreference,
    getUsageStatisticsPreference,
    getNewTabTemplatePreference,
    getStrengthStepPreference,
    getLoraActiveFiltersAutocompletePreference,
    setLoraManagerSettingValue,
};
