/**
 * Agenistrator - Settings Page.
 *
 * Handles all settings page functionality including provider management and model settings.
 *
 * @package   Agenistrator
 * @since     1.0.0
 * @author    Alex Ruban <alex@maximum.guru>
 * @author    Maximum Software Inc <contact@maximum.software>
 * @license   GPL-3.0-only
 * @link      https://maximum.software/
 *
 * SPDX-FileCopyrightText: 2025-2026 Alex Ruban <alex@maximum.guru>
 * SPDX-FileCopyrightText: 2025-2026 Maximum Software Inc <contact@maximum.software>
 * SPDX-License-Identifier: GPL-3.0-only
 */
jQuery(document).ready(function() {
    'use strict';

    window.Agenistrator = window.Agenistrator || {};

    // Register templates if they exist in the settings object
    if (agenistrator_settings && agenistrator_settings.templates) {
        Agenistrator.Template.registerTemplates(agenistrator_settings.templates);
    }

    Agenistrator.SettingsManager = {
        elements: {},

        /**
         * Initialize settings page functionality.
         *
         * @since 1.0.0
         */
        init: function() {
            if (!jQuery('.agenistrator-settings').length) {
                return;
            }

            this.elements = {
                $navTabs: jQuery('.agenistrator-settings .nav-tab'),
                $tabContent: jQuery('.agenistrator-settings .tab-content'),
                $syncEmbeddings: jQuery('#sync-embeddings'),
                $regenerateAllEmbeddings: jQuery('#regenerate-all-embeddings'),
                $embeddingsProgressContainer: jQuery('#embeddings-progress-container'),
                $chatModelSelect: jQuery('#agenistrator_chat_model'),
                $embeddingsModelSelect: jQuery('#agenistrator_embeddings_model'),
                $providerDataScript: jQuery('#agenistrator-provider-data'),
                $activeTabInput: jQuery('#agenistrator-active-tab')
            };

            this.bindEvents();

            // Update model dropdowns for all configured providers
            this.updateModelDropdowns();

            // Handle URL hash to activate the correct tab on page load
            this.activateTabFromHash();

            // Listen for hash changes while on the page
            var self = this;
            jQuery(window).on('hashchange', function() {
                self.activateTabFromHash();
            });
        },

        /**
         * Activate tab based on URL hash fragment.
         *
         * @since 1.0.0
         */
        activateTabFromHash: function() {
            var hash = window.location.hash;
            if (hash) {
                var $targetTab = this.elements.$navTabs.filter('[href="' + hash + '"]');
                if ($targetTab.length) {
                    $targetTab.trigger('click');
                }
            }
        },

        /**
         * Bind event handlers for settings page interactions.
         *
         * @since 1.0.0
         */
        bindEvents: function() {
            var self = this;

            this.elements.$navTabs.on('click', function(e) {
                e.preventDefault();
                var targetTab = jQuery(this).attr('href');

                self.elements.$navTabs.removeClass('nav-tab-active');
                jQuery(this).addClass('nav-tab-active');
                self.elements.$tabContent.hide();
                jQuery(targetTab).show();

                // Update URL hash without triggering hashchange
                history.replaceState(null, null, targetTab);

                // Track active tab for form submission
                self.elements.$activeTabInput.val(targetTab);

                // Show/hide embeddings warning based on model selection
                if (targetTab === '#embeddings') {
                    self.updateEmbeddingsTabState();
                }
            });

            this.elements.$syncEmbeddings.on('click', function() {
                var button = jQuery(this);
                var statusEl = button.siblings('.embeddings-status');
                var regenerateAll = self.elements.$regenerateAllEmbeddings.is(':checked');

                statusEl.text(agenistrator_settings.strings.generating_embeddings).show();
                button.prop('disabled', true).addClass('disabled');

                jQuery.ajax({
                    url: ajaxurl,
                    method: 'POST',
                    data: {
                        action: 'agenistrator_sync_embeddings',
                        nonce: agenistrator.nonce,
                        regenerate_all: regenerateAll
                    },
                    success: function(response) {
                        if (response.success) {
                            if (regenerateAll) {
                                statusEl.text(agenistrator_settings.strings.embeddings_scheduled);
                            } else {
                                statusEl.text(response.data.message);
                            }
                        } else {
                            statusEl.text(response.data && response.data.message ? response.data.message : agenistrator_settings.strings.error_generating_embeddings);
                        }
                        button.prop('disabled', false).removeClass('disabled');
                    },
                    error: function(xhr, status, error) {
                        var errorDetails = error;

                        // Try to extract a meaningful error message
                        if (xhr.responseJSON && xhr.responseJSON.data && xhr.responseJSON.data.message) {
                            errorDetails = xhr.responseJSON.data.message;
                        } else if (xhr.responseText) {
                            errorDetails = xhr.responseText.substring(0, 100);
                        } else if (error) {
                            errorDetails = error.toString();
                        }

                        var errorMessage = Agenistrator.Template.replaceTags(
                            agenistrator_settings.strings.server_error,
                            { error_details: errorDetails }
                        );
                        statusEl.text(errorMessage);
                        button.prop('disabled', false).removeClass('disabled');
                    }
                });
            });

            // Update embeddings tab state when embeddings model selection changes
            this.elements.$embeddingsModelSelect.on('change', function() {
                self.updateEmbeddingsTabState();
            });
        },

        /**
         * Update model dropdowns with models from all configured providers.
         *
         * @since 1.0.0
         */
        updateModelDropdowns: function() {
            var self = this;

            // Model settings tab is always accessible
            jQuery('a[href="#model-settings"]').removeClass('disabled-tab');

            // Embeddings tab is always accessible (shows informative state)
            jQuery('a[href="#embeddings"]').removeClass('disabled-tab');

            // Update embeddings tab state based on current model selection
            this.updateEmbeddingsTabState();

            // Fetch models from the API (all providers)
            jQuery.ajax({
                url: ajaxurl,
                method: 'POST',
                data: {
                    action: 'agenistrator_get_models',
                    nonce: agenistrator.nonce
                },
                success: function(response) {
                    if (response.success) {
                        var data = response.data;
                        self.updateModelDropdownsWithData(data);

                        // Model settings tab is always enabled since "None" is a valid option
                        jQuery('a[href="#model-settings"]').removeClass('disabled-tab');

                        // Update embeddings tab state after models are loaded
                        self.updateEmbeddingsTabState();
                    } else {
                        var errorMessage = Agenistrator.Template.replaceTags(
                            agenistrator_settings.strings.error_fetching_models,
                            { error_details: (response.data && response.data.message ? response.data.message : response.data) }
                        );
                        Agenistrator.Log.logError(errorMessage, response);
                    }
                },
                error: function(error) {
                    Agenistrator.Log.logError(agenistrator_settings.strings.server_error_fetching_models, error);
                }
            });
        },

        /**
         * Update the embeddings tab state.
         *
         * @since 1.0.0
         */
        updateEmbeddingsTabState: function() {
            var hasEmbeddingsModel = this.elements.$embeddingsModelSelect.val();
            var $databaseWarning = jQuery('#database-incompatible-warning');
            var $modelWarning = jQuery('#no-embeddings-model-warning');
            var $syncButton = this.elements.$syncEmbeddings;

            if (!agenistrator_settings.is_database_compatible) {
                $databaseWarning.show();
                $modelWarning.hide();
                $syncButton.prop('disabled', true);
            } else if (hasEmbeddingsModel) {
                $databaseWarning.hide();
                $modelWarning.hide();
                $syncButton.prop('disabled', false);
            } else {
                $databaseWarning.hide();
                $modelWarning.show();
                $syncButton.prop('disabled', true);
            }
        },

        /**
         * Update model dropdown options with the fetched data.
         *
         * @param {Object} modelsData - Models data from providers.
         * @since 1.0.0
         */
        updateModelDropdownsWithData: function(modelsData) {
            if (!modelsData) return;

            // Get the currently selected models
            var currentChatModel = this.elements.$chatModelSelect.val();
            var currentEmbeddingsModel = this.elements.$embeddingsModelSelect.val();

            // Reset model selects
            this.elements.$chatModelSelect.empty().prop('disabled', false);
            this.elements.$embeddingsModelSelect.empty().prop('disabled', false);

            // Add available chat models and check if current model exists
            var chatResult = { html: '', foundCurrent: false };
            if (modelsData.chat && modelsData.chat.length > 0) {
                chatResult = this.buildModelOptions(modelsData.chat, currentChatModel);
            }

            // Select "None" if no current model or current model's provider not found
            var selectChatNone = !currentChatModel || !chatResult.foundCurrent;

            // Chat models - always add "None" option first
            var chatNoneOptionHtml = Agenistrator.Template.render('settings-select-option', {
                value: '',
                text: agenistrator_settings.strings.chat_none,
                selected: selectChatNone ? 'selected' : '',
                disabled: ''
            });
            this.elements.$chatModelSelect.append(chatNoneOptionHtml);

            // Add the chat model options
            if (chatResult.html) {
                this.elements.$chatModelSelect.append(chatResult.html);
            }

            // Add available embedding models and check if current model exists
            var embeddingResult = { html: '', foundCurrent: false };
            if (modelsData.embedding && modelsData.embedding.length > 0) {
                embeddingResult = this.buildModelOptions(modelsData.embedding, currentEmbeddingsModel);
            }

            // Select "None" if no current model or current model's provider not found
            var selectEmbeddingsNone = !currentEmbeddingsModel || !embeddingResult.foundCurrent;

            // Embedding models - always add "None" option first
            var noneOptionHtml = Agenistrator.Template.render('settings-select-option', {
                value: '',
                text: agenistrator_settings.strings.embeddings_none,
                selected: selectEmbeddingsNone ? 'selected' : '',
                disabled: ''
            });
            this.elements.$embeddingsModelSelect.append(noneOptionHtml);

            // Add the embedding model options
            if (embeddingResult.html) {
                this.elements.$embeddingsModelSelect.append(embeddingResult.html);
            }
        },

        /**
         * Build model select options HTML.
         *
         * @param {Array} models - Array of model objects.
         * @param {string} currentValue - Currently selected value.
         * @returns {Object} Object with html and foundCurrent properties.
         * @since 1.0.0
         */
        buildModelOptions: function(models, currentValue) {
            var html = '';
            var foundCurrent = false;

            // Group models by provider
            var modelsByProvider = {};
            models.forEach(function(model) {
                if (!modelsByProvider[model.provider]) {
                    modelsByProvider[model.provider] = [];
                }
                modelsByProvider[model.provider].push(model);
            });

            // Process each provider group (sorted alphabetically)
            Object.keys(modelsByProvider).sort().forEach(function(providerName) {
                var optionsHtml = '';

                // Sort models alphabetically by display name
                modelsByProvider[providerName].sort(function(a, b) {
                    return (a.name || a.id).localeCompare(b.name || b.id);
                });

                // Build options for this provider
                modelsByProvider[providerName].forEach(function(model) {
                    var isSelected = model.id === currentValue;
                    if (isSelected) {
                        foundCurrent = true;
                    }

                    optionsHtml += Agenistrator.Template.render('settings-select-option', {
                        value: Agenistrator.Format.escapeHTMLChars(model.id),
                        text: Agenistrator.Format.escapeHTML(model.name || model.id),
                        selected: isSelected ? 'selected' : '',
                        disabled: ''
                    });
                });

                // Build optgroup
                html += Agenistrator.Template.render('settings-select-optgroup', {
                    label: Agenistrator.Format.escapeHTMLChars(providerName),
                    options: optionsHtml
                });
            });

            return { html: html, foundCurrent: foundCurrent };
        }
    };

    Agenistrator.ProviderManager = {
        elements: {},
        providerData: null,

        /**
         * Initialize provider manager functionality.
         *
         * @since 1.0.0
         */
        init: function() {
            if (!jQuery('.agenistrator-settings').length) {
                return;
            }

            // Initialize element references for elements that exist in the DOM initially
            this.elements = {
                $providerDataScript: jQuery('#agenistrator-provider-data'),
                $providerListBody: jQuery('#provider-list-body'),
                $addProviderButton: jQuery('.add-provider'),
                $providerList: jQuery('#provider-list')
            };

            // The provider form is not in the DOM initially, so we set all form-related references to empty jQuery objects
            this.elements.$providerForm = jQuery();
            this.elements.$providerFormTitle = jQuery();
            this.elements.$providerDisplayName = jQuery();
            this.elements.$providerType = jQuery();
            this.elements.$providerId = jQuery();
            this.elements.$providerTestStatus = jQuery();
            this.elements.$providerParams = jQuery();
            this.elements.$testProviderConfig = jQuery();
            this.elements.$saveProvider = jQuery();
            this.elements.$cancelProviderButton = jQuery();

            this.bindEvents();

            // Populate provider list
            this.populateProviderList();
        },

        /**
         * Get provider data from the script tag.
         *
         * @returns {Object} Provider data object.
         * @since 1.0.0
         */
        getProviderData: function() {
            if (this.providerData === null) {
                try {
                    var jsonText = this.elements.$providerDataScript.text();
                    if (jsonText) {
                        this.providerData = JSON.parse(jsonText);
                    } else {
                        this.providerData = { instances: {}, types: [] };
                    }
                } catch (e) {
                    Agenistrator.Log.logError(agenistrator_settings.strings.error_parsing_provider_data, e);
                    this.providerData = { instances: {}, types: [] };
                }
            }
            return this.providerData;
        },

        /**
         * Bind event handlers for provider management.
         *
         * @since 1.0.0
         */
        bindEvents: function() {
            var self = this;

            this.elements.$addProviderButton.on('click', function(e) {
                e.preventDefault();
                self.showProviderForm();
            });

            jQuery(document).on('click', '.enable-provider', function(e) {
                e.preventDefault();
                var providerId = jQuery(this).data('provider-id');
                self.enableProvider(providerId);
            });

            jQuery(document).on('click', '.disable-provider', function(e) {
                e.preventDefault();
                var providerId = jQuery(this).data('provider-id');
                self.disableProvider(providerId);
            });

            jQuery(document).on('click', '.delete-provider', function(e) {
                e.preventDefault();
                var providerId = jQuery(this).data('provider-id');
                self.deleteProvider(providerId);
            });

            jQuery(document).on('click', '.edit-provider', function(e) {
                e.preventDefault();
                var providerId = jQuery(this).data('provider-id');
                self.editProvider(providerId);
            });
        },

        /**
         * Load parameters for the selected provider type.
         *
         * @param {string} providerType - The provider type ID.
         * @returns {Promise} Promise that resolves when parameters are loaded.
         * @since 1.0.0
         */
        loadProviderParameters: function(providerType) {
            if (!providerType) {
                return Promise.resolve();
            }

            // Make sure we have the correct elements
            var $providerParams = jQuery('#provider-parameters');
            var $providerTestStatus = jQuery('#provider-test-status');

            this.elements.$providerParams = $providerParams;
            this.elements.$providerTestStatus = $providerTestStatus;

            $providerParams.empty();
            $providerTestStatus.hide();

            // Add a loading indicator
            $providerParams.html(Agenistrator.Template.render('settings-message', {
                css_class: '',
                message: agenistrator_settings.strings.loading_parameters
            }));

            // Return a Promise that resolves when parameters are loaded
            return new Promise(function(resolve, reject) {
                jQuery.ajax({
                    url: ajaxurl,
                    method: 'POST',
                    data: {
                        action: 'agenistrator_get_provider_parameters',
                        nonce: agenistrator.nonce,
                        provider_type: providerType
                    },
                    success: function(response) {
                        $providerParams.empty();

                        if (response.success && response.data) {
                            var data = response.data.parameters;
                            var apiKeyUrl = response.data.api_key_url || '';

                            // Check if data is an object with parameters
                            if (data && typeof data === 'object' && Object.keys(data).length > 0) {
                                // Convert object to array of parameters with their keys
                                Object.keys(data).forEach(function(paramName) {
                                    var param = data[paramName];
                                    var paramLabel = param.name || paramName;
                                    var inputType = param.type === 'password' ? 'password' : (param.type === 'number' ? 'number' : 'text');
                                    var required = param.required ? 'required' : '';
                                    var value = param.default || '';

                                    // Build extra attributes for number inputs
                                    var extraAttrs = '';
                                    if (param.type === 'number') {
                                        if (param.min !== undefined && !isNaN(Number(param.min))) {
                                            extraAttrs += 'min="' + Number(param.min) + '" ';
                                        }
                                        if (param.max !== undefined && !isNaN(Number(param.max))) {
                                            extraAttrs += 'max="' + Number(param.max) + '" ';
                                        }
                                        if (param.step !== undefined && !isNaN(Number(param.step))) {
                                            extraAttrs += 'step="' + Number(param.step) + '" ';
                                        }
                                    }

                                    // Build description HTML - escape text first, then append HTML elements
                                    var description = Agenistrator.Format.escapeHTML(param.description);
                                    if (paramName === 'api_key' && apiKeyUrl) {
                                        description += '<br>' + Agenistrator.Template.render('external-link', {
                                            url: Agenistrator.Format.escapeHTMLChars(apiKeyUrl),
                                            text: agenistrator_settings.strings.get_api_key
                                        });
                                    }

                                    // Render the parameter row using the template system
                                    var html = Agenistrator.Template.render('settings-provider-parameter-row', {
                                        name: Agenistrator.Format.escapeHTMLChars(paramName),
                                        label: Agenistrator.Format.escapeHTML(paramLabel),
                                        input_type: inputType,
                                        provider_type: Agenistrator.Format.escapeHTMLChars(providerType),
                                        value: Agenistrator.Format.escapeHTMLChars(value),
                                        required: required,
                                        description: description,
                                        extra_attrs: extraAttrs
                                    });

                                    $providerParams.append(html);
                                });
                                // Resolve the promise with the loaded parameters
                                resolve(data);
                            } else {
                                $providerParams.html(Agenistrator.Template.render('settings-message', {
                                    css_class: '',
                                    message: agenistrator_settings.strings.no_parameters_required
                                }));
                                // Resolve with empty object since there are no parameters
                                resolve({});
                            }
                        } else {
                            var errorMsg = response.data && response.data.message ? response.data.message : agenistrator_settings.strings.error_loading_parameters;
                            var errorMessage = Agenistrator.Template.replaceTags(
                                agenistrator_settings.strings.error_prefix,
                                { error_details: errorMsg }
                            );
                            $providerParams.html(Agenistrator.Template.render('settings-message', {
                                css_class: 'error',
                                message: Agenistrator.Format.escapeHTML(errorMessage)
                            }));
                            Agenistrator.Log.logError(agenistrator_settings.strings.error_loading_parameters, response);
                            // Reject the promise with the error message
                            reject(new Error(errorMsg));
                        }
                    },
                    error: function(error) {
                        var errorMsg = Agenistrator.Template.replaceTags(
                            agenistrator_settings.strings.error_loading_parameters_with_details,
                            { error_details: error.toString() }
                        );
                        $providerParams.html(Agenistrator.Template.render('settings-message', {
                            css_class: 'error',
                            message: Agenistrator.Format.escapeHTML(errorMsg)
                        }));
                        Agenistrator.Log.logError(agenistrator_settings.strings.error_loading_parameters, error);
                        // Reject the promise with the error
                        reject(error);
                    }
                });
            });
        },

        /**
         * Load and edit an existing provider configuration.
         *
         * @param {string} providerId - The provider ID to edit.
         * @since 1.0.0
         */
        editProvider: function(providerId) {
            var self = this;

            // Show the provider form (this will create it if it doesn't exist)
            self.showProviderForm();

            // Set the title to 'Edit Provider'
            self.elements.$providerFormTitle.text(agenistrator_settings.strings.edit_provider);

            jQuery.ajax({
                url: ajaxurl,
                method: 'POST',
                data: {
                    action: 'agenistrator_get_provider_data',
                    nonce: agenistrator.nonce,
                    provider_id: providerId
                },
                success: function(response) {
                    if (response.success) {
                        var data = response.data.provider_data;
                        self.elements.$providerType.val(data.type);
                        self.elements.$providerDisplayName.val(data.display_name);
                        self.elements.$providerId.val(providerId);

                        // Load parameters and then set their values once loaded
                        self.loadProviderParameters(data.type)
                            .then(function() {
                                if (data.parameters) {
                                    Object.keys(data.parameters).forEach(function(paramName) {
                                        jQuery('#param-' + paramName).val(data.parameters[paramName]);
                                    });
                                }
                            });

                        jQuery('html, body').animate({
                            scrollTop: jQuery('#provider-form').offset().top - 50
                        }, 500);
                    } else {
                        var errorMsg = Agenistrator.Template.replaceTags(
                            agenistrator_settings.strings.error_loading_provider_data_with_details,
                            { error_details: response.data && response.data.message ? response.data.message : agenistrator.strings.unknown_error }
                        );
                        Agenistrator.Log.logError(response.data && response.data.message ? response.data.message : errorMsg, response);
                    }
                },
                error: function(error) {
                    var errorMsg = Agenistrator.Template.replaceTags(
                        agenistrator_settings.strings.error_loading_provider_data_with_details,
                        { error_details: error.toString() }
                    );
                    Agenistrator.Log.logError(errorMsg, error);
                }
            });
        },

        /**
         * Test the current provider configuration.
         *
         * @since 1.0.0
         */
        testProviderConfig: function() {
            if (!this.validateProviderForm()) {
                return;
            }

            var self = this;
            var providerType = this.elements.$providerType.val();
            var params = {};

            // Get all provider parameters
            jQuery('.provider-param').each(function() {
                var paramName = jQuery(this).data('param-name');
                var paramValue = jQuery(this).val();
                if (paramValue) {
                    params[paramName] = paramValue;
                }
            });

            this.elements.$providerTestStatus.text(agenistrator_settings.strings.testing_configuration).removeClass('agenistrator-success agenistrator-error').show();
            this.elements.$testProviderConfig.prop('disabled', true);
            jQuery.ajax({
                url: ajaxurl,
                method: 'POST',
                data: {
                    action: 'agenistrator_test_provider_config',
                    nonce: agenistrator.nonce,
                    provider_type: providerType,
                    params: params
                },
                success: function(response) {
                    if (response.success) {
                        self.elements.$providerTestStatus.text(agenistrator_settings.strings.configuration_valid).removeClass('agenistrator-error').addClass('agenistrator-success');
                    } else {
                        var errorMsg = response.data && response.data.message ? response.data.message : agenistrator_settings.strings.configuration_invalid;
                        self.elements.$providerTestStatus.text(errorMsg).removeClass('agenistrator-success').addClass('agenistrator-error');
                    }
                },
                error: function(error) {
                    var errorMsg = Agenistrator.Template.replaceTags(
                        agenistrator_settings.strings.error_testing_configuration_with_details,
                        { error_details: error.textStatus }
                    );
                    self.elements.$providerTestStatus.text(errorMsg).removeClass('agenistrator-success').addClass('agenistrator-error');
                },
                complete: function() {
                    self.elements.$testProviderConfig.prop('disabled', false);
                }
            });
        },

        /**
         * Save the current provider configuration.
         *
         * @since 1.0.0
         */
        saveProvider: function() {
            if (!this.validateProviderForm()) {
                return;
            }

            var providerType = this.elements.$providerType.val();
            var displayName = this.elements.$providerDisplayName.val();
            var providerId = this.elements.$providerId.val();
            var params = {};

            // Get all provider parameters
            jQuery('.provider-param').each(function() {
                var paramName = jQuery(this).data('param-name');
                var paramValue = jQuery(this).val();
                if (paramValue) {
                    params[paramName] = paramValue;
                }
            });
            jQuery.ajax({
                url: ajaxurl,
                method: 'POST',
                data: {
                    action: 'agenistrator_save_provider',
                    nonce: agenistrator.nonce,
                    provider_type: providerType,
                    display_name: displayName,
                    provider_id: providerId,
                    params: params
                },
                success: function(response) {
                    if (response.success) {
                        // Reload page to show updated provider list
                        window.location.reload();
                    } else {
                        Agenistrator.Log.logError(response.data && response.data.message ? response.data.message : agenistrator_settings.strings.error_saving_provider, response);
                    }
                },
                error: function(error) {
                    var errorMsg = Agenistrator.Template.replaceTags(
                        agenistrator_settings.strings.error_saving_provider_with_details,
                        { error_details: error.toString() }
                    );
                    Agenistrator.Log.logError(errorMsg, error);
                }
            });
        },

        /**
         * Enable a provider.
         *
         * @param {string} providerId - The provider ID to enable.
         * @since 1.0.0
         */
        enableProvider: function(providerId) {
            jQuery.ajax({
                url: ajaxurl,
                method: 'POST',
                data: {
                    action: 'agenistrator_enable_provider',
                    nonce: agenistrator.nonce,
                    provider_id: providerId
                },
                success: function(response) {
                    if (response.success) {
                        // Reload page to show updated provider list
                        window.location.reload();
                    } else {
                        Agenistrator.Log.logError(response.data && response.data.message ? response.data.message : agenistrator_settings.strings.error_enabling_provider, response);
                    }
                },
                error: function(error) {
                    var errorMsg = Agenistrator.Template.replaceTags(
                        agenistrator_settings.strings.error_enabling_provider_with_details,
                        { error_details: error.toString() }
                    );
                    Agenistrator.Log.logError(errorMsg, error);
                }
            });
        },

        /**
         * Disable a provider.
         *
         * @param {string} providerId - The provider ID to disable.
         * @since 1.0.0
         */
        disableProvider: function(providerId) {
            jQuery.ajax({
                url: ajaxurl,
                method: 'POST',
                data: {
                    action: 'agenistrator_disable_provider',
                    nonce: agenistrator.nonce,
                    provider_id: providerId
                },
                success: function(response) {
                    if (response.success) {
                        // Reload page to show updated provider list
                        window.location.reload();
                    } else {
                        Agenistrator.Log.logError(response.data && response.data.message ? response.data.message : agenistrator_settings.strings.error_disabling_provider, response);
                    }
                },
                error: function(error) {
                    var errorMsg = Agenistrator.Template.replaceTags(
                        agenistrator_settings.strings.error_disabling_provider_with_details,
                        { error_details: error.toString() }
                    );
                    Agenistrator.Log.logError(errorMsg, error);
                }
            });
        },

        /**
         * Delete a provider.
         *
         * @param {string} providerId - The provider ID to delete.
         * @since 1.0.0
         */
        deleteProvider: function(providerId) {
            if (!confirm(agenistrator_settings.strings.confirm_delete_provider)) {
                return;
            }

            jQuery.ajax({
                url: ajaxurl,
                method: 'POST',
                data: {
                    action: 'agenistrator_delete_provider',
                    nonce: agenistrator.nonce,
                    provider_id: providerId
                },
                success: function(response) {
                    if (response.success) {
                        // Reload page to show updated provider list
                        window.location.reload();
                    } else {
                        Agenistrator.Log.logError(response.data && response.data.message ? response.data.message : agenistrator_settings.strings.error_deleting_provider, response);
                    }
                },
                error: function(error) {
                    var errorMsg = Agenistrator.Template.replaceTags(
                        agenistrator_settings.strings.error_deleting_provider_with_details,
                        { error_details: error.toString() }
                    );
                    Agenistrator.Log.logError(errorMsg, error);
                }
            });
        },

        /**
         * Validate the provider form before saving or testing.
         *
         * @returns {boolean} True if valid, false otherwise.
         * @since 1.0.0
         */
        validateProviderForm: function() {
            if (!this.elements.$providerDisplayName.val()) {
                Agenistrator.Log.logWarning(agenistrator_settings.strings.provider_name_required);
                this.elements.$providerDisplayName.focus();
                return false;
            }

            var valid = true;
            // Find all required parameters within the provider parameters container
            this.elements.$providerParams.find('.provider-param[required]').each(function() {
                if (!jQuery(this).val()) {
                    var fieldName = jQuery(this).closest('tr').find('label').text();
                    var message = Agenistrator.Template.replaceTags(
                        agenistrator_settings.strings.field_required,
                        { field_name: fieldName }
                    );
                    Agenistrator.Log.logWarning(message);
                    jQuery(this).focus();
                    valid = false;
                    return false;
                }
            });

            return valid;
        },

        /**
         * Populate provider types dropdown.
         *
         * @since 1.0.0
         */
        populateProviderTypes: function() {
            var providerTypes = this.getProviderData().types;

            // Make sure we have a valid provider type select element
            if (this.elements.$providerType && this.elements.$providerType.length) {
                // Clear existing options
                this.elements.$providerType.empty();

                // Add the default option
                this.elements.$providerType.append(Agenistrator.Template.render('settings-select-option', {
                    value: '',
                    text: agenistrator_settings.strings.select_provider_type,
                    selected: '',
                    disabled: ''
                }));

                // Add provider type options
                if (providerTypes && providerTypes.length) {
                    jQuery.each(providerTypes, function(_, typeId) {
                        this.elements.$providerType.append(Agenistrator.Template.render('settings-select-option', {
                            value: Agenistrator.Format.escapeHTMLChars(typeId),
                            text: Agenistrator.Format.escapeHTML(typeId),
                            selected: '',
                            disabled: ''
                        }));
                    }.bind(this));
                }
            }
        },

        /**
         * Populate provider list with configured instances.
         *
         * @since 1.0.0
         */
        populateProviderList: function() {
            var providerInstances = this.getProviderData().instances;

            // Make sure we have a valid provider list body element
            if (this.elements.$providerListBody && this.elements.$providerListBody.length) {
                // Clear existing list items
                this.elements.$providerListBody.empty();
            } else {
                Agenistrator.Log.logError(agenistrator_settings.strings.provider_list_body_not_found);
                return;
            }

            // Add provider list items
            if (providerInstances && typeof providerInstances === 'object' && Object.keys(providerInstances).length > 0) {
                // Loop through each provider instance
                jQuery.each(providerInstances, function(id, provider) {
                    // Get provider properties
                    var displayName = provider.display_name;
                    var typeId = provider.type;
                    var enabled = provider.enabled;

                    // Prepare status and toggle action
                    var statusClass = enabled ? 'enabled' : 'disabled';
                    var statusText = enabled ? agenistrator_settings.strings.enabled : agenistrator_settings.strings.disabled;
                    var toggleAction = Agenistrator.Template.render('settings-toggle-link', {
                        css_class: enabled ? 'disable-provider' : 'enable-provider',
                        provider_id: Agenistrator.Format.escapeHTMLChars(id),
                        text: enabled ? agenistrator_settings.strings.disable : agenistrator_settings.strings.enable
                    });

                    // Render the provider list item using the template system
                    var html = Agenistrator.Template.render('settings-provider-list-item', {
                        id: Agenistrator.Format.escapeHTMLChars(id),
                        display_name: Agenistrator.Format.escapeHTML(displayName),
                        type_id: Agenistrator.Format.escapeHTML(typeId),
                        status_class: statusClass,
                        status_text: statusText,
                        toggle_action: toggleAction,
                        edit_text: agenistrator_settings.strings.edit,
                        delete_text: agenistrator_settings.strings.delete
                    });

                    // Add the rendered HTML to the provider list body
                    this.elements.$providerListBody.append(html);
                }.bind(this));
            } else {
                // No providers configured - show empty message
                var emptyHtml = Agenistrator.Template.render('settings-empty-row', {
                    colspan: '4',
                    message: agenistrator_settings.strings.no_providers_configured
                });
                this.elements.$providerListBody.append(emptyHtml);
            }
        },

        // Show the provider form for adding/editing a provider
        /**
         * Show the provider form for adding or editing.
         *
         * @since 1.0.0
         */
        showProviderForm: function() {
            // Make sure the form container exists
            if (this.elements.$providerForm.length === 0) {
                // Render the provider form template
                var formHtml = Agenistrator.Template.render('settings-provider-form', {
                    form_title: agenistrator_settings.strings.form_title,
                    provider_name_label: agenistrator_settings.strings.provider_name_label,
                    provider_name_description: agenistrator_settings.strings.provider_name_description,
                    provider_type_label: agenistrator_settings.strings.provider_type_label,
                    provider_type_description: agenistrator_settings.strings.provider_type_description,
                    test_configuration_button: agenistrator_settings.strings.test_configuration_button,
                    save_provider_button: agenistrator_settings.strings.save_provider_button,
                    cancel_button: agenistrator_settings.strings.cancel_button
                });

                // Create the form container
                var containerHtml = Agenistrator.Template.render('settings-provider-form-container', {
                    content: formHtml
                });

                // Add the form to the DOM
                this.elements.$providerList.after(containerHtml);
                var $formContainer = jQuery('#provider-form');

                // Update the element reference
                this.elements.$providerForm = $formContainer;

                // Re-bind event handlers for the form elements - select only from within the form container
                this.elements.$providerFormTitle = $formContainer.find('#provider-form-title');
                this.elements.$providerDisplayName = $formContainer.find('#provider-display-name');
                this.elements.$providerType = $formContainer.find('#provider-type');
                this.elements.$providerId = $formContainer.find('#provider-id');
                this.elements.$providerTestStatus = $formContainer.find('#provider-test-status');
                this.elements.$providerParams = $formContainer.find('#provider-parameters');
                this.elements.$testProviderConfig = $formContainer.find('#test-provider-config');
                this.elements.$saveProvider = $formContainer.find('#save-provider');
                this.elements.$cancelProviderButton = $formContainer.find('#cancel-provider');

                // Re-bind events using the element references
                this.elements.$cancelProviderButton.on('click', jQuery.proxy(this.hideProviderForm, this));
                this.elements.$testProviderConfig.on('click', jQuery.proxy(this.testProviderConfig, this));
                this.elements.$saveProvider.on('click', jQuery.proxy(this.saveProvider, this));
                this.elements.$providerType.on('change', jQuery.proxy(function() {
                    this.loadProviderParameters(this.elements.$providerType.val());
                }, this));

                // Populate provider types dropdown
                this.populateProviderTypes();
            }

            // Reset form fields
            this.elements.$providerFormTitle.text(agenistrator_settings.strings.add_new_provider);
            this.elements.$providerDisplayName.val('');
            this.elements.$providerType.val('').trigger('change');
            this.elements.$providerId.val('');
            this.elements.$providerTestStatus.hide();

            this.elements.$providerList.hide();
            this.elements.$providerForm.show();
        },

        /**
         * Hide the provider form and show the list.
         *
         * @since 1.0.0
         */
        hideProviderForm: function() {
            // Remove the form from the DOM
            if (this.elements.$providerForm.length > 0) {
                this.elements.$providerForm.remove();

                // Clear all form-related element references
                this.elements.$providerForm = jQuery();
                this.elements.$providerFormTitle = jQuery();
                this.elements.$providerDisplayName = jQuery();
                this.elements.$providerType = jQuery();
                this.elements.$providerId = jQuery();
                this.elements.$providerTestStatus = jQuery();
                this.elements.$providerParams = jQuery();
                this.elements.$testProviderConfig = jQuery();
                this.elements.$saveProvider = jQuery();
                this.elements.$cancelProviderButton = jQuery();
            }

            // Show the provider list
            this.elements.$providerList.show();
        }
    };

    // Tools Manager - Handles the tools management interface
    Agenistrator.ToolsManager = {
        elements: {
            $toolList: jQuery('#tool-list-body'),
            $noItemsRow: jQuery('.no-items')
        },

        /**
         * Initialize tools manager.
         *
         * @since 1.0.0
         */
        init: function() {
            this.loadTools();
            this.bindEvents();
        },

        /**
         * Bind event handlers for tools management.
         *
         * @since 1.0.0
         */
        bindEvents: function() {
            var self = this;

            // Use event delegation for tool status update buttons since they're added dynamically
            jQuery(document).on('click', '.update-tool-status', function(e) {
                e.preventDefault();
                var toolId = jQuery(this).data('tool-id');
                var status = jQuery(this).data('status');
                self.updateToolStatus(toolId, status);
            });

            // Enable all tools button
            jQuery('#enable-all-tools').on('click', function(e) {
                e.preventDefault();
                self.enableAllTools();
            });
        },

        /**
         * Enable all tools.
         *
         * @since 1.0.0
         */
        enableAllTools: function() {
            var self = this;

            // Show confirmation dialog
            if (!confirm(agenistrator_settings.strings.confirm_enable_all_tools)) {
                return;
            }

            // Disable the button and show loading state
            var $button = jQuery('#enable-all-tools');
            $button.prop('disabled', true);
            $button.html(Agenistrator.Template.render('settings-spinner-button', {
                text: agenistrator_settings.strings.enabling_all_tools
            }));

            // Send request to enable all tools
            jQuery.ajax({
                url: ajaxurl,
                method: 'POST',
                data: {
                    action: 'agenistrator_enable_all_tools',
                    nonce: agenistrator.nonce
                },
                success: function(response) {
                    $button.prop('disabled', false);
                    $button.html(agenistrator_settings.strings.enable_all_tools);

                    if (response.success) {
                        // Reload the tools list
                        self.loadTools();
                    } else {
                        var errorMessage = Agenistrator.Template.replaceTags(
                            agenistrator_settings.strings.failed_to_enable_all_tools,
                            { error_details: (response.data && response.data.message ? response.data.message : agenistrator.strings.unknown_error) }
                        );
                        self.showError(errorMessage);
                    }
                },
                error: function() {
                    $button.prop('disabled', false);
                    $button.html(agenistrator_settings.strings.enable_all_tools);
                    self.showError(agenistrator_settings.strings.failed_to_enable_all_tools_generic);
                }
            });
        },

        /**
         * Load tools from the server.
         *
         * @since 1.0.0
         */
        loadTools: function() {
            var self = this;

            // Show loading state
            var loadingHtml = Agenistrator.Template.render('settings-loading-row', {
                colspan: '5',
                loading_text: agenistrator_settings.strings.please_wait
            });
            self.elements.$toolList.html(loadingHtml);

            // Fetch tools from the server
            jQuery.ajax({
                url: ajaxurl,
                method: 'POST',
                data: {
                    action: 'agenistrator_get_tools',
                    nonce: agenistrator.nonce
                },
                success: function(response) {
                    if (response.success && response.data.tools) {
                        self.renderTools(response.data.tools);
                    } else {
                        var errorMessage = Agenistrator.Template.replaceTags(
                            agenistrator_settings.strings.failed_to_load_tools,
                            { error_details: (response.data && response.data.message ? response.data.message : agenistrator.strings.unknown_error) }
                        );
                        self.showError(errorMessage);
                    }
                },
                error: function() {
                    self.showError(agenistrator_settings.strings.failed_to_load_tools_generic);
                }
            });
        },

        /**
         * Render tools list.
         *
         * @param {Array} tools - Array of tool objects.
         * @since 1.0.0
         */
        renderTools: function(tools) {
            var self = this;

            // Clear the list
            self.elements.$toolList.empty();

            if (tools.length === 0) {
                self.elements.$noItemsRow.show();
                return;
            }

            self.elements.$noItemsRow.hide();

            // Add each tool to the list
            tools.forEach(function(tool) {
                // Determine side effects display
                var sideEffectsClass = tool.is_read_only ? 'side-effects-read-only' : 'side-effects-read-write';
                var sideEffectsText = tool.is_read_only ?
                    agenistrator_settings.strings.tool_read_only :
                    agenistrator_settings.strings.tool_read_write;

                // Determine status display
                var statusClass = tool.enabled ? 'status-enabled' : 'status-disabled';
                var statusText = tool.enabled ?
                    agenistrator_settings.strings.enabled :
                    agenistrator_settings.strings.disabled;

                // Determine action button
                var actionButton;
                if (tool.is_always_enabled) {
                    actionButton = agenistrator_settings.strings.always_enabled;
                } else {
                    actionButton = Agenistrator.Template.render('settings-tool-action-button', {
                        button_class: tool.enabled ? '' : 'button-primary',
                        tool_id: Agenistrator.Format.escapeHTMLChars(tool.id),
                        status: tool.enabled ? 'disable' : 'enable',
                        text: tool.enabled ? agenistrator_settings.strings.disable : agenistrator_settings.strings.enable
                    });
                }

                // Render the tool row
                var rowHtml = Agenistrator.Template.render('tool-list-item', {
                    tool_name: Agenistrator.Format.escapeHTML(tool.name),
                    tool_description: Agenistrator.Format.escapeHTML(tool.description),
                    side_effects_class: sideEffectsClass,
                    side_effects_text: sideEffectsText,
                    status_class: statusClass,
                    status_text: statusText,
                    action_button: actionButton
                });

                self.elements.$toolList.append(rowHtml);
            });
        },

        /**
         * Update tool enabled status.
         *
         * @param {string} toolId - The tool ID.
         * @param {string} status - The new status (enable/disable).
         * @since 1.0.0
         */
        updateToolStatus: function(toolId, status) {
            var self = this;

            // Show loading state
            self.showActionLoading(toolId);

            // Send request to update the tool status
            jQuery.ajax({
                url: ajaxurl,
                method: 'POST',
                data: {
                    action: 'agenistrator_update_tool_status',
                    tool_id: toolId,
                    status: status,
                    nonce: agenistrator.nonce
                },
                success: function(response) {
                    if (response.success) {
                        // Reload the tools list
                        self.loadTools();
                    } else {
                        var actionString = status === 'enable' ? agenistrator_settings.strings.failed_to_enable_tool : agenistrator_settings.strings.failed_to_disable_tool;
                        var errorMessage = Agenistrator.Template.replaceTags(
                            actionString,
                            { error_details: (response.data && response.data.message ? response.data.message : agenistrator.strings.unknown_error) }
                        );
                        self.showError(errorMessage);
                        self.hideActionLoading(toolId);
                    }
                },
                error: function() {
                    var action = status === 'enable' ? agenistrator_settings.strings.failed_to_enable_tool_generic : agenistrator_settings.strings.failed_to_disable_tool_generic;
                    self.showError(action);
                    self.hideActionLoading(toolId);
                }
            });
        },

        /**
         * Show loading state for action button.
         *
         * @param {string} toolId - The tool ID.
         * @since 1.0.0
         */
        showActionLoading: function(toolId) {
            var $button = jQuery('button[data-tool-id="' + toolId + '"]');
            $button.prop('disabled', true);
            $button.html(Agenistrator.Template.render('settings-spinner-button', { text: '' }));
        },

        /**
         * Hide loading state for action button.
         *
         * @param {string} toolId - The tool ID.
         * @since 1.0.0
         */
        hideActionLoading: function(toolId) {
            var $button = jQuery('button[data-tool-id="' + toolId + '"]');
            $button.prop('disabled', false);

            var status = $button.data('status');
            $button.html(status === 'enable' ? agenistrator_settings.strings.enable : agenistrator_settings.strings.disable);
        },

        /**
         * Show error message.
         *
         * @param {string} message - The error message.
         * @since 1.0.0
         */
        showError: function(message) {
            Agenistrator.Log.logError(message);
        }
    };

    // Initialize the settings manager
    Agenistrator.SettingsManager.init();

    // Initialize provider manager
    Agenistrator.ProviderManager.init();

    // Initialize the tools manager
    Agenistrator.ToolsManager.init();
});
