Files
hack/tools/scripts/llm-key-hunter/results/_cache/content/bcardi0427_website-ai-assistant.json

1 line
180 KiB
JSON

{"repo": "bcardi0427/website-ai-assistant", "files": {"admin/class-admin-settings.php": {"59d3ed1856b1051742d52a42048659abc04a9399": {"t": 1785745767.3724012, "n": 50772, "h": "9a4b86061dd9a6a3", "c": "<?php\nnamespace Website_Ai_Assistant\\Admin;\n\nuse Website_Ai_Assistant\\Models\\OpenAI_Service;\nuse Website_Ai_Assistant\\Models\\Gemini_Service;\nuse Website_Ai_Assistant\\Models\\Deepseek_Service;\n\nclass Admin_Settings {\n private const OPTION_GROUP = 'waa_options';\n private const SETTINGS_PAGE = 'website-ai-assistant';\n private const TEST_PAGE = 'website-ai-assistant-test';\n\n public function __construct() {\n add_action('admin_menu', [$this, 'add_settings_page']);\n add_action('admin_init', [$this, 'register_settings']);\n add_action('admin_enqueue_scripts', [$this, 'enqueue_admin_assets']);\n add_action('wp_ajax_waa_fetch_models', [$this, 'handle_fetch_models']);\n add_action('wp_ajax_waa_update_model', [$this, 'handle_update_model']);\n\n // Log the AJAX actions setup\n waa_debug_log('Setting up AJAX actions');\n \n // Initialize admin settings values and log current settings\n add_action('admin_init', function() {\n $options = get_option('waa_options', []);\n waa_debug_log('Current admin settings:', [\n 'provider' => $options['ai_provider'] ?? 'not set',\n 'model' => $options[$options['ai_provider'] . '_model'] ?? 'not set',\n 'has_api_key' => !empty($options[$options['ai_provider'] . '_api_key']) ? 'yes' : 'no'\n ]);\n });\n }\n\n public function add_settings_page(): void {\n add_options_page(\n __('Website AI Assistant Settings', 'website-ai-assistant'),\n __('Website AI Assistant', 'website-ai-assistant'),\n 'manage_options',\n self::SETTINGS_PAGE,\n [$this, 'render_settings_page']\n );\n }\npublic function render_text_field($args): void {\n if (empty($args['field'])) {\n waa_debug_log(\"Error: Missing field name in render_text_field\", $args);\n return;\n }\n\n $options = get_option('waa_options', []);\n $field_name = $args['field'];\n $field_type = $args['type'] ?? 'text';\n $value = $options[$field_name] ?? $args['default'] ?? '';\n $class = $args['class'] ?? '';\n \n waa_debug_log(\"Rendering field: $field_name\", [\n 'type' => $field_type,\n 'value' => $value,\n 'class' => $class\n ]);\n \n ?>\n <div class=\"<?php echo esc_attr($class); ?>\">\n <?php if ($field_type === 'select'): ?>\n <select\n name=\"waa_options[<?php echo esc_attr($field_name); ?>]\"\n id=\"waa_options_<?php echo esc_attr($field_name); ?>\"\n class=\"regular-text\"\n <?php\n if (!empty($args['data'])) {\n foreach ($args['data'] as $key => $val) {\n echo ' data-' . esc_attr($key) . '=\"' . esc_attr($val) . '\"';\n }\n }\n ?>\n >\n <?php if (!empty($args['options'])): ?>\n <?php foreach ($args['options'] as $option_value => $option_label): ?>\n <option value=\"<?php echo esc_attr($option_value); ?>\" <?php selected($value, $option_value); ?>>\n <?php echo esc_html($option_label); ?>\n </option>\n <?php endforeach; ?>\n <?php endif; ?>\n </select>\n <?php else: ?>\n <input\n type=\"<?php echo esc_attr($field_type); ?>\"\n id=\"waa_options_<?php echo esc_attr($field_name); ?>\"\n name=\"waa_options[<?php echo esc_attr($field_name); ?>]\"\n value=\"<?php echo esc_attr($value); ?>\"\n class=\"regular-text\"\n />\n <?php endif; ?>\n <?php if (!empty($args['description'])): ?>\n <p class=\"description\"><?php echo esc_html($args['description']); ?></p>\n <?php endif; ?>\n </div>\n <?php\n}\n\npublic function render_textarea_field(array $args): void {\n $options = get_option('waa_options');\n $field = $args['field'];\n $value = $options[$field] ?? '';\n echo '<textarea name=\"waa_options[' . esc_attr($field) . ']\" class=\"large-text\" rows=\"4\">' . esc_textarea($value) . '</textarea>';\n if (!empty($args['description'])) {\n echo '<p class=\"description\">' . esc_html($args['description']) . '</p>';\n }\n}\n\npublic function render_select_field(array $args): void {\n $options = get_option('waa_options');\n $field = $args['field'];\n $value = $options[$field] ?? $args['default'] ?? '';\n $class = $args['class'] ?? '';\n \n // Build data attributes\n $data_attrs = '';\n if (!empty($args['data'])) {\n foreach ($args['data'] as $key => $val) {\n $data_attrs .= ' data-' . esc_attr($key) . '=\"' . esc_attr($val) . '\"';\n }\n }\n \n $id = $args['id'] ?? 'waa_options_' . esc_attr($field);\n \n echo '<select name=\"waa_options[' . esc_attr($field) . ']\" id=\"' . esc_attr($id) . '\" class=\"' . esc_attr($class) . '\"' . $data_attrs . '>';\n foreach ($args['options'] as $key => $label) {\n echo '<option value=\"' . esc_attr($key) . '\" ' . selected($value, $key, false) . '>';\n echo esc_html($label);\n echo '</option>';\n }\n echo '</select>';\n \n if (!empty($args['description'])) {\n echo '<p class=\"description\">' . esc_html($args['description']) . '</p>';\n }\n}\n\npublic function register_settings(): void {\n // Register the settings group\n register_setting(\n 'waa_options', // Option group\n 'waa_options', // Option name in the database\n ['sanitize_callback' => [$this, 'sanitize_options']]\n );\n\n // Register settings sections\n $this->register_ai_settings(); // AI provider and model settings\n $this->register_api_settings(); // API credentials for all providers\n $this->register_search_settings(); // Search configuration\n $this->register_display_settings(); // Display options\n $this->register_lead_settings(); // Lead generation settings\n $this->register_consent_settings(); // Consent settings\n\n // Log registered settings for debugging\n waa_debug_log('Settings registered with the following data:', [\n 'option_group' => 'waa_options',\n 'sections' => [\n 'ai_settings' => 'website-ai-assistant',\n 'api_credentials' => 'website-ai-assistant',\n 'search_settings' => 'website-ai-assistant',\n 'display_settings' => 'website-ai-assistant',\n 'lead_settings' => 'website-ai-assistant',\n 'consent_settings' => 'website-ai-assistant'\n ]\n ]);\n}\n\nprivate function register_lead_settings(): void {\n add_settings_section(\n 'waa_lead_settings',\n __('Lead Generation Settings', 'website-ai-assistant'),\n [$this, 'render_lead_section'],\n 'website-ai-assistant'\n );\n\n // Enable lead collection\n add_settings_field(\n 'enable_lead_collection',\n __('Enable Lead Collection', 'website-ai-assistant'),\n [$this, 'render_checkbox_field'],\n 'website-ai-assistant',\n 'waa_lead_settings',\n [\n 'field' => 'enable_lead_collection',\n 'description' => __('Show lead collection form in chat widget', 'website-ai-assistant')\n ]\n );\n\n // Lead collection timing\n add_settings_field(\n 'lead_collection_timing',\n __('When to Show Form', 'website-ai-assistant'),\n [$this, 'render_select_field'],\n 'website-ai-assistant',\n 'waa_lead_settings',\n [\n 'field' => 'lead_collection_timing',\n 'options' => [\n 'immediate' => __('Immediately', 'website-ai-assistant'),\n 'after_first' => __('After First Message', 'website-ai-assistant'),\n 'after_two' => __('After Two Messages', 'website-ai-assistant'),\n 'end' => __('After Three Messages', 'website-ai-assistant')\n ],\n 'default' => 'immediate',\n 'description' => __('Choose when to display the lead collection form', 'website-ai-assistant')\n ]\n );\n\n // Form heading\n add_settings_field(\n 'lead_collection_heading',\n __('Form Heading', 'website-ai-assistant'),\n [$this, 'render_text_field'],\n 'website-ai-assistant',\n 'waa_lead_settings',\n [\n 'field' => 'lead_collection_heading',\n 'type' => 'text',\n 'default' => __('Please share your contact info to continue', 'website-ai-assistant'),\n 'description' => __('Heading text displayed at the top of the form', 'website-ai-assistant')\n ]\n );\n\n // Form description\n add_settings_field(\n 'lead_collection_description',\n __('Form Description', 'website-ai-assistant'),\n [$this, 'render_text_field'],\n 'website-ai-assistant',\n 'waa_lead_settings',\n [\n 'field' => 'lead_collection_description',\n 'type' => 'text',\n 'description' => __('Optional description text below the heading', 'website-ai-assistant')\n ]\n );\n\n // FluentCRM List selector (populated dynamically)\n add_settings_field(\n 'fluentcrm_list_id',\n __('FluentCRM List', 'website-ai-assistant'),\n [$this, 'render_select_field'],\n 'website-ai-assistant',\n 'waa_lead_settings',\n [\n 'field' => 'fluentcrm_list_id',\n 'options' => $this->get_fluentcrm_lists(),\n 'description' => __('Select the FluentCRM list to add contacts to', 'website-ai-assistant')\n ]\n );\n\n // FluentCRM Tag selector (populated dynamically)\n add_settings_field(\n 'fluentcrm_tag_id',\n __('FluentCRM Tag', 'website-ai-assistant'),\n [$this, 'render_select_field'],\n 'website-ai-assistant',\n 'waa_lead_settings',\n [\n 'field' => 'fluentcrm_tag_id',\n 'options' => $this->get_fluentcrm_tags(),\n 'description' => __('Select the FluentCRM tag to apply to contacts', 'website-ai-assistant')\n ]\n );\n\n // Contact Status\n add_settings_field(\n 'fluentcrm_status',\n __('Contact Status', 'website-ai-assistant'),\n [$this, 'render_select_field'],\n 'website-ai-assistant',\n 'waa_lead_settings',\n [\n 'field' => 'fluentcrm_status',\n 'options' => [\n 'subscribed' => __('Subscribed', 'website-ai-assistant'),\n 'pending' => __('Pending', 'website-ai-assistant'),\n 'unsubscribed' => __('Unsubscribed', 'website-ai-assistant')\n ],\n 'default' => 'subscribed',\n 'description' => __('Select the default status for new contacts', 'website-ai-assistant')\n ]\n );\n}\n\npublic function render_lead_section(): void {\n echo '<p>' . esc_html__('Configure lead generation settings:', 'website-ai-assistant') . '</p>';\n echo '<ul class=\"waa-section-info\">';\n echo '<li>' . esc_html__('Enable/disable lead collection form', 'website-ai-assistant') . '</li>';\n echo '<li>' . esc_html__('Choose when to show the form (immediately, after first message, etc.)', 'website-ai-assistant') . '</li>';\n echo '<li>' . esc_html__('Customize form heading and description', 'website-ai-assistant') . '</li>';\n echo '<li>' . esc_html__('Connect to FluentCRM for lead storage (make sure FluentCRM is installed)', 'website-ai-assistant') . '</li>';\n echo '<li>' . esc_html__('Select FluentCRM list and tag for organizing contacts', 'website-ai-assistant') . '</li>';\n echo '</ul>';\n}\n\n\n private function register_ai_settings(): void {\n /* Original AI settings section\n add_settings_section(\n 'waa_ai_settings',\n __('AI Settings', 'website-ai-assistant'),\n [$this, 'render_ai_section'],\n 'website-ai-assistant'\n );\n\n // AI Provider selector\n add_settings_field(\n 'ai_provider',\n __('AI Provider', 'website-ai-assistant'),\n [$this, 'render_select_field'],\n 'website-ai-assistant',\n 'waa_ai_settings',\n [\n 'field' => 'ai_provider',\n 'options' => $this->get_ai_provider_options(),\n 'default' => 'gemini'\n ]\n );\n\n // AI Model selector\n add_settings_field(\n 'ai_model',\n __('AI Model', 'website-ai-assistant'),\n [$this, 'render_select_field'],\n 'website-ai-assistant',\n 'waa_ai_settings',\n [\n 'field' => 'ai_model',\n 'options' => []\n ]\n );\n\n // System Message\n add_settings_field(\n 'system_message',\n __('System Message', 'website-ai-assistant'),\n [$this, 'render_textarea_field'],\n 'website-ai-assistant',\n 'waa_ai_settings',\n ['field' => 'system_message']\n );\n */\n\n add_settings_section(\n 'waa_ai_settings',\n __('AI Settings', 'website-ai-assistant'),\n [$this, 'render_ai_section'],\n 'website-ai-assistant'\n );\n\n // AI Provider selector\n add_settings_field(\n 'ai_provider',\n __('AI Provider', 'website-ai-assistant'),\n [$this, 'render_select_field'],\n 'website-ai-assistant',\n 'waa_ai_settings',\n [\n 'field' => 'ai_provider',\n 'id' => 'waa_options_ai_provider',\n 'options' => $this->get_ai_provider_options(),\n 'default' => 'gemini',\n 'description' => __('Select your AI provider', 'website-ai-assistant')\n ]\n );\n\n // OpenAI Model Selector - populated dynamically via AJAX\n add_settings_field(\n 'openai_model',\n __('OpenAI Model', 'website-ai-assistant'),\n [$this, 'render_select_field'],\n 'website-ai-assistant',\n 'waa_ai_settings',\n [\n 'field' => 'openai_model',\n 'id' => 'waa_options_openai_model',\n 'class' => 'openai-field model-field',\n 'data' => [\n 'current-value' => get_option('waa_options')['openai_model'] ?? '',\n 'provider' => 'openai'\n ],\n 'options' => array_merge(\n ['' => __('Select OpenAI model', 'website-ai-assistant')],\n get_option('waa_openai_models', [])\n ),\n 'description' => __('Select OpenAI model', 'website-ai-assistant')\n ]\n );\n\n // Gemini Model Selector with predefined options\n add_settings_field(\n 'gemini_model',\n __('Gemini Model', 'website-ai-assistant'),\n [$this, 'render_select_field'],\n 'website-ai-assistant',\n 'waa_ai_settings',\n [\n 'field' => 'gemini_model',\n 'id' => 'waa_options_gemini_model',\n 'class' => 'gemini-field model-field',\n 'data' => [\n 'current-value' => get_option('waa_options')['gemini_model'] ?? '',\n 'provider' => 'gemini'\n ],\n 'options' => array_merge(\n ['' => __('Select Gemini model', 'website-ai-assistant')],\n \\Website_Ai_Assistant\\Models\\Gemini_Service::AVAILABLE_MODELS\n ),\n 'description' => __('Select a Gemini model to use', 'website-ai-assistant')\n ]\n );\n\n // Deepseek Model Selector - populated dynamically via AJAX\n add_settings_field(\n 'deepseek_model',\n __('Deepseek Model', 'website-ai-assistant'),\n [$this, 'render_select_field'],\n 'website-ai-assistant',\n 'waa_ai_settings',\n [\n 'field' => 'deepseek_model',\n 'id' => 'waa_options_deepseek_model',\n 'class' => 'deepseek-field model-field',\n 'data' => [\n 'current-value' => get_option('waa_options')['deepseek_model'] ?? '',\n 'provider' => 'deepseek'\n ],\n 'options' => array_merge(\n ['' => __('Select Deepseek model', 'website-ai-assistant')],\n get_option('waa_deepseek_models', [])\n ),\n 'description' => __('Select Deepseek model', 'website-ai-assistant')\n ]\n );\n\n add_settings_field(\n 'system_message',\n __('System Message', 'website-ai-assistant'),\n [$this, 'render_textarea_field'],\n 'website-ai-assistant',\n 'waa_ai_settings',\n [\n 'field' => 'system_message',\n 'description' => __('This message sets the AI\\'s behavior and tone. Leave blank for default.', 'website-ai-assistant')\n ]\n );\n }\n\n private function register_api_settings(): void {\n // API Credentials Section\n add_settings_section(\n 'api_credentials',\n __('API Credentials', 'website-ai-assistant'),\n [$this, 'render_api_section'],\n self::SETTINGS_PAGE\n );\n\n // OpenAI Credentials\n add_settings_field(\n 'openai_api_key',\n __('OpenAI API Key', 'website-ai-assistant'),\n [$this, 'render_text_field'],\n 'website-ai-assistant',\n 'api_credentials',\n [\n 'field' => 'openai_api_key',\n 'type' => 'password',\n 'class' => 'openai-field waa-api-key-field',\n 'description' => __('Enter your API key from OpenAI dashboard', 'website-ai-assistant')\n ]\n );\n\n // OpenAI Cache Control\n add_settings_field(\n 'openai_disable_cache',\n __('Model Cache', 'website-ai-assistant'),\n [$this, 'render_checkbox_field'],\n 'website-ai-assistant',\n 'api_credentials',\n [\n 'field' => 'openai_disable_cache',\n 'class' => 'openai-field',\n 'description' => __('Disable caching to fetch fresh model list from OpenAI API each time', 'website-ai-assistant')\n ]\n );\n\n // Deepseek API Key\n add_settings_field(\n 'deepseek_api_key',\n __('Deepseek API Key', 'website-ai-assistant'),\n [$this, 'render_text_field'],\n 'website-ai-assistant',\n 'api_credentials',\n [\n 'field' => 'deepseek_api_key',\n 'type' => 'password',\n 'class' => 'deepseek-field waa-api-key-field',\n 'description' => __('Enter your API key from Deepseek dashboard', 'website-ai-assistant')\n ]\n );\n\n // Deepseek API Endpoint\n add_settings_field(\n 'deepseek_endpoint',\n __('Deepseek Endpoint', 'website-ai-assistant'),\n [$this, 'render_text_field'],\n 'website-ai-assistant',\n 'api_credentials',\n [\n 'field' => 'deepseek_endpoint',\n 'type' => 'text',\n 'class' => 'deepseek-field waa-api-key-field',\n 'default' => 'https://api.deepseek.com/v1/',\n 'description' => __('API endpoint for Deepseek service (default: https://api.deepseek.com/v1/)', 'website-ai-assistant')\n ]\n );\n\n // Gemini API Key\n add_settings_field(\n 'gemini_api_key',\n __('Gemini API Key', 'website-ai-assistant'),\n [$this, 'render_text_field'],\n 'website-ai-assistant',\n 'api_credentials',\n [\n 'field' => 'gemini_api_key',\n 'type' => 'password',\n 'class' => 'waa-api-key-field',\n 'description' => __('Enter your API key from Google AI Studio', 'website-ai-assistant')\n ]\n );\n\n // Keep existing fields commented for reference\n /* Original Gemini field\n add_settings_field(\n 'gemini_api_key',\n __('Gemini API Key', 'website-ai-assistant'),\n [$this, 'render_text_field'],\n 'waa_api_credentials',\n 'waa_api_credentials',\n [\n 'field' => 'gemini_api_key',\n 'type' => 'password',\n 'class' => 'gemini-field waa-api-key-field'\n ]\n );\n */\n\n }\n\n private function register_search_settings(): void {\n // Search Settings Section\n add_settings_section(\n 'waa_search_settings',\n __('Search Settings', 'website-ai-assistant'),\n [$this, 'render_search_section'],\n 'website-ai-assistant'\n );\n\n // Define all search fields\n $search_fields = [\n // Search Provider\n [\n 'id' => 'search_provider',\n 'title' => __('Search Provider', 'website-ai-assistant'),\n 'callback' => 'render_select_field',\n 'args' => [\n 'field' => 'search_provider',\n 'options' => [\n 'google' => __('Google Custom Search', 'website-ai-assistant'),\n 'algolia' => __('Algolia', 'website-ai-assistant')\n ],\n 'default' => 'google',\n 'description' => __('Select your preferred search provider', 'website-ai-assistant')\n ]\n ],\n // Google Search Settings\n [\n 'id' => 'google_search_api_key',\n 'title' => __('Google Search API Key', 'website-ai-assistant'),\n 'callback' => 'render_text_field',\n 'args' => [\n 'field' => 'google_search_api_key',\n 'type' => 'password',\n 'class' => 'google-search-field waa-api-key-field',\n 'description' => __('Enter your Google Custom Search API Key', 'website-ai-assistant')\n ]\n ],\n [\n 'id' => 'search_engine_id',\n 'title' => __('Google Search Engine ID', 'website-ai-assistant'),\n 'callback' => 'render_text_field',\n 'args' => [\n 'field' => 'search_engine_id',\n 'type' => 'text',\n 'class' => 'google-search-field waa-api-key-field',\n 'description' => __('Enter your Google Custom Search Engine ID', 'website-ai-assistant')\n ]\n ],\n // Algolia Settings\n [\n 'id' => 'algolia_app_id',\n 'title' => __('Algolia Application ID', 'website-ai-assistant'),\n 'callback' => 'render_text_field',\n 'args' => [\n 'field' => 'algolia_app_id',\n 'type' => 'text',\n 'class' => 'algolia-field waa-api-key-field',\n 'description' => __('Enter your Algolia Application ID', 'website-ai-assistant')\n ]\n ],\n [\n 'id' => 'algolia_search_key',\n 'title' => __('Algolia Search API Key', 'website-ai-assistant'),\n 'callback' => 'render_text_field',\n 'args' => [\n 'field' => 'algolia_search_key',\n 'type' => 'password',\n 'class' => 'algolia-field waa-api-key-field',\n 'description' => __('Enter your Algolia Search-Only API Key', 'website-ai-assistant')\n ]\n ],\n [\n 'id' => 'algolia_admin_key',\n 'title' => __('Algolia Admin API Key', 'website-ai-assistant'),\n 'callback' => 'render_text_field',\n 'args' => [\n 'field' => 'algolia_admin_key',\n 'type' => 'password',\n 'class' => 'algolia-field waa-api-key-field',\n 'description' => __('Enter your Algolia Admin API Key', 'website-ai-assistant')\n ]\n ],\n [\n 'id' => 'algolia_index',\n 'title' => __('Algolia Index Name', 'website-ai-assistant'),\n 'callback' => 'render_text_field',\n 'args' => [\n 'field' => 'algolia_index',\n 'type' => 'text',\n 'class' => 'algolia-field waa-api-key-field',\n 'description' => __('Enter your Algolia Index Name (e.g., website_contentsearchable_posts)', 'website-ai-assistant')\n ]\n ]\n ];\n\n // Register all search fields\n foreach ($search_fields as $field) {\n add_settings_field(\n $field['id'],\n $field['title'],\n [$this, $field['callback']],\n 'website-ai-assistant',\n 'waa_search_settings',\n $field['args']\n );\n }\n }\n\n private function register_display_settings(): void {\n add_settings_section(\n 'waa_display_settings',\n __('Display Settings', 'website-ai-assistant'),\n [$this, 'render_display_section'],\n 'website-ai-assistant'\n );\n\n add_settings_field(\n 'display_locations',\n __('Show Chat Widget On', 'website-ai-assistant'),\n [$this, 'render_display_locations_field'],\n 'website-ai-assistant',\n 'waa_display_settings'\n );\n\n add_settings_field(\n 'enable_debug',\n __('Enable Debug Logging', 'website-ai-assistant'),\n [$this, 'render_checkbox_field'],\n 'website-ai-assistant',\n 'waa_display_settings',\n [\n 'field' => 'enable_debug',\n 'description' => __('Log debug information', 'website-ai-assistant')\n ]\n );\n }\n\n private function register_consent_settings(): void {\n add_settings_section(\n 'waa_consent_settings',\n __('Consent Settings', 'website-ai-assistant'),\n [$this, 'render_consent_section'],\n 'website-ai-assistant'\n );\n\n // Enable consent checkbox\n add_settings_field(\n 'enable_consent',\n __('Enable Consent Request', 'website-ai-assistant'),\n [$this, 'render_checkbox_field'],\n 'website-ai-assistant',\n 'waa_consent_settings',\n [\n 'field' => 'enable_consent',\n 'description' => __('Requires users to accept the consent message before starting a chat.', 'website-ai-assistant')\n ]\n );\n\n // Consent Message textarea\n add_settings_field(\n 'consent_message',\n __('Consent Message', 'website-ai-assistant'),\n [$this, 'render_textarea_field'],\n 'website-ai-assistant',\n 'waa_consent_settings',\n [\n 'field' => 'consent_message',\n 'description' => __('The text shown to the user requesting consent.', 'website-ai-assistant')\n ]\n );\n }\n\n public function render_consent_section(): void {\n echo '<p>' . esc_html__('Configure chatbot consent settings below:', 'website-ai-assistant') . '</p>';\n }\n\n private function get_ai_provider_options(): array {\n return [\n 'gemini' => __('Google Gemini AI', 'website-ai-assistant'),\n 'openai' => __('OpenAI', 'website-ai-assistant'),\n 'deepseek' => __('Deepseek', 'website-ai-assistant')\n ];\n }\n\n private function get_fluentcrm_lists(): array {\n if (!function_exists('FluentCrmApi')) {\n return ['' => __('FluentCRM not installed', 'website-ai-assistant')];\n }\n\n try {\n $listApi = FluentCrmApi('lists');\n if (!$listApi) {\n return ['' => __('FluentCRM API not available', 'website-ai-assistant')];\n }\n\n $lists = $listApi->all();\n if (empty($lists)) {\n return ['' => __('No lists found', 'website-ai-assistant')];\n }\n\n $options = ['' => __('Select a list', 'website-ai-assistant')];\n foreach ($lists as $list) {\n $options[$list->id] = esc_html($list->title);\n }\n return $options;\n } catch (\\Exception $e) {\n error_log('Website AI Assistant Error: ' . $e->getMessage());\n return ['' => __('Error loading lists', 'website-ai-assistant')];\n }\n }\n\n private function get_fluentcrm_tags(): array {\n if (!function_exists('FluentCrmApi')) {\n return ['' => __('FluentCRM not installed', 'website-ai-assistant')];\n }\n\n try {\n $tagApi = FluentCrmApi('tags');\n if (!$tagApi) {\n return ['' => __('FluentCRM API not available', 'website-ai-assistant')];\n }\n\n $tags = $tagApi->all();\n if (empty($tags)) {\n return ['' => __('No tags found', 'website-ai-assistant')];\n }\n\n $options = ['' => __('Select a tag', 'website-ai-assistant')];\n foreach ($tags as $tag) {\n $options[$tag->id] = esc_html($tag->title);\n }\n return $options;\n } catch (\\Exception $e) {\n error_log('Website AI Assistant Error: ' . $e->getMessage());\n return ['' => __('Error loading tags', 'website-ai-assistant')];\n }\n }\n\n public function render_settings_page(): void {\n if (!current_user_can('manage_options')) {\n return;\n }\n require_once WAA_PLUGIN_DIR . 'admin/views/settings-page.php';\n }\n\n public function render_ai_section(): void {\n echo '<p>' . esc_html__('Configure your AI settings below:', 'website-ai-assistant') . '</p>';\n echo '<ul class=\"waa-section-info\">';\n echo '<li>' . esc_html__('Select your preferred AI provider', 'website-ai-assistant') . '</li>';\n echo '<li>' . esc_html__('Enter the required API credentials', 'website-ai-assistant') . '</li>';\n echo '<li>' . esc_html__('Choose the model you want to use', 'website-ai-assistant') . '</li>';\n echo '</ul>';\n }\n\n public function render_api_section(): void {\n echo '<p>' . esc_html__('API Credentials:', 'website-ai-assistant') . '</p>';\n echo '<ul class=\"waa-section-info\">';\n echo '<li>' . esc_html__('Gemini: Get your API key from Google AI Studio', 'website-ai-assistant') . '</li>';\n echo '<li>' . esc_html__('OpenAI: Get your API key from OpenAI dashboard', 'website-ai-assistant') . '</li>';\n echo '<li>' . esc_html__('Deepseek: Get your API key from Deepseek platform', 'website-ai-assistant') . '</li>';\n echo '</ul>';\n }\n\n public function render_search_section(): void {\n echo '<p>' . esc_html__('Search Provider Settings:', 'website-ai-assistant') . '</p>';\n echo '<ul class=\"waa-section-info\">';\n echo '<li>' . esc_html__('Google: Custom Search requires API key and Engine ID', 'website-ai-assistant') . '</li>';\n echo '<li>' . esc_html__('Algolia: Uses existing WordPress Algolia plugin settings', 'website-ai-assistant') . '</li>';\n echo '</ul>';\n }\n\n public function render_display_section(): void {\n echo '<p>' . esc_html__('Configure where the chat widget should appear.', 'website-ai-assistant') . '</p>';\n }\n\n\n /* Commented out duplicate method - preserved for reference\n public function render_textarea_field(array $args): void {\n $options = get_option('waa_options');\n $field = $args['field'];\n $value = $options[$field] ?? '';\n echo '<textarea name=\"waa_options[' . esc_attr($field) . ']\" class=\"large-text\" rows=\"4\">' . esc_textarea($value) . '</textarea>';\n if (!empty($args['description'])) {\n echo '<p class=\"description\">' . esc_html($args['description']) . '</p>';\n }\n }\n */\n\n public function handle_fetch_models(): void {\n error_log('Starting handle_fetch_models...');\n check_ajax_referer('waa_admin_nonce', 'nonce');\n \n if (!current_user_can('manage_options')) {\n error_log('Unauthorized access attempt in handle_fetch_models');\n wp_send_json_error(['message' => __('Unauthorized access', 'website-ai-assistant')]);\n return;\n }\n \n $provider = sanitize_text_field($_POST['provider'] ?? '');\n $api_key = sanitize_text_field($_POST['api_key'] ?? '');\n waa_debug_log('handle_fetch_models called', [\n 'provider' => $provider,\n 'has_api_key' => !empty($api_key),\n 'api_key_length' => strlen($api_key),\n 'post_data' => $_POST,\n 'request_method' => $_SERVER['REQUEST_METHOD']\n ]);\n \n $models = [];\n \n switch ($provider) {\n case 'gemini':\n $models = \\Website_Ai_Assistant\\Models\\Gemini_Service::AVAILABLE_MODELS;\n update_option('waa_gemini_models', $models);\n waa_debug_log('Using static Gemini models');\n break;\n case 'openai':\n try {\n $api_key = sanitize_text_field($_POST['api_key'] ?? '');\n waa_debug_log('OpenAI: Processing model fetch request');\n \n waa_debug_log('OpenAI: Processing fetch models request', [\n 'has_api_key' => !empty($api_key),\n 'api_key_length' => strlen($api_key),\n 'api_key_preview' => substr($api_key, 0, 10) . '...'\n ]);\n\n // Check for cached models first\n $cached_models = get_option('waa_openai_models', []);\n $cached_key_hash = get_option('waa_openai_key_hash', '');\n $current_key_hash = md5($api_key);\n \n // Use cached models if available and key matches\n if (!empty($cached_models) && $cached_key_hash === $current_key_hash) {\n $models = $cached_models;\n waa_debug_log('OpenAI: Using cached models');\n break;\n }\n \n if (empty($api_key)) {\n throw new \\Exception(__('API key is required', 'website-ai-assistant'));\n }\n \n // If no cache hit, determine whether to use cache for fetching\n $options = get_option('waa_options', []);\n $force_refresh = isset($_POST['force_refresh']) && $_POST['force_refresh'] === 'true';\n $use_cache = !$force_refresh && empty($options['openai_disable_cache']);\n\n waa_debug_log('OpenAI: Cache Settings:', [\n 'use_cache' => $use_cache,\n 'force_refresh' => $force_refresh ? 'yes' : 'no',\n 'disable_cache_setting' => !empty($options['openai_disable_cache']) ? 'yes' : 'no'\n ]);\n \n if ($use_cache) {\n $cached_models = get_option('waa_openai_models', []);\n $cached_key_hash = get_option('waa_openai_key_hash', '');\n $current_key_hash = md5($api_key);\n\n waa_debug_log('OpenAI: Cache status', [\n 'has_cached_models' => !empty($cached_models),\n 'models_count' => count($cached_models),\n 'cache_key_match' => $cached_key_hash === $current_key_hash,\n 'current_key_hash' => $current_key_hash\n ]);\n\n // Use cached models if available and key matches\n if ($cached_models && $cached_key_hash === $current_key_hash) {\n $models = $cached_models;\n waa_debug_log('OpenAI: Using cached models');\n break;\n }\n }\n \n // If we get here, either cache is disabled or we need fresh models\n waa_debug_log('OpenAI: Fetching fresh models from API');\n $openai_service = new OpenAI_Service($api_key);\n $models = $openai_service->get_available_models();\n \n // Cache the models unless this was a forced refresh\n if (!$force_refresh && !empty($models)) {\n update_option('waa_openai_models', $models);\n update_option('waa_openai_key_hash', md5($api_key));\n waa_debug_log('OpenAI: Cached new models');\n }\n\n // Set default model if none selected\n if (!empty($models)) {\n $options = get_option('waa_options', []);\n if (empty($options['openai_model'])) {\n $first_model = array_key_first($models);\n $options['openai_model'] = $first_model;\n update_option('waa_options', $options);\n waa_debug_log('OpenAI: Set default model:', $first_model);\n }\n }\n } catch (\\Exception $e) {\n wp_send_json_error(['message' => $e->getMessage()]);\n return;\n }\n break;\n case 'deepseek':\n // Check for cached models first\n $cached_models = get_option('waa_deepseek_models', []);\n $cached_key_hash = get_option('waa_deepseek_key_hash', '');\n $api_key = sanitize_text_field($_POST['api_key'] ?? '');\n $current_key_hash = md5($api_key);\n\n // Use cached models if available and key matches\n if (!empty($cached_models) && $cached_key_hash === $current_key_hash) {\n $models = $cached_models;\n waa_debug_log('Deepseek: Using cached models');\n break;\n }\n\n // If no cache hit, validate API key and fetch models\n if (empty($api_key)) {\n throw new \\Exception(__('API key is required', 'website-ai-assistant'));\n }\n\n try {\n $deepseek_service = new Deepseek_Service($api_key, Deepseek_Service::API_ENDPOINT);\n $models = $deepseek_service->get_available_models();\n \n // Cache the models and API key hash\n update_option('waa_deepseek_models', $models);\n update_option('waa_deepseek_key_hash', $current_key_hash);\n waa_debug_log('Deepseek: Cached new models');\n } catch (\\Exception $e) {\n wp_send_json_error(['message' => $e->getMessage()]);\n return;\n }\n break;\n default:\n wp_send_json_error(['message' => __('Invalid provider', 'website-ai-assistant')]);\n return;\n }\n \n wp_send_json_success(['models' => $models]);\n }\n\n /* Commented out duplicate method - preserved for reference\n public function render_select_field(array $args): void {\n $options = get_option('waa_options');\n $field = $args['field'];\n $value = $options[$field] ?? $args['default'] ?? '';\n \n echo '<select name=\"waa_options[' . esc_attr($field) . ']\" id=\"waa_options_' . esc_attr($field) . '\">';\n foreach ($args['options'] as $key => $label) {\n echo '<option value=\"' . esc_attr($key) . '\" ' . selected($value, $key, false) . '>';\n echo esc_html($label);\n echo '</option>';\n }\n echo '</select>';\n \n if (!empty($args['description'])) {\n echo '<p class=\"description\">' . esc_html($args['description']) . '</p>';\n }\n }\n */\n\n public function render_checkbox_field(array $args): void {\n $options = get_option('waa_options');\n $field = $args['field'];\n $checked = isset($options[$field]) && $options[$field] ? 'checked' : '';\n \n echo '<input type=\"checkbox\" name=\"waa_options[' . esc_attr($field) . ']\" ' . $checked . ' value=\"1\">';\n if (!empty($args['description'])) {\n echo '<p class=\"description\">' . esc_html($args['description']) . '</p>';\n }\n }\n\n public function render_display_locations_field(): void {\n $options = get_option('waa_options', []);\n $locations = $options['display_locations'] ?? ['all'];\n ?>\n <fieldset>\n <label>\n <input type=\"checkbox\" name=\"waa_options[display_locations][]\"\n value=\"all\" <?php checked(in_array('all', $locations)); ?>>\n <?php esc_html_e('All Pages', 'website-ai-assistant'); ?>\n </label><br>\n <label>\n <input type=\"checkbox\" name=\"waa_options[display_locations][]\"\n value=\"home\" <?php checked(in_array('home', $locations)); ?>>\n <?php esc_html_e('Home Page', 'website-ai-assistant'); ?>\n </label><br>\n <label>\n <input type=\"checkbox\" name=\"waa_options[display_locations][]\"\n value=\"posts\" <?php checked(in_array('posts', $locations)); ?>>\n <?php esc_html_e('Blog Posts', 'website-ai-assistant'); ?>\n </label><br>\n <label>\n <input type=\"checkbox\" name=\"waa_options[display_locations][]\"\n value=\"pages\" <?php checked(in_array('pages', $locations)); ?>>\n <?php esc_html_e('Pages', 'website-ai-assistant'); ?>\n </label><br>\n <label>\n <input type=\"checkbox\" name=\"waa_options[display_locations][]\"\n value=\"products\" <?php checked(in_array('products', $locations)); ?>>\n <?php esc_html_e('Products', 'website-ai-assistant'); ?>\n </label>\n </fieldset>\n <?php\n }\n\n public function enqueue_admin_assets($hook): void {\n // Only load on our settings page\n if ('settings_page_website-ai-assistant' !== $hook) {\n return;\n }\n\n wp_enqueue_style(\n 'waa-admin-styles',\n WAA_PLUGIN_URL . 'admin/css/admin-settings.css',\n [],\n WAA_VERSION\n );\n\n wp_enqueue_script(\n 'waa-admin-scripts',\n WAA_PLUGIN_URL . 'admin/js/admin-settings.js',\n ['jquery'],\n WAA_VERSION,\n true\n );\n\n wp_localize_script('waa-admin-scripts', 'waaAdmin', [\n 'ajaxUrl' => admin_url('admin-ajax.php'),\n 'nonce' => wp_create_nonce('waa_admin_nonce'),\n 'i18n' => [\n 'loadingModels' => __('Loading available models...', 'website-ai-assistant'),\n 'enterApiKey' => __('Please enter API key first', 'website-ai-assistant'),\n 'selectModel' => __('Select a model', 'website-ai-assistant'),\n 'fetchError' => __('Failed to fetch models', 'website-ai-assistant'),\n 'noModelsFound' => __('No available models found', 'website-ai-assistant'),\n 'fetchingModels' => __('Fetching available models...', 'website-ai-assistant')\n ]\n ]);\n }\n\n public function sanitize_options($input): array {\n waa_debug_log('Sanitizing input options:', [\n 'ai_provider' => $input['ai_provider'] ?? 'not set',\n 'search_provider' => $input['search_provider'] ?? 'not set',\n 'fields_present' => array_keys($input)\n ]);\n\n // Get existing options to preserve any values not in current input\n $existing = get_option('waa_options', []);\n $sanitized = $existing;\n\n // Handle search provider changes\n if (isset($input['search_provider'])) {\n $search_provider = sanitize_text_field($input['search_provider']);\n if (in_array($search_provider, ['google', 'algolia'])) {\n $old_provider = $existing['search_provider'] ?? 'google';\n $sanitized['search_provider'] = $search_provider;\n \n waa_debug_log('Search provider updated:', [\n 'from' => $old_provider,\n 'to' => $search_provider\n ]);\n\n // Only clear settings if they're explicitly empty in the input\n if ($search_provider === 'google') {\n // When switching to Google, preserve existing Algolia settings\n $sanitized['google_search_api_key'] = $input['google_search_api_key'] ?? $existing['google_search_api_key'] ?? '';\n $sanitized['search_engine_id'] = $input['search_engine_id'] ?? $existing['search_engine_id'] ?? '';\n } else if ($search_provider === 'algolia') {\n // When switching to Algolia, preserve existing Google settings\n $sanitized['algolia_app_id'] = $input['algolia_app_id'] ?? $existing['algolia_app_id'] ?? '';\n $sanitized['algolia_search_key'] = $input['algolia_search_key'] ?? $existing['algolia_search_key'] ?? '';\n $sanitized['algolia_admin_key'] = $input['algolia_admin_key'] ?? $existing['algolia_admin_key'] ?? '';\n $sanitized['algolia_index'] = $input['algolia_index'] ?? $existing['algolia_index'] ?? '';\n }\n \n waa_debug_log('Settings after provider change:', [\n 'provider' => $search_provider,\n 'has_google_key' => isset($sanitized['google_search_api_key']),\n 'has_algolia_key' => isset($sanitized['algolia_search_key'])\n ]);\n }\n }\n \n $field_types = [\n 'url' => ['deepseek_endpoint'],\n 'key' => [\n 'gemini_api_key', 'openai_api_key', 'deepseek_api_key',\n 'google_search_api_key', 'search_engine_id',\n 'algolia_app_id', 'algolia_search_key', 'algolia_admin_key'\n ],\n 'text' => ['algolia_index']\n ];\n\n // Process each field type\n foreach ($field_types as $type => $fields) {\n foreach ($fields as $field) {\n if (!isset($input[$field])) continue;\n\n switch ($type) {\n case 'url':\n $sanitized[$field] = esc_url_raw(rtrim($input[$field], '/') . '/');\n break;\n case 'key':\n case 'text':\n $sanitized[$field] = sanitize_text_field($input[$field]);\n if ($type === 'text') {\n waa_debug_log(\"Sanitizing text field: $field\", [\n 'input_value' => $input[$field],\n 'sanitized_value' => $sanitized[$field]\n ]);\n }\n break;\n }\n }\n }\n\n // Provider and model fields\n $provider_model_fields = [\n 'ai_provider',\n 'openai_model',\n 'gemini_model',\n 'deepseek_model',\n 'search_provider',\n 'system_message'\n ];\n\n foreach ($provider_model_fields as $field) {\n if (isset($input[$field])) {\n $sanitized[$field] = sanitize_text_field($input[$field]);\n waa_debug_log(\"Sanitized $field:\", $sanitized[$field]);\n } else {\n waa_debug_log(\"Field not found in input: $field\");\n $sanitized[$field] = '';\n }\n }\n\n // Add special handling for provider-specific model fields\n $provider = $sanitized['ai_provider'] ?? '';\n if ($provider) {\n $model_field = $provider . '_model';\n waa_debug_log(\"Checking provider-specific model field: $model_field\", [\n 'value' => $sanitized[$model_field] ?? 'not set',\n 'provider' => $provider\n ]);\n }\n\n // Handle display locations array\n if (isset($input['display_locations']) && is_array($input['display_locations'])) {\n $sanitized['display_locations'] = array_map('sanitize_text_field', $input['display_locations']);\n } else {\n $sanitized['display_locations'] = ['all']; // Default to all pages if not set\n }\n\n // Handle debug option\n $sanitized['enable_debug'] = isset($input['enable_debug']) ? 1 : 0;\n\n // Sanitize lead generation fields\n $lead_fields = [\n 'enable_lead_collection' => 'bool',\n 'lead_collection_timing' => 'text',\n 'lead_collection_heading' => 'text',\n 'lead_collection_description' => 'text',\n 'fluentcrm_list_id' => 'int',\n 'fluentcrm_tag_id' => 'int',\n 'fluentcrm_status' => 'text'\n ];\n\n foreach ($lead_fields as $field => $type) {\n if (isset($input[$field])) {\n switch ($type) {\n case 'bool':\n $sanitized[$field] = (bool) $input[$field];\n break;\n case 'int':\n $sanitized[$field] = absint($input[$field]);\n break;\n case 'text':\n $sanitized[$field] = sanitize_text_field($input[$field]);\n break;\n }\n }\n }\n\n // Sanitize consent settings\n $sanitized['enable_consent'] = isset($input['enable_consent']) ? 1 : 0;\n $sanitized['consent_message'] = isset($input['consent_message']) ? sanitize_textarea_field($input['consent_message']) : '';\n\n return $sanitized;\n }\n\n}\n"}, "424bfbab1d94a7b7783b5bb6012f882c30a08c45": {"t": 1785756317.915637, "n": 50772, "h": "9a4b86061dd9a6a3", "c": "<?php\nnamespace Website_Ai_Assistant\\Admin;\n\nuse Website_Ai_Assistant\\Models\\OpenAI_Service;\nuse Website_Ai_Assistant\\Models\\Gemini_Service;\nuse Website_Ai_Assistant\\Models\\Deepseek_Service;\n\nclass Admin_Settings {\n private const OPTION_GROUP = 'waa_options';\n private const SETTINGS_PAGE = 'website-ai-assistant';\n private const TEST_PAGE = 'website-ai-assistant-test';\n\n public function __construct() {\n add_action('admin_menu', [$this, 'add_settings_page']);\n add_action('admin_init', [$this, 'register_settings']);\n add_action('admin_enqueue_scripts', [$this, 'enqueue_admin_assets']);\n add_action('wp_ajax_waa_fetch_models', [$this, 'handle_fetch_models']);\n add_action('wp_ajax_waa_update_model', [$this, 'handle_update_model']);\n\n // Log the AJAX actions setup\n waa_debug_log('Setting up AJAX actions');\n \n // Initialize admin settings values and log current settings\n add_action('admin_init', function() {\n $options = get_option('waa_options', []);\n waa_debug_log('Current admin settings:', [\n 'provider' => $options['ai_provider'] ?? 'not set',\n 'model' => $options[$options['ai_provider'] . '_model'] ?? 'not set',\n 'has_api_key' => !empty($options[$options['ai_provider'] . '_api_key']) ? 'yes' : 'no'\n ]);\n });\n }\n\n public function add_settings_page(): void {\n add_options_page(\n __('Website AI Assistant Settings', 'website-ai-assistant'),\n __('Website AI Assistant', 'website-ai-assistant'),\n 'manage_options',\n self::SETTINGS_PAGE,\n [$this, 'render_settings_page']\n );\n }\npublic function render_text_field($args): void {\n if (empty($args['field'])) {\n waa_debug_log(\"Error: Missing field name in render_text_field\", $args);\n return;\n }\n\n $options = get_option('waa_options', []);\n $field_name = $args['field'];\n $field_type = $args['type'] ?? 'text';\n $value = $options[$field_name] ?? $args['default'] ?? '';\n $class = $args['class'] ?? '';\n \n waa_debug_log(\"Rendering field: $field_name\", [\n 'type' => $field_type,\n 'value' => $value,\n 'class' => $class\n ]);\n \n ?>\n <div class=\"<?php echo esc_attr($class); ?>\">\n <?php if ($field_type === 'select'): ?>\n <select\n name=\"waa_options[<?php echo esc_attr($field_name); ?>]\"\n id=\"waa_options_<?php echo esc_attr($field_name); ?>\"\n class=\"regular-text\"\n <?php\n if (!empty($args['data'])) {\n foreach ($args['data'] as $key => $val) {\n echo ' data-' . esc_attr($key) . '=\"' . esc_attr($val) . '\"';\n }\n }\n ?>\n >\n <?php if (!empty($args['options'])): ?>\n <?php foreach ($args['options'] as $option_value => $option_label): ?>\n <option value=\"<?php echo esc_attr($option_value); ?>\" <?php selected($value, $option_value); ?>>\n <?php echo esc_html($option_label); ?>\n </option>\n <?php endforeach; ?>\n <?php endif; ?>\n </select>\n <?php else: ?>\n <input\n type=\"<?php echo esc_attr($field_type); ?>\"\n id=\"waa_options_<?php echo esc_attr($field_name); ?>\"\n name=\"waa_options[<?php echo esc_attr($field_name); ?>]\"\n value=\"<?php echo esc_attr($value); ?>\"\n class=\"regular-text\"\n />\n <?php endif; ?>\n <?php if (!empty($args['description'])): ?>\n <p class=\"description\"><?php echo esc_html($args['description']); ?></p>\n <?php endif; ?>\n </div>\n <?php\n}\n\npublic function render_textarea_field(array $args): void {\n $options = get_option('waa_options');\n $field = $args['field'];\n $value = $options[$field] ?? '';\n echo '<textarea name=\"waa_options[' . esc_attr($field) . ']\" class=\"large-text\" rows=\"4\">' . esc_textarea($value) . '</textarea>';\n if (!empty($args['description'])) {\n echo '<p class=\"description\">' . esc_html($args['description']) . '</p>';\n }\n}\n\npublic function render_select_field(array $args): void {\n $options = get_option('waa_options');\n $field = $args['field'];\n $value = $options[$field] ?? $args['default'] ?? '';\n $class = $args['class'] ?? '';\n \n // Build data attributes\n $data_attrs = '';\n if (!empty($args['data'])) {\n foreach ($args['data'] as $key => $val) {\n $data_attrs .= ' data-' . esc_attr($key) . '=\"' . esc_attr($val) . '\"';\n }\n }\n \n $id = $args['id'] ?? 'waa_options_' . esc_attr($field);\n \n echo '<select name=\"waa_options[' . esc_attr($field) . ']\" id=\"' . esc_attr($id) . '\" class=\"' . esc_attr($class) . '\"' . $data_attrs . '>';\n foreach ($args['options'] as $key => $label) {\n echo '<option value=\"' . esc_attr($key) . '\" ' . selected($value, $key, false) . '>';\n echo esc_html($label);\n echo '</option>';\n }\n echo '</select>';\n \n if (!empty($args['description'])) {\n echo '<p class=\"description\">' . esc_html($args['description']) . '</p>';\n }\n}\n\npublic function register_settings(): void {\n // Register the settings group\n register_setting(\n 'waa_options', // Option group\n 'waa_options', // Option name in the database\n ['sanitize_callback' => [$this, 'sanitize_options']]\n );\n\n // Register settings sections\n $this->register_ai_settings(); // AI provider and model settings\n $this->register_api_settings(); // API credentials for all providers\n $this->register_search_settings(); // Search configuration\n $this->register_display_settings(); // Display options\n $this->register_lead_settings(); // Lead generation settings\n $this->register_consent_settings(); // Consent settings\n\n // Log registered settings for debugging\n waa_debug_log('Settings registered with the following data:', [\n 'option_group' => 'waa_options',\n 'sections' => [\n 'ai_settings' => 'website-ai-assistant',\n 'api_credentials' => 'website-ai-assistant',\n 'search_settings' => 'website-ai-assistant',\n 'display_settings' => 'website-ai-assistant',\n 'lead_settings' => 'website-ai-assistant',\n 'consent_settings' => 'website-ai-assistant'\n ]\n ]);\n}\n\nprivate function register_lead_settings(): void {\n add_settings_section(\n 'waa_lead_settings',\n __('Lead Generation Settings', 'website-ai-assistant'),\n [$this, 'render_lead_section'],\n 'website-ai-assistant'\n );\n\n // Enable lead collection\n add_settings_field(\n 'enable_lead_collection',\n __('Enable Lead Collection', 'website-ai-assistant'),\n [$this, 'render_checkbox_field'],\n 'website-ai-assistant',\n 'waa_lead_settings',\n [\n 'field' => 'enable_lead_collection',\n 'description' => __('Show lead collection form in chat widget', 'website-ai-assistant')\n ]\n );\n\n // Lead collection timing\n add_settings_field(\n 'lead_collection_timing',\n __('When to Show Form', 'website-ai-assistant'),\n [$this, 'render_select_field'],\n 'website-ai-assistant',\n 'waa_lead_settings',\n [\n 'field' => 'lead_collection_timing',\n 'options' => [\n 'immediate' => __('Immediately', 'website-ai-assistant'),\n 'after_first' => __('After First Message', 'website-ai-assistant'),\n 'after_two' => __('After Two Messages', 'website-ai-assistant'),\n 'end' => __('After Three Messages', 'website-ai-assistant')\n ],\n 'default' => 'immediate',\n 'description' => __('Choose when to display the lead collection form', 'website-ai-assistant')\n ]\n );\n\n // Form heading\n add_settings_field(\n 'lead_collection_heading',\n __('Form Heading', 'website-ai-assistant'),\n [$this, 'render_text_field'],\n 'website-ai-assistant',\n 'waa_lead_settings',\n [\n 'field' => 'lead_collection_heading',\n 'type' => 'text',\n 'default' => __('Please share your contact info to continue', 'website-ai-assistant'),\n 'description' => __('Heading text displayed at the top of the form', 'website-ai-assistant')\n ]\n );\n\n // Form description\n add_settings_field(\n 'lead_collection_description',\n __('Form Description', 'website-ai-assistant'),\n [$this, 'render_text_field'],\n 'website-ai-assistant',\n 'waa_lead_settings',\n [\n 'field' => 'lead_collection_description',\n 'type' => 'text',\n 'description' => __('Optional description text below the heading', 'website-ai-assistant')\n ]\n );\n\n // FluentCRM List selector (populated dynamically)\n add_settings_field(\n 'fluentcrm_list_id',\n __('FluentCRM List', 'website-ai-assistant'),\n [$this, 'render_select_field'],\n 'website-ai-assistant',\n 'waa_lead_settings',\n [\n 'field' => 'fluentcrm_list_id',\n 'options' => $this->get_fluentcrm_lists(),\n 'description' => __('Select the FluentCRM list to add contacts to', 'website-ai-assistant')\n ]\n );\n\n // FluentCRM Tag selector (populated dynamically)\n add_settings_field(\n 'fluentcrm_tag_id',\n __('FluentCRM Tag', 'website-ai-assistant'),\n [$this, 'render_select_field'],\n 'website-ai-assistant',\n 'waa_lead_settings',\n [\n 'field' => 'fluentcrm_tag_id',\n 'options' => $this->get_fluentcrm_tags(),\n 'description' => __('Select the FluentCRM tag to apply to contacts', 'website-ai-assistant')\n ]\n );\n\n // Contact Status\n add_settings_field(\n 'fluentcrm_status',\n __('Contact Status', 'website-ai-assistant'),\n [$this, 'render_select_field'],\n 'website-ai-assistant',\n 'waa_lead_settings',\n [\n 'field' => 'fluentcrm_status',\n 'options' => [\n 'subscribed' => __('Subscribed', 'website-ai-assistant'),\n 'pending' => __('Pending', 'website-ai-assistant'),\n 'unsubscribed' => __('Unsubscribed', 'website-ai-assistant')\n ],\n 'default' => 'subscribed',\n 'description' => __('Select the default status for new contacts', 'website-ai-assistant')\n ]\n );\n}\n\npublic function render_lead_section(): void {\n echo '<p>' . esc_html__('Configure lead generation settings:', 'website-ai-assistant') . '</p>';\n echo '<ul class=\"waa-section-info\">';\n echo '<li>' . esc_html__('Enable/disable lead collection form', 'website-ai-assistant') . '</li>';\n echo '<li>' . esc_html__('Choose when to show the form (immediately, after first message, etc.)', 'website-ai-assistant') . '</li>';\n echo '<li>' . esc_html__('Customize form heading and description', 'website-ai-assistant') . '</li>';\n echo '<li>' . esc_html__('Connect to FluentCRM for lead storage (make sure FluentCRM is installed)', 'website-ai-assistant') . '</li>';\n echo '<li>' . esc_html__('Select FluentCRM list and tag for organizing contacts', 'website-ai-assistant') . '</li>';\n echo '</ul>';\n}\n\n\n private function register_ai_settings(): void {\n /* Original AI settings section\n add_settings_section(\n 'waa_ai_settings',\n __('AI Settings', 'website-ai-assistant'),\n [$this, 'render_ai_section'],\n 'website-ai-assistant'\n );\n\n // AI Provider selector\n add_settings_field(\n 'ai_provider',\n __('AI Provider', 'website-ai-assistant'),\n [$this, 'render_select_field'],\n 'website-ai-assistant',\n 'waa_ai_settings',\n [\n 'field' => 'ai_provider',\n 'options' => $this->get_ai_provider_options(),\n 'default' => 'gemini'\n ]\n );\n\n // AI Model selector\n add_settings_field(\n 'ai_model',\n __('AI Model', 'website-ai-assistant'),\n [$this, 'render_select_field'],\n 'website-ai-assistant',\n 'waa_ai_settings',\n [\n 'field' => 'ai_model',\n 'options' => []\n ]\n );\n\n // System Message\n add_settings_field(\n 'system_message',\n __('System Message', 'website-ai-assistant'),\n [$this, 'render_textarea_field'],\n 'website-ai-assistant',\n 'waa_ai_settings',\n ['field' => 'system_message']\n );\n */\n\n add_settings_section(\n 'waa_ai_settings',\n __('AI Settings', 'website-ai-assistant'),\n [$this, 'render_ai_section'],\n 'website-ai-assistant'\n );\n\n // AI Provider selector\n add_settings_field(\n 'ai_provider',\n __('AI Provider', 'website-ai-assistant'),\n [$this, 'render_select_field'],\n 'website-ai-assistant',\n 'waa_ai_settings',\n [\n 'field' => 'ai_provider',\n 'id' => 'waa_options_ai_provider',\n 'options' => $this->get_ai_provider_options(),\n 'default' => 'gemini',\n 'description' => __('Select your AI provider', 'website-ai-assistant')\n ]\n );\n\n // OpenAI Model Selector - populated dynamically via AJAX\n add_settings_field(\n 'openai_model',\n __('OpenAI Model', 'website-ai-assistant'),\n [$this, 'render_select_field'],\n 'website-ai-assistant',\n 'waa_ai_settings',\n [\n 'field' => 'openai_model',\n 'id' => 'waa_options_openai_model',\n 'class' => 'openai-field model-field',\n 'data' => [\n 'current-value' => get_option('waa_options')['openai_model'] ?? '',\n 'provider' => 'openai'\n ],\n 'options' => array_merge(\n ['' => __('Select OpenAI model', 'website-ai-assistant')],\n get_option('waa_openai_models', [])\n ),\n 'description' => __('Select OpenAI model', 'website-ai-assistant')\n ]\n );\n\n // Gemini Model Selector with predefined options\n add_settings_field(\n 'gemini_model',\n __('Gemini Model', 'website-ai-assistant'),\n [$this, 'render_select_field'],\n 'website-ai-assistant',\n 'waa_ai_settings',\n [\n 'field' => 'gemini_model',\n 'id' => 'waa_options_gemini_model',\n 'class' => 'gemini-field model-field',\n 'data' => [\n 'current-value' => get_option('waa_options')['gemini_model'] ?? '',\n 'provider' => 'gemini'\n ],\n 'options' => array_merge(\n ['' => __('Select Gemini model', 'website-ai-assistant')],\n \\Website_Ai_Assistant\\Models\\Gemini_Service::AVAILABLE_MODELS\n ),\n 'description' => __('Select a Gemini model to use', 'website-ai-assistant')\n ]\n );\n\n // Deepseek Model Selector - populated dynamically via AJAX\n add_settings_field(\n 'deepseek_model',\n __('Deepseek Model', 'website-ai-assistant'),\n [$this, 'render_select_field'],\n 'website-ai-assistant',\n 'waa_ai_settings',\n [\n 'field' => 'deepseek_model',\n 'id' => 'waa_options_deepseek_model',\n 'class' => 'deepseek-field model-field',\n 'data' => [\n 'current-value' => get_option('waa_options')['deepseek_model'] ?? '',\n 'provider' => 'deepseek'\n ],\n 'options' => array_merge(\n ['' => __('Select Deepseek model', 'website-ai-assistant')],\n get_option('waa_deepseek_models', [])\n ),\n 'description' => __('Select Deepseek model', 'website-ai-assistant')\n ]\n );\n\n add_settings_field(\n 'system_message',\n __('System Message', 'website-ai-assistant'),\n [$this, 'render_textarea_field'],\n 'website-ai-assistant',\n 'waa_ai_settings',\n [\n 'field' => 'system_message',\n 'description' => __('This message sets the AI\\'s behavior and tone. Leave blank for default.', 'website-ai-assistant')\n ]\n );\n }\n\n private function register_api_settings(): void {\n // API Credentials Section\n add_settings_section(\n 'api_credentials',\n __('API Credentials', 'website-ai-assistant'),\n [$this, 'render_api_section'],\n self::SETTINGS_PAGE\n );\n\n // OpenAI Credentials\n add_settings_field(\n 'openai_api_key',\n __('OpenAI API Key', 'website-ai-assistant'),\n [$this, 'render_text_field'],\n 'website-ai-assistant',\n 'api_credentials',\n [\n 'field' => 'openai_api_key',\n 'type' => 'password',\n 'class' => 'openai-field waa-api-key-field',\n 'description' => __('Enter your API key from OpenAI dashboard', 'website-ai-assistant')\n ]\n );\n\n // OpenAI Cache Control\n add_settings_field(\n 'openai_disable_cache',\n __('Model Cache', 'website-ai-assistant'),\n [$this, 'render_checkbox_field'],\n 'website-ai-assistant',\n 'api_credentials',\n [\n 'field' => 'openai_disable_cache',\n 'class' => 'openai-field',\n 'description' => __('Disable caching to fetch fresh model list from OpenAI API each time', 'website-ai-assistant')\n ]\n );\n\n // Deepseek API Key\n add_settings_field(\n 'deepseek_api_key',\n __('Deepseek API Key', 'website-ai-assistant'),\n [$this, 'render_text_field'],\n 'website-ai-assistant',\n 'api_credentials',\n [\n 'field' => 'deepseek_api_key',\n 'type' => 'password',\n 'class' => 'deepseek-field waa-api-key-field',\n 'description' => __('Enter your API key from Deepseek dashboard', 'website-ai-assistant')\n ]\n );\n\n // Deepseek API Endpoint\n add_settings_field(\n 'deepseek_endpoint',\n __('Deepseek Endpoint', 'website-ai-assistant'),\n [$this, 'render_text_field'],\n 'website-ai-assistant',\n 'api_credentials',\n [\n 'field' => 'deepseek_endpoint',\n 'type' => 'text',\n 'class' => 'deepseek-field waa-api-key-field',\n 'default' => 'https://api.deepseek.com/v1/',\n 'description' => __('API endpoint for Deepseek service (default: https://api.deepseek.com/v1/)', 'website-ai-assistant')\n ]\n );\n\n // Gemini API Key\n add_settings_field(\n 'gemini_api_key',\n __('Gemini API Key', 'website-ai-assistant'),\n [$this, 'render_text_field'],\n 'website-ai-assistant',\n 'api_credentials',\n [\n 'field' => 'gemini_api_key',\n 'type' => 'password',\n 'class' => 'waa-api-key-field',\n 'description' => __('Enter your API key from Google AI Studio', 'website-ai-assistant')\n ]\n );\n\n // Keep existing fields commented for reference\n /* Original Gemini field\n add_settings_field(\n 'gemini_api_key',\n __('Gemini API Key', 'website-ai-assistant'),\n [$this, 'render_text_field'],\n 'waa_api_credentials',\n 'waa_api_credentials',\n [\n 'field' => 'gemini_api_key',\n 'type' => 'password',\n 'class' => 'gemini-field waa-api-key-field'\n ]\n );\n */\n\n }\n\n private function register_search_settings(): void {\n // Search Settings Section\n add_settings_section(\n 'waa_search_settings',\n __('Search Settings', 'website-ai-assistant'),\n [$this, 'render_search_section'],\n 'website-ai-assistant'\n );\n\n // Define all search fields\n $search_fields = [\n // Search Provider\n [\n 'id' => 'search_provider',\n 'title' => __('Search Provider', 'website-ai-assistant'),\n 'callback' => 'render_select_field',\n 'args' => [\n 'field' => 'search_provider',\n 'options' => [\n 'google' => __('Google Custom Search', 'website-ai-assistant'),\n 'algolia' => __('Algolia', 'website-ai-assistant')\n ],\n 'default' => 'google',\n 'description' => __('Select your preferred search provider', 'website-ai-assistant')\n ]\n ],\n // Google Search Settings\n [\n 'id' => 'google_search_api_key',\n 'title' => __('Google Search API Key', 'website-ai-assistant'),\n 'callback' => 'render_text_field',\n 'args' => [\n 'field' => 'google_search_api_key',\n 'type' => 'password',\n 'class' => 'google-search-field waa-api-key-field',\n 'description' => __('Enter your Google Custom Search API Key', 'website-ai-assistant')\n ]\n ],\n [\n 'id' => 'search_engine_id',\n 'title' => __('Google Search Engine ID', 'website-ai-assistant'),\n 'callback' => 'render_text_field',\n 'args' => [\n 'field' => 'search_engine_id',\n 'type' => 'text',\n 'class' => 'google-search-field waa-api-key-field',\n 'description' => __('Enter your Google Custom Search Engine ID', 'website-ai-assistant')\n ]\n ],\n // Algolia Settings\n [\n 'id' => 'algolia_app_id',\n 'title' => __('Algolia Application ID', 'website-ai-assistant'),\n 'callback' => 'render_text_field',\n 'args' => [\n 'field' => 'algolia_app_id',\n 'type' => 'text',\n 'class' => 'algolia-field waa-api-key-field',\n 'description' => __('Enter your Algolia Application ID', 'website-ai-assistant')\n ]\n ],\n [\n 'id' => 'algolia_search_key',\n 'title' => __('Algolia Search API Key', 'website-ai-assistant'),\n 'callback' => 'render_text_field',\n 'args' => [\n 'field' => 'algolia_search_key',\n 'type' => 'password',\n 'class' => 'algolia-field waa-api-key-field',\n 'description' => __('Enter your Algolia Search-Only API Key', 'website-ai-assistant')\n ]\n ],\n [\n 'id' => 'algolia_admin_key',\n 'title' => __('Algolia Admin API Key', 'website-ai-assistant'),\n 'callback' => 'render_text_field',\n 'args' => [\n 'field' => 'algolia_admin_key',\n 'type' => 'password',\n 'class' => 'algolia-field waa-api-key-field',\n 'description' => __('Enter your Algolia Admin API Key', 'website-ai-assistant')\n ]\n ],\n [\n 'id' => 'algolia_index',\n 'title' => __('Algolia Index Name', 'website-ai-assistant'),\n 'callback' => 'render_text_field',\n 'args' => [\n 'field' => 'algolia_index',\n 'type' => 'text',\n 'class' => 'algolia-field waa-api-key-field',\n 'description' => __('Enter your Algolia Index Name (e.g., website_contentsearchable_posts)', 'website-ai-assistant')\n ]\n ]\n ];\n\n // Register all search fields\n foreach ($search_fields as $field) {\n add_settings_field(\n $field['id'],\n $field['title'],\n [$this, $field['callback']],\n 'website-ai-assistant',\n 'waa_search_settings',\n $field['args']\n );\n }\n }\n\n private function register_display_settings(): void {\n add_settings_section(\n 'waa_display_settings',\n __('Display Settings', 'website-ai-assistant'),\n [$this, 'render_display_section'],\n 'website-ai-assistant'\n );\n\n add_settings_field(\n 'display_locations',\n __('Show Chat Widget On', 'website-ai-assistant'),\n [$this, 'render_display_locations_field'],\n 'website-ai-assistant',\n 'waa_display_settings'\n );\n\n add_settings_field(\n 'enable_debug',\n __('Enable Debug Logging', 'website-ai-assistant'),\n [$this, 'render_checkbox_field'],\n 'website-ai-assistant',\n 'waa_display_settings',\n [\n 'field' => 'enable_debug',\n 'description' => __('Log debug information', 'website-ai-assistant')\n ]\n );\n }\n\n private function register_consent_settings(): void {\n add_settings_section(\n 'waa_consent_settings',\n __('Consent Settings', 'website-ai-assistant'),\n [$this, 'render_consent_section'],\n 'website-ai-assistant'\n );\n\n // Enable consent checkbox\n add_settings_field(\n 'enable_consent',\n __('Enable Consent Request', 'website-ai-assistant'),\n [$this, 'render_checkbox_field'],\n 'website-ai-assistant',\n 'waa_consent_settings',\n [\n 'field' => 'enable_consent',\n 'description' => __('Requires users to accept the consent message before starting a chat.', 'website-ai-assistant')\n ]\n );\n\n // Consent Message textarea\n add_settings_field(\n 'consent_message',\n __('Consent Message', 'website-ai-assistant'),\n [$this, 'render_textarea_field'],\n 'website-ai-assistant',\n 'waa_consent_settings',\n [\n 'field' => 'consent_message',\n 'description' => __('The text shown to the user requesting consent.', 'website-ai-assistant')\n ]\n );\n }\n\n public function render_consent_section(): void {\n echo '<p>' . esc_html__('Configure chatbot consent settings below:', 'website-ai-assistant') . '</p>';\n }\n\n private function get_ai_provider_options(): array {\n return [\n 'gemini' => __('Google Gemini AI', 'website-ai-assistant'),\n 'openai' => __('OpenAI', 'website-ai-assistant'),\n 'deepseek' => __('Deepseek', 'website-ai-assistant')\n ];\n }\n\n private function get_fluentcrm_lists(): array {\n if (!function_exists('FluentCrmApi')) {\n return ['' => __('FluentCRM not installed', 'website-ai-assistant')];\n }\n\n try {\n $listApi = FluentCrmApi('lists');\n if (!$listApi) {\n return ['' => __('FluentCRM API not available', 'website-ai-assistant')];\n }\n\n $lists = $listApi->all();\n if (empty($lists)) {\n return ['' => __('No lists found', 'website-ai-assistant')];\n }\n\n $options = ['' => __('Select a list', 'website-ai-assistant')];\n foreach ($lists as $list) {\n $options[$list->id] = esc_html($list->title);\n }\n return $options;\n } catch (\\Exception $e) {\n error_log('Website AI Assistant Error: ' . $e->getMessage());\n return ['' => __('Error loading lists', 'website-ai-assistant')];\n }\n }\n\n private function get_fluentcrm_tags(): array {\n if (!function_exists('FluentCrmApi')) {\n return ['' => __('FluentCRM not installed', 'website-ai-assistant')];\n }\n\n try {\n $tagApi = FluentCrmApi('tags');\n if (!$tagApi) {\n return ['' => __('FluentCRM API not available', 'website-ai-assistant')];\n }\n\n $tags = $tagApi->all();\n if (empty($tags)) {\n return ['' => __('No tags found', 'website-ai-assistant')];\n }\n\n $options = ['' => __('Select a tag', 'website-ai-assistant')];\n foreach ($tags as $tag) {\n $options[$tag->id] = esc_html($tag->title);\n }\n return $options;\n } catch (\\Exception $e) {\n error_log('Website AI Assistant Error: ' . $e->getMessage());\n return ['' => __('Error loading tags', 'website-ai-assistant')];\n }\n }\n\n public function render_settings_page(): void {\n if (!current_user_can('manage_options')) {\n return;\n }\n require_once WAA_PLUGIN_DIR . 'admin/views/settings-page.php';\n }\n\n public function render_ai_section(): void {\n echo '<p>' . esc_html__('Configure your AI settings below:', 'website-ai-assistant') . '</p>';\n echo '<ul class=\"waa-section-info\">';\n echo '<li>' . esc_html__('Select your preferred AI provider', 'website-ai-assistant') . '</li>';\n echo '<li>' . esc_html__('Enter the required API credentials', 'website-ai-assistant') . '</li>';\n echo '<li>' . esc_html__('Choose the model you want to use', 'website-ai-assistant') . '</li>';\n echo '</ul>';\n }\n\n public function render_api_section(): void {\n echo '<p>' . esc_html__('API Credentials:', 'website-ai-assistant') . '</p>';\n echo '<ul class=\"waa-section-info\">';\n echo '<li>' . esc_html__('Gemini: Get your API key from Google AI Studio', 'website-ai-assistant') . '</li>';\n echo '<li>' . esc_html__('OpenAI: Get your API key from OpenAI dashboard', 'website-ai-assistant') . '</li>';\n echo '<li>' . esc_html__('Deepseek: Get your API key from Deepseek platform', 'website-ai-assistant') . '</li>';\n echo '</ul>';\n }\n\n public function render_search_section(): void {\n echo '<p>' . esc_html__('Search Provider Settings:', 'website-ai-assistant') . '</p>';\n echo '<ul class=\"waa-section-info\">';\n echo '<li>' . esc_html__('Google: Custom Search requires API key and Engine ID', 'website-ai-assistant') . '</li>';\n echo '<li>' . esc_html__('Algolia: Uses existing WordPress Algolia plugin settings', 'website-ai-assistant') . '</li>';\n echo '</ul>';\n }\n\n public function render_display_section(): void {\n echo '<p>' . esc_html__('Configure where the chat widget should appear.', 'website-ai-assistant') . '</p>';\n }\n\n\n /* Commented out duplicate method - preserved for reference\n public function render_textarea_field(array $args): void {\n $options = get_option('waa_options');\n $field = $args['field'];\n $value = $options[$field] ?? '';\n echo '<textarea name=\"waa_options[' . esc_attr($field) . ']\" class=\"large-text\" rows=\"4\">' . esc_textarea($value) . '</textarea>';\n if (!empty($args['description'])) {\n echo '<p class=\"description\">' . esc_html($args['description']) . '</p>';\n }\n }\n */\n\n public function handle_fetch_models(): void {\n error_log('Starting handle_fetch_models...');\n check_ajax_referer('waa_admin_nonce', 'nonce');\n \n if (!current_user_can('manage_options')) {\n error_log('Unauthorized access attempt in handle_fetch_models');\n wp_send_json_error(['message' => __('Unauthorized access', 'website-ai-assistant')]);\n return;\n }\n \n $provider = sanitize_text_field($_POST['provider'] ?? '');\n $api_key = sanitize_text_field($_POST['api_key'] ?? '');\n waa_debug_log('handle_fetch_models called', [\n 'provider' => $provider,\n 'has_api_key' => !empty($api_key),\n 'api_key_length' => strlen($api_key),\n 'post_data' => $_POST,\n 'request_method' => $_SERVER['REQUEST_METHOD']\n ]);\n \n $models = [];\n \n switch ($provider) {\n case 'gemini':\n $models = \\Website_Ai_Assistant\\Models\\Gemini_Service::AVAILABLE_MODELS;\n update_option('waa_gemini_models', $models);\n waa_debug_log('Using static Gemini models');\n break;\n case 'openai':\n try {\n $api_key = sanitize_text_field($_POST['api_key'] ?? '');\n waa_debug_log('OpenAI: Processing model fetch request');\n \n waa_debug_log('OpenAI: Processing fetch models request', [\n 'has_api_key' => !empty($api_key),\n 'api_key_length' => strlen($api_key),\n 'api_key_preview' => substr($api_key, 0, 10) . '...'\n ]);\n\n // Check for cached models first\n $cached_models = get_option('waa_openai_models', []);\n $cached_key_hash = get_option('waa_openai_key_hash', '');\n $current_key_hash = md5($api_key);\n \n // Use cached models if available and key matches\n if (!empty($cached_models) && $cached_key_hash === $current_key_hash) {\n $models = $cached_models;\n waa_debug_log('OpenAI: Using cached models');\n break;\n }\n \n if (empty($api_key)) {\n throw new \\Exception(__('API key is required', 'website-ai-assistant'));\n }\n \n // If no cache hit, determine whether to use cache for fetching\n $options = get_option('waa_options', []);\n $force_refresh = isset($_POST['force_refresh']) && $_POST['force_refresh'] === 'true';\n $use_cache = !$force_refresh && empty($options['openai_disable_cache']);\n\n waa_debug_log('OpenAI: Cache Settings:', [\n 'use_cache' => $use_cache,\n 'force_refresh' => $force_refresh ? 'yes' : 'no',\n 'disable_cache_setting' => !empty($options['openai_disable_cache']) ? 'yes' : 'no'\n ]);\n \n if ($use_cache) {\n $cached_models = get_option('waa_openai_models', []);\n $cached_key_hash = get_option('waa_openai_key_hash', '');\n $current_key_hash = md5($api_key);\n\n waa_debug_log('OpenAI: Cache status', [\n 'has_cached_models' => !empty($cached_models),\n 'models_count' => count($cached_models),\n 'cache_key_match' => $cached_key_hash === $current_key_hash,\n 'current_key_hash' => $current_key_hash\n ]);\n\n // Use cached models if available and key matches\n if ($cached_models && $cached_key_hash === $current_key_hash) {\n $models = $cached_models;\n waa_debug_log('OpenAI: Using cached models');\n break;\n }\n }\n \n // If we get here, either cache is disabled or we need fresh models\n waa_debug_log('OpenAI: Fetching fresh models from API');\n $openai_service = new OpenAI_Service($api_key);\n $models = $openai_service->get_available_models();\n \n // Cache the models unless this was a forced refresh\n if (!$force_refresh && !empty($models)) {\n update_option('waa_openai_models', $models);\n update_option('waa_openai_key_hash', md5($api_key));\n waa_debug_log('OpenAI: Cached new models');\n }\n\n // Set default model if none selected\n if (!empty($models)) {\n $options = get_option('waa_options', []);\n if (empty($options['openai_model'])) {\n $first_model = array_key_first($models);\n $options['openai_model'] = $first_model;\n update_option('waa_options', $options);\n waa_debug_log('OpenAI: Set default model:', $first_model);\n }\n }\n } catch (\\Exception $e) {\n wp_send_json_error(['message' => $e->getMessage()]);\n return;\n }\n break;\n case 'deepseek':\n // Check for cached models first\n $cached_models = get_option('waa_deepseek_models', []);\n $cached_key_hash = get_option('waa_deepseek_key_hash', '');\n $api_key = sanitize_text_field($_POST['api_key'] ?? '');\n $current_key_hash = md5($api_key);\n\n // Use cached models if available and key matches\n if (!empty($cached_models) && $cached_key_hash === $current_key_hash) {\n $models = $cached_models;\n waa_debug_log('Deepseek: Using cached models');\n break;\n }\n\n // If no cache hit, validate API key and fetch models\n if (empty($api_key)) {\n throw new \\Exception(__('API key is required', 'website-ai-assistant'));\n }\n\n try {\n $deepseek_service = new Deepseek_Service($api_key, Deepseek_Service::API_ENDPOINT);\n $models = $deepseek_service->get_available_models();\n \n // Cache the models and API key hash\n update_option('waa_deepseek_models', $models);\n update_option('waa_deepseek_key_hash', $current_key_hash);\n waa_debug_log('Deepseek: Cached new models');\n } catch (\\Exception $e) {\n wp_send_json_error(['message' => $e->getMessage()]);\n return;\n }\n break;\n default:\n wp_send_json_error(['message' => __('Invalid provider', 'website-ai-assistant')]);\n return;\n }\n \n wp_send_json_success(['models' => $models]);\n }\n\n /* Commented out duplicate method - preserved for reference\n public function render_select_field(array $args): void {\n $options = get_option('waa_options');\n $field = $args['field'];\n $value = $options[$field] ?? $args['default'] ?? '';\n \n echo '<select name=\"waa_options[' . esc_attr($field) . ']\" id=\"waa_options_' . esc_attr($field) . '\">';\n foreach ($args['options'] as $key => $label) {\n echo '<option value=\"' . esc_attr($key) . '\" ' . selected($value, $key, false) . '>';\n echo esc_html($label);\n echo '</option>';\n }\n echo '</select>';\n \n if (!empty($args['description'])) {\n echo '<p class=\"description\">' . esc_html($args['description']) . '</p>';\n }\n }\n */\n\n public function render_checkbox_field(array $args): void {\n $options = get_option('waa_options');\n $field = $args['field'];\n $checked = isset($options[$field]) && $options[$field] ? 'checked' : '';\n \n echo '<input type=\"checkbox\" name=\"waa_options[' . esc_attr($field) . ']\" ' . $checked . ' value=\"1\">';\n if (!empty($args['description'])) {\n echo '<p class=\"description\">' . esc_html($args['description']) . '</p>';\n }\n }\n\n public function render_display_locations_field(): void {\n $options = get_option('waa_options', []);\n $locations = $options['display_locations'] ?? ['all'];\n ?>\n <fieldset>\n <label>\n <input type=\"checkbox\" name=\"waa_options[display_locations][]\"\n value=\"all\" <?php checked(in_array('all', $locations)); ?>>\n <?php esc_html_e('All Pages', 'website-ai-assistant'); ?>\n </label><br>\n <label>\n <input type=\"checkbox\" name=\"waa_options[display_locations][]\"\n value=\"home\" <?php checked(in_array('home', $locations)); ?>>\n <?php esc_html_e('Home Page', 'website-ai-assistant'); ?>\n </label><br>\n <label>\n <input type=\"checkbox\" name=\"waa_options[display_locations][]\"\n value=\"posts\" <?php checked(in_array('posts', $locations)); ?>>\n <?php esc_html_e('Blog Posts', 'website-ai-assistant'); ?>\n </label><br>\n <label>\n <input type=\"checkbox\" name=\"waa_options[display_locations][]\"\n value=\"pages\" <?php checked(in_array('pages', $locations)); ?>>\n <?php esc_html_e('Pages', 'website-ai-assistant'); ?>\n </label><br>\n <label>\n <input type=\"checkbox\" name=\"waa_options[display_locations][]\"\n value=\"products\" <?php checked(in_array('products', $locations)); ?>>\n <?php esc_html_e('Products', 'website-ai-assistant'); ?>\n </label>\n </fieldset>\n <?php\n }\n\n public function enqueue_admin_assets($hook): void {\n // Only load on our settings page\n if ('settings_page_website-ai-assistant' !== $hook) {\n return;\n }\n\n wp_enqueue_style(\n 'waa-admin-styles',\n WAA_PLUGIN_URL . 'admin/css/admin-settings.css',\n [],\n WAA_VERSION\n );\n\n wp_enqueue_script(\n 'waa-admin-scripts',\n WAA_PLUGIN_URL . 'admin/js/admin-settings.js',\n ['jquery'],\n WAA_VERSION,\n true\n );\n\n wp_localize_script('waa-admin-scripts', 'waaAdmin', [\n 'ajaxUrl' => admin_url('admin-ajax.php'),\n 'nonce' => wp_create_nonce('waa_admin_nonce'),\n 'i18n' => [\n 'loadingModels' => __('Loading available models...', 'website-ai-assistant'),\n 'enterApiKey' => __('Please enter API key first', 'website-ai-assistant'),\n 'selectModel' => __('Select a model', 'website-ai-assistant'),\n 'fetchError' => __('Failed to fetch models', 'website-ai-assistant'),\n 'noModelsFound' => __('No available models found', 'website-ai-assistant'),\n 'fetchingModels' => __('Fetching available models...', 'website-ai-assistant')\n ]\n ]);\n }\n\n public function sanitize_options($input): array {\n waa_debug_log('Sanitizing input options:', [\n 'ai_provider' => $input['ai_provider'] ?? 'not set',\n 'search_provider' => $input['search_provider'] ?? 'not set',\n 'fields_present' => array_keys($input)\n ]);\n\n // Get existing options to preserve any values not in current input\n $existing = get_option('waa_options', []);\n $sanitized = $existing;\n\n // Handle search provider changes\n if (isset($input['search_provider'])) {\n $search_provider = sanitize_text_field($input['search_provider']);\n if (in_array($search_provider, ['google', 'algolia'])) {\n $old_provider = $existing['search_provider'] ?? 'google';\n $sanitized['search_provider'] = $search_provider;\n \n waa_debug_log('Search provider updated:', [\n 'from' => $old_provider,\n 'to' => $search_provider\n ]);\n\n // Only clear settings if they're explicitly empty in the input\n if ($search_provider === 'google') {\n // When switching to Google, preserve existing Algolia settings\n $sanitized['google_search_api_key'] = $input['google_search_api_key'] ?? $existing['google_search_api_key'] ?? '';\n $sanitized['search_engine_id'] = $input['search_engine_id'] ?? $existing['search_engine_id'] ?? '';\n } else if ($search_provider === 'algolia') {\n // When switching to Algolia, preserve existing Google settings\n $sanitized['algolia_app_id'] = $input['algolia_app_id'] ?? $existing['algolia_app_id'] ?? '';\n $sanitized['algolia_search_key'] = $input['algolia_search_key'] ?? $existing['algolia_search_key'] ?? '';\n $sanitized['algolia_admin_key'] = $input['algolia_admin_key'] ?? $existing['algolia_admin_key'] ?? '';\n $sanitized['algolia_index'] = $input['algolia_index'] ?? $existing['algolia_index'] ?? '';\n }\n \n waa_debug_log('Settings after provider change:', [\n 'provider' => $search_provider,\n 'has_google_key' => isset($sanitized['google_search_api_key']),\n 'has_algolia_key' => isset($sanitized['algolia_search_key'])\n ]);\n }\n }\n \n $field_types = [\n 'url' => ['deepseek_endpoint'],\n 'key' => [\n 'gemini_api_key', 'openai_api_key', 'deepseek_api_key',\n 'google_search_api_key', 'search_engine_id',\n 'algolia_app_id', 'algolia_search_key', 'algolia_admin_key'\n ],\n 'text' => ['algolia_index']\n ];\n\n // Process each field type\n foreach ($field_types as $type => $fields) {\n foreach ($fields as $field) {\n if (!isset($input[$field])) continue;\n\n switch ($type) {\n case 'url':\n $sanitized[$field] = esc_url_raw(rtrim($input[$field], '/') . '/');\n break;\n case 'key':\n case 'text':\n $sanitized[$field] = sanitize_text_field($input[$field]);\n if ($type === 'text') {\n waa_debug_log(\"Sanitizing text field: $field\", [\n 'input_value' => $input[$field],\n 'sanitized_value' => $sanitized[$field]\n ]);\n }\n break;\n }\n }\n }\n\n // Provider and model fields\n $provider_model_fields = [\n 'ai_provider',\n 'openai_model',\n 'gemini_model',\n 'deepseek_model',\n 'search_provider',\n 'system_message'\n ];\n\n foreach ($provider_model_fields as $field) {\n if (isset($input[$field])) {\n $sanitized[$field] = sanitize_text_field($input[$field]);\n waa_debug_log(\"Sanitized $field:\", $sanitized[$field]);\n } else {\n waa_debug_log(\"Field not found in input: $field\");\n $sanitized[$field] = '';\n }\n }\n\n // Add special handling for provider-specific model fields\n $provider = $sanitized['ai_provider'] ?? '';\n if ($provider) {\n $model_field = $provider . '_model';\n waa_debug_log(\"Checking provider-specific model field: $model_field\", [\n 'value' => $sanitized[$model_field] ?? 'not set',\n 'provider' => $provider\n ]);\n }\n\n // Handle display locations array\n if (isset($input['display_locations']) && is_array($input['display_locations'])) {\n $sanitized['display_locations'] = array_map('sanitize_text_field', $input['display_locations']);\n } else {\n $sanitized['display_locations'] = ['all']; // Default to all pages if not set\n }\n\n // Handle debug option\n $sanitized['enable_debug'] = isset($input['enable_debug']) ? 1 : 0;\n\n // Sanitize lead generation fields\n $lead_fields = [\n 'enable_lead_collection' => 'bool',\n 'lead_collection_timing' => 'text',\n 'lead_collection_heading' => 'text',\n 'lead_collection_description' => 'text',\n 'fluentcrm_list_id' => 'int',\n 'fluentcrm_tag_id' => 'int',\n 'fluentcrm_status' => 'text'\n ];\n\n foreach ($lead_fields as $field => $type) {\n if (isset($input[$field])) {\n switch ($type) {\n case 'bool':\n $sanitized[$field] = (bool) $input[$field];\n break;\n case 'int':\n $sanitized[$field] = absint($input[$field]);\n break;\n case 'text':\n $sanitized[$field] = sanitize_text_field($input[$field]);\n break;\n }\n }\n }\n\n // Sanitize consent settings\n $sanitized['enable_consent'] = isset($input['enable_consent']) ? 1 : 0;\n $sanitized['consent_message'] = isset($input['consent_message']) ? sanitize_textarea_field($input['consent_message']) : '';\n\n return $sanitized;\n }\n\n}\n"}, "c52f8b402a1362aecc23312ba13ae6e5a11fb792": {"t": 1785756319.694695, "n": 48986, "h": "d948add6048bc0cb", "c": "<?php\nnamespace Website_Ai_Assistant\\Admin;\n\nuse Website_Ai_Assistant\\Models\\OpenAI_Service;\nuse Website_Ai_Assistant\\Models\\Gemini_Service;\nuse Website_Ai_Assistant\\Models\\Deepseek_Service;\n\nclass Admin_Settings {\n private const OPTION_GROUP = 'waa_options';\n private const SETTINGS_PAGE = 'website-ai-assistant';\n private const TEST_PAGE = 'website-ai-assistant-test';\n\n public function __construct() {\n add_action('admin_menu', [$this, 'add_settings_page']);\n add_action('admin_init', [$this, 'register_settings']);\n add_action('admin_enqueue_scripts', [$this, 'enqueue_admin_assets']);\n add_action('wp_ajax_waa_fetch_models', [$this, 'handle_fetch_models']);\n add_action('wp_ajax_waa_update_model', [$this, 'handle_update_model']);\n\n // Log the AJAX actions setup\n waa_debug_log('Setting up AJAX actions');\n \n // Initialize admin settings values and log current settings\n add_action('admin_init', function() {\n $options = get_option('waa_options', []);\n waa_debug_log('Current admin settings:', [\n 'provider' => $options['ai_provider'] ?? 'not set',\n 'model' => $options[$options['ai_provider'] . '_model'] ?? 'not set',\n 'has_api_key' => !empty($options[$options['ai_provider'] . '_api_key']) ? 'yes' : 'no'\n ]);\n });\n }\n\n public function add_settings_page(): void {\n add_options_page(\n __('Website AI Assistant Settings', 'website-ai-assistant'),\n __('Website AI Assistant', 'website-ai-assistant'),\n 'manage_options',\n self::SETTINGS_PAGE,\n [$this, 'render_settings_page']\n );\n }\npublic function render_text_field($args): void {\n if (empty($args['field'])) {\n waa_debug_log(\"Error: Missing field name in render_text_field\", $args);\n return;\n }\n\n $options = get_option('waa_options', []);\n $field_name = $args['field'];\n $field_type = $args['type'] ?? 'text';\n $value = $options[$field_name] ?? $args['default'] ?? '';\n $class = $args['class'] ?? '';\n \n waa_debug_log(\"Rendering field: $field_name\", [\n 'type' => $field_type,\n 'value' => $value,\n 'class' => $class\n ]);\n \n ?>\n <div class=\"<?php echo esc_attr($class); ?>\">\n <?php if ($field_type === 'select'): ?>\n <select\n name=\"waa_options[<?php echo esc_attr($field_name); ?>]\"\n id=\"waa_options_<?php echo esc_attr($field_name); ?>\"\n class=\"regular-text\"\n <?php\n if (!empty($args['data'])) {\n foreach ($args['data'] as $key => $val) {\n echo ' data-' . esc_attr($key) . '=\"' . esc_attr($val) . '\"';\n }\n }\n ?>\n >\n <?php if (!empty($args['options'])): ?>\n <?php foreach ($args['options'] as $option_value => $option_label): ?>\n <option value=\"<?php echo esc_attr($option_value); ?>\" <?php selected($value, $option_value); ?>>\n <?php echo esc_html($option_label); ?>\n </option>\n <?php endforeach; ?>\n <?php endif; ?>\n </select>\n <?php else: ?>\n <input\n type=\"<?php echo esc_attr($field_type); ?>\"\n id=\"waa_options_<?php echo esc_attr($field_name); ?>\"\n name=\"waa_options[<?php echo esc_attr($field_name); ?>]\"\n value=\"<?php echo esc_attr($value); ?>\"\n class=\"regular-text\"\n />\n <?php endif; ?>\n <?php if (!empty($args['description'])): ?>\n <p class=\"description\"><?php echo esc_html($args['description']); ?></p>\n <?php endif; ?>\n </div>\n <?php\n}\n\npublic function render_textarea_field(array $args): void {\n $options = get_option('waa_options');\n $field = $args['field'];\n $value = $options[$field] ?? '';\n echo '<textarea name=\"waa_options[' . esc_attr($field) . ']\" class=\"large-text\" rows=\"4\">' . esc_textarea($value) . '</textarea>';\n if (!empty($args['description'])) {\n echo '<p class=\"description\">' . esc_html($args['description']) . '</p>';\n }\n}\n\npublic function render_select_field(array $args): void {\n $options = get_option('waa_options');\n $field = $args['field'];\n $value = $options[$field] ?? $args['default'] ?? '';\n $class = $args['class'] ?? '';\n \n // Build data attributes\n $data_attrs = '';\n if (!empty($args['data'])) {\n foreach ($args['data'] as $key => $val) {\n $data_attrs .= ' data-' . esc_attr($key) . '=\"' . esc_attr($val) . '\"';\n }\n }\n \n $id = $args['id'] ?? 'waa_options_' . esc_attr($field);\n \n echo '<select name=\"waa_options[' . esc_attr($field) . ']\" id=\"' . esc_attr($id) . '\" class=\"' . esc_attr($class) . '\"' . $data_attrs . '>';\n foreach ($args['options'] as $key => $label) {\n echo '<option value=\"' . esc_attr($key) . '\" ' . selected($value, $key, false) . '>';\n echo esc_html($label);\n echo '</option>';\n }\n echo '</select>';\n \n if (!empty($args['description'])) {\n echo '<p class=\"description\">' . esc_html($args['description']) . '</p>';\n }\n}\n\npublic function register_settings(): void {\n // Register the settings group\n register_setting(\n 'waa_options', // Option group\n 'waa_options', // Option name in the database\n ['sanitize_callback' => [$this, 'sanitize_options']]\n );\n\n // Register settings sections\n $this->register_ai_settings(); // AI provider and model settings\n $this->register_api_settings(); // API credentials for all providers\n $this->register_search_settings(); // Search configuration\n $this->register_display_settings(); // Display options\n $this->register_lead_settings(); // Lead generation settings\n\n // Log registered settings for debugging\n waa_debug_log('Settings registered with the following data:', [\n 'option_group' => 'waa_options',\n 'sections' => [\n 'ai_settings' => 'website-ai-assistant',\n 'api_credentials' => 'website-ai-assistant',\n 'search_settings' => 'website-ai-assistant',\n 'display_settings' => 'website-ai-assistant',\n 'lead_settings' => 'website-ai-assistant'\n ]\n ]);\n}\n\nprivate function register_lead_settings(): void {\n add_settings_section(\n 'waa_lead_settings',\n __('Lead Generation Settings', 'website-ai-assistant'),\n [$this, 'render_lead_section'],\n 'website-ai-assistant'\n );\n\n // Enable lead collection\n add_settings_field(\n 'enable_lead_collection',\n __('Enable Lead Collection', 'website-ai-assistant'),\n [$this, 'render_checkbox_field'],\n 'website-ai-assistant',\n 'waa_lead_settings',\n [\n 'field' => 'enable_lead_collection',\n 'description' => __('Show lead collection form in chat widget', 'website-ai-assistant')\n ]\n );\n\n // Lead collection timing\n add_settings_field(\n 'lead_collection_timing',\n __('When to Show Form', 'website-ai-assistant'),\n [$this, 'render_select_field'],\n 'website-ai-assistant',\n 'waa_lead_settings',\n [\n 'field' => 'lead_collection_timing',\n 'options' => [\n 'immediate' => __('Immediately', 'website-ai-assistant'),\n 'after_first' => __('After First Message', 'website-ai-assistant'),\n 'after_two' => __('After Two Messages', 'website-ai-assistant'),\n 'end' => __('After Three Messages', 'website-ai-assistant')\n ],\n 'default' => 'immediate',\n 'description' => __('Choose when to display the lead collection form', 'website-ai-assistant')\n ]\n );\n\n // Form heading\n add_settings_field(\n 'lead_collection_heading',\n __('Form Heading', 'website-ai-assistant'),\n [$this, 'render_text_field'],\n 'website-ai-assistant',\n 'waa_lead_settings',\n [\n 'field' => 'lead_collection_heading',\n 'type' => 'text',\n 'default' => __('Please share your contact info to continue', 'website-ai-assistant'),\n 'description' => __('Heading text displayed at the top of the form', 'website-ai-assistant')\n ]\n );\n\n // Form description\n add_settings_field(\n 'lead_collection_description',\n __('Form Description', 'website-ai-assistant'),\n [$this, 'render_text_field'],\n 'website-ai-assistant',\n 'waa_lead_settings',\n [\n 'field' => 'lead_collection_description',\n 'type' => 'text',\n 'description' => __('Optional description text below the heading', 'website-ai-assistant')\n ]\n );\n\n // FluentCRM List selector (populated dynamically)\n add_settings_field(\n 'fluentcrm_list_id',\n __('FluentCRM List', 'website-ai-assistant'),\n [$this, 'render_select_field'],\n 'website-ai-assistant',\n 'waa_lead_settings',\n [\n 'field' => 'fluentcrm_list_id',\n 'options' => $this->get_fluentcrm_lists(),\n 'description' => __('Select the FluentCRM list to add contacts to', 'website-ai-assistant')\n ]\n );\n\n // FluentCRM Tag selector (populated dynamically)\n add_settings_field(\n 'fluentcrm_tag_id',\n __('FluentCRM Tag', 'website-ai-assistant'),\n [$this, 'render_select_field'],\n 'website-ai-assistant',\n 'waa_lead_settings',\n [\n 'field' => 'fluentcrm_tag_id',\n 'options' => $this->get_fluentcrm_tags(),\n 'description' => __('Select the FluentCRM tag to apply to contacts', 'website-ai-assistant')\n ]\n );\n\n // Contact Status\n add_settings_field(\n 'fluentcrm_status',\n __('Contact Status', 'website-ai-assistant'),\n [$this, 'render_select_field'],\n 'website-ai-assistant',\n 'waa_lead_settings',\n [\n 'field' => 'fluentcrm_status',\n 'options' => [\n 'subscribed' => __('Subscribed', 'website-ai-assistant'),\n 'pending' => __('Pending', 'website-ai-assistant'),\n 'unsubscribed' => __('Unsubscribed', 'website-ai-assistant')\n ],\n 'default' => 'subscribed',\n 'description' => __('Select the default status for new contacts', 'website-ai-assistant')\n ]\n );\n}\n\npublic function render_lead_section(): void {\n echo '<p>' . esc_html__('Configure lead generation settings:', 'website-ai-assistant') . '</p>';\n echo '<ul class=\"waa-section-info\">';\n echo '<li>' . esc_html__('Enable/disable lead collection form', 'website-ai-assistant') . '</li>';\n echo '<li>' . esc_html__('Choose when to show the form (immediately, after first message, etc.)', 'website-ai-assistant') . '</li>';\n echo '<li>' . esc_html__('Customize form heading and description', 'website-ai-assistant') . '</li>';\n echo '<li>' . esc_html__('Connect to FluentCRM for lead storage (make sure FluentCRM is installed)', 'website-ai-assistant') . '</li>';\n echo '<li>' . esc_html__('Select FluentCRM list and tag for organizing contacts', 'website-ai-assistant') . '</li>';\n echo '</ul>';\n}\n\n\n private function register_ai_settings(): void {\n /* Original AI settings section\n add_settings_section(\n 'waa_ai_settings',\n __('AI Settings', 'website-ai-assistant'),\n [$this, 'render_ai_section'],\n 'website-ai-assistant'\n );\n\n // AI Provider selector\n add_settings_field(\n 'ai_provider',\n __('AI Provider', 'website-ai-assistant'),\n [$this, 'render_select_field'],\n 'website-ai-assistant',\n 'waa_ai_settings',\n [\n 'field' => 'ai_provider',\n 'options' => $this->get_ai_provider_options(),\n 'default' => 'gemini'\n ]\n );\n\n // AI Model selector\n add_settings_field(\n 'ai_model',\n __('AI Model', 'website-ai-assistant'),\n [$this, 'render_select_field'],\n 'website-ai-assistant',\n 'waa_ai_settings',\n [\n 'field' => 'ai_model',\n 'options' => []\n ]\n );\n\n // System Message\n add_settings_field(\n 'system_message',\n __('System Message', 'website-ai-assistant'),\n [$this, 'render_textarea_field'],\n 'website-ai-assistant',\n 'waa_ai_settings',\n ['field' => 'system_message']\n );\n */\n\n add_settings_section(\n 'waa_ai_settings',\n __('AI Settings', 'website-ai-assistant'),\n [$this, 'render_ai_section'],\n 'website-ai-assistant'\n );\n\n // AI Provider selector\n add_settings_field(\n 'ai_provider',\n __('AI Provider', 'website-ai-assistant'),\n [$this, 'render_select_field'],\n 'website-ai-assistant',\n 'waa_ai_settings',\n [\n 'field' => 'ai_provider',\n 'id' => 'waa_options_ai_provider',\n 'options' => $this->get_ai_provider_options(),\n 'default' => 'gemini',\n 'description' => __('Select your AI provider', 'website-ai-assistant')\n ]\n );\n\n // OpenAI Model Selector - populated dynamically via AJAX\n add_settings_field(\n 'openai_model',\n __('OpenAI Model', 'website-ai-assistant'),\n [$this, 'render_select_field'],\n 'website-ai-assistant',\n 'waa_ai_settings',\n [\n 'field' => 'openai_model',\n 'id' => 'waa_options_openai_model',\n 'class' => 'openai-field model-field',\n 'data' => [\n 'current-value' => get_option('waa_options')['openai_model'] ?? '',\n 'provider' => 'openai'\n ],\n 'options' => array_merge(\n ['' => __('Select OpenAI model', 'website-ai-assistant')],\n get_option('waa_openai_models', [])\n ),\n 'description' => __('Select OpenAI model', 'website-ai-assistant')\n ]\n );\n\n // Gemini Model Selector with predefined options\n add_settings_field(\n 'gemini_model',\n __('Gemini Model', 'website-ai-assistant'),\n [$this, 'render_select_field'],\n 'website-ai-assistant',\n 'waa_ai_settings',\n [\n 'field' => 'gemini_model',\n 'id' => 'waa_options_gemini_model',\n 'class' => 'gemini-field model-field',\n 'data' => [\n 'current-value' => get_option('waa_options')['gemini_model'] ?? '',\n 'provider' => 'gemini'\n ],\n 'options' => array_merge(\n ['' => __('Select Gemini model', 'website-ai-assistant')],\n \\Website_Ai_Assistant\\Models\\Gemini_Service::AVAILABLE_MODELS\n ),\n 'description' => __('Select a Gemini model to use', 'website-ai-assistant')\n ]\n );\n\n // Deepseek Model Selector - populated dynamically via AJAX\n add_settings_field(\n 'deepseek_model',\n __('Deepseek Model', 'website-ai-assistant'),\n [$this, 'render_select_field'],\n 'website-ai-assistant',\n 'waa_ai_settings',\n [\n 'field' => 'deepseek_model',\n 'id' => 'waa_options_deepseek_model',\n 'class' => 'deepseek-field model-field',\n 'data' => [\n 'current-value' => get_option('waa_options')['deepseek_model'] ?? '',\n 'provider' => 'deepseek'\n ],\n 'options' => array_merge(\n ['' => __('Select Deepseek model', 'website-ai-assistant')],\n get_option('waa_deepseek_models', [])\n ),\n 'description' => __('Select Deepseek model', 'website-ai-assistant')\n ]\n );\n\n add_settings_field(\n 'system_message',\n __('System Message', 'website-ai-assistant'),\n [$this, 'render_textarea_field'],\n 'website-ai-assistant',\n 'waa_ai_settings',\n [\n 'field' => 'system_message',\n 'description' => __('This message sets the AI\\'s behavior and tone. Leave blank for default.', 'website-ai-assistant')\n ]\n );\n }\n\n private function register_api_settings(): void {\n // API Credentials Section\n add_settings_section(\n 'api_credentials',\n __('API Credentials', 'website-ai-assistant'),\n [$this, 'render_api_section'],\n self::SETTINGS_PAGE\n );\n\n // OpenAI Credentials\n add_settings_field(\n 'openai_api_key',\n __('OpenAI API Key', 'website-ai-assistant'),\n [$this, 'render_text_field'],\n 'website-ai-assistant',\n 'api_credentials',\n [\n 'field' => 'openai_api_key',\n 'type' => 'password',\n 'class' => 'openai-field waa-api-key-field',\n 'description' => __('Enter your API key from OpenAI dashboard', 'website-ai-assistant')\n ]\n );\n\n // OpenAI Cache Control\n add_settings_field(\n 'openai_disable_cache',\n __('Model Cache', 'website-ai-assistant'),\n [$this, 'render_checkbox_field'],\n 'website-ai-assistant',\n 'api_credentials',\n [\n 'field' => 'openai_disable_cache',\n 'class' => 'openai-field',\n 'description' => __('Disable caching to fetch fresh model list from OpenAI API each time', 'website-ai-assistant')\n ]\n );\n\n // Deepseek API Key\n add_settings_field(\n 'deepseek_api_key',\n __('Deepseek API Key', 'website-ai-assistant'),\n [$this, 'render_text_field'],\n 'website-ai-assistant',\n 'api_credentials',\n [\n 'field' => 'deepseek_api_key',\n 'type' => 'password',\n 'class' => 'deepseek-field waa-api-key-field',\n 'description' => __('Enter your API key from Deepseek dashboard', 'website-ai-assistant')\n ]\n );\n\n // Deepseek API Endpoint\n add_settings_field(\n 'deepseek_endpoint',\n __('Deepseek Endpoint', 'website-ai-assistant'),\n [$this, 'render_text_field'],\n 'website-ai-assistant',\n 'api_credentials',\n [\n 'field' => 'deepseek_endpoint',\n 'type' => 'text',\n 'class' => 'deepseek-field waa-api-key-field',\n 'default' => 'https://api.deepseek.com/v1/',\n 'description' => __('API endpoint for Deepseek service (default: https://api.deepseek.com/v1/)', 'website-ai-assistant')\n ]\n );\n\n // Gemini API Key\n add_settings_field(\n 'gemini_api_key',\n __('Gemini API Key', 'website-ai-assistant'),\n [$this, 'render_text_field'],\n 'website-ai-assistant',\n 'api_credentials',\n [\n 'field' => 'gemini_api_key',\n 'type' => 'password',\n 'class' => 'waa-api-key-field',\n 'description' => __('Enter your API key from Google AI Studio', 'website-ai-assistant')\n ]\n );\n\n // Keep existing fields commented for reference\n /* Original Gemini field\n add_settings_field(\n 'gemini_api_key',\n __('Gemini API Key', 'website-ai-assistant'),\n [$this, 'render_text_field'],\n 'waa_api_credentials',\n 'waa_api_credentials',\n [\n 'field' => 'gemini_api_key',\n 'type' => 'password',\n 'class' => 'gemini-field waa-api-key-field'\n ]\n );\n */\n\n }\n\n private function register_search_settings(): void {\n // Search Settings Section\n add_settings_section(\n 'waa_search_settings',\n __('Search Settings', 'website-ai-assistant'),\n [$this, 'render_search_section'],\n 'website-ai-assistant'\n );\n\n // Define all search fields\n $search_fields = [\n // Search Provider\n [\n 'id' => 'search_provider',\n 'title' => __('Search Provider', 'website-ai-assistant'),\n 'callback' => 'render_select_field',\n 'args' => [\n 'field' => 'search_provider',\n 'options' => [\n 'google' => __('Google Custom Search', 'website-ai-assistant'),\n 'algolia' => __('Algolia', 'website-ai-assistant')\n ],\n 'default' => 'google',\n 'description' => __('Select your preferred search provider', 'website-ai-assistant')\n ]\n ],\n // Google Search Settings\n [\n 'id' => 'google_search_api_key',\n 'title' => __('Google Search API Key', 'website-ai-assistant'),\n 'callback' => 'render_text_field',\n 'args' => [\n 'field' => 'google_search_api_key',\n 'type' => 'password',\n 'class' => 'google-search-field waa-api-key-field',\n 'description' => __('Enter your Google Custom Search API Key', 'website-ai-assistant')\n ]\n ],\n [\n 'id' => 'search_engine_id',\n 'title' => __('Google Search Engine ID', 'website-ai-assistant'),\n 'callback' => 'render_text_field',\n 'args' => [\n 'field' => 'search_engine_id',\n 'type' => 'text',\n 'class' => 'google-search-field waa-api-key-field',\n 'description' => __('Enter your Google Custom Search Engine ID', 'website-ai-assistant')\n ]\n ],\n // Algolia Settings\n [\n 'id' => 'algolia_app_id',\n 'title' => __('Algolia Application ID', 'website-ai-assistant'),\n 'callback' => 'render_text_field',\n 'args' => [\n 'field' => 'algolia_app_id',\n 'type' => 'text',\n 'class' => 'algolia-field waa-api-key-field',\n 'description' => __('Enter your Algolia Application ID', 'website-ai-assistant')\n ]\n ],\n [\n 'id' => 'algolia_search_key',\n 'title' => __('Algolia Search API Key', 'website-ai-assistant'),\n 'callback' => 'render_text_field',\n 'args' => [\n 'field' => 'algolia_search_key',\n 'type' => 'password',\n 'class' => 'algolia-field waa-api-key-field',\n 'description' => __('Enter your Algolia Search-Only API Key', 'website-ai-assistant')\n ]\n ],\n [\n 'id' => 'algolia_admin_key',\n 'title' => __('Algolia Admin API Key', 'website-ai-assistant'),\n 'callback' => 'render_text_field',\n 'args' => [\n 'field' => 'algolia_admin_key',\n 'type' => 'password',\n 'class' => 'algolia-field waa-api-key-field',\n 'description' => __('Enter your Algolia Admin API Key', 'website-ai-assistant')\n ]\n ],\n [\n 'id' => 'algolia_index',\n 'title' => __('Algolia Index Name', 'website-ai-assistant'),\n 'callback' => 'render_text_field',\n 'args' => [\n 'field' => 'algolia_index',\n 'type' => 'text',\n 'class' => 'algolia-field waa-api-key-field',\n 'description' => __('Enter your Algolia Index Name (e.g., website_contentsearchable_posts)', 'website-ai-assistant')\n ]\n ]\n ];\n\n // Register all search fields\n foreach ($search_fields as $field) {\n add_settings_field(\n $field['id'],\n $field['title'],\n [$this, $field['callback']],\n 'website-ai-assistant',\n 'waa_search_settings',\n $field['args']\n );\n }\n }\n\n private function register_display_settings(): void {\n add_settings_section(\n 'waa_display_settings',\n __('Display Settings', 'website-ai-assistant'),\n [$this, 'render_display_section'],\n 'website-ai-assistant'\n );\n\n add_settings_field(\n 'display_locations',\n __('Show Chat Widget On', 'website-ai-assistant'),\n [$this, 'render_display_locations_field'],\n 'website-ai-assistant',\n 'waa_display_settings'\n );\n\n add_settings_field(\n 'enable_debug',\n __('Enable Debug Logging', 'website-ai-assistant'),\n [$this, 'render_checkbox_field'],\n 'website-ai-assistant',\n 'waa_display_settings',\n [\n 'field' => 'enable_debug',\n 'description' => __('Log debug information', 'website-ai-assistant')\n ]\n );\n }\n\n private function get_ai_provider_options(): array {\n return [\n 'gemini' => __('Google Gemini AI', 'website-ai-assistant'),\n 'openai' => __('OpenAI', 'website-ai-assistant'),\n 'deepseek' => __('Deepseek', 'website-ai-assistant')\n ];\n }\n\n private function get_fluentcrm_lists(): array {\n if (!function_exists('FluentCrmApi')) {\n return ['' => __('FluentCRM not installed', 'website-ai-assistant')];\n }\n\n try {\n $listApi = FluentCrmApi('lists');\n if (!$listApi) {\n return ['' => __('FluentCRM API not available', 'website-ai-assistant')];\n }\n\n $lists = $listApi->all();\n if (empty($lists)) {\n return ['' => __('No lists found', 'website-ai-assistant')];\n }\n\n $options = ['' => __('Select a list', 'website-ai-assistant')];\n foreach ($lists as $list) {\n $options[$list->id] = esc_html($list->title);\n }\n return $options;\n } catch (\\Exception $e) {\n error_log('Website AI Assistant Error: ' . $e->getMessage());\n return ['' => __('Error loading lists', 'website-ai-assistant')];\n }\n }\n\n private function get_fluentcrm_tags(): array {\n if (!function_exists('FluentCrmApi')) {\n return ['' => __('FluentCRM not installed', 'website-ai-assistant')];\n }\n\n try {\n $tagApi = FluentCrmApi('tags');\n if (!$tagApi) {\n return ['' => __('FluentCRM API not available', 'website-ai-assistant')];\n }\n\n $tags = $tagApi->all();\n if (empty($tags)) {\n return ['' => __('No tags found', 'website-ai-assistant')];\n }\n\n $options = ['' => __('Select a tag', 'website-ai-assistant')];\n foreach ($tags as $tag) {\n $options[$tag->id] = esc_html($tag->title);\n }\n return $options;\n } catch (\\Exception $e) {\n error_log('Website AI Assistant Error: ' . $e->getMessage());\n return ['' => __('Error loading tags', 'website-ai-assistant')];\n }\n }\n\n public function render_settings_page(): void {\n if (!current_user_can('manage_options')) {\n return;\n }\n require_once WAA_PLUGIN_DIR . 'admin/views/settings-page.php';\n }\n\n public function render_ai_section(): void {\n echo '<p>' . esc_html__('Configure your AI settings below:', 'website-ai-assistant') . '</p>';\n echo '<ul class=\"waa-section-info\">';\n echo '<li>' . esc_html__('Select your preferred AI provider', 'website-ai-assistant') . '</li>';\n echo '<li>' . esc_html__('Enter the required API credentials', 'website-ai-assistant') . '</li>';\n echo '<li>' . esc_html__('Choose the model you want to use', 'website-ai-assistant') . '</li>';\n echo '</ul>';\n }\n\n public function render_api_section(): void {\n echo '<p>' . esc_html__('API Credentials:', 'website-ai-assistant') . '</p>';\n echo '<ul class=\"waa-section-info\">';\n echo '<li>' . esc_html__('Gemini: Get your API key from Google AI Studio', 'website-ai-assistant') . '</li>';\n echo '<li>' . esc_html__('OpenAI: Get your API key from OpenAI dashboard', 'website-ai-assistant') . '</li>';\n echo '<li>' . esc_html__('Deepseek: Get your API key from Deepseek platform', 'website-ai-assistant') . '</li>';\n echo '</ul>';\n }\n\n public function render_search_section(): void {\n echo '<p>' . esc_html__('Search Provider Settings:', 'website-ai-assistant') . '</p>';\n echo '<ul class=\"waa-section-info\">';\n echo '<li>' . esc_html__('Google: Custom Search requires API key and Engine ID', 'website-ai-assistant') . '</li>';\n echo '<li>' . esc_html__('Algolia: Uses existing WordPress Algolia plugin settings', 'website-ai-assistant') . '</li>';\n echo '</ul>';\n }\n\n public function render_display_section(): void {\n echo '<p>' . esc_html__('Configure where the chat widget should appear.', 'website-ai-assistant') . '</p>';\n }\n\n\n /* Commented out duplicate method - preserved for reference\n public function render_textarea_field(array $args): void {\n $options = get_option('waa_options');\n $field = $args['field'];\n $value = $options[$field] ?? '';\n echo '<textarea name=\"waa_options[' . esc_attr($field) . ']\" class=\"large-text\" rows=\"4\">' . esc_textarea($value) . '</textarea>';\n if (!empty($args['description'])) {\n echo '<p class=\"description\">' . esc_html($args['description']) . '</p>';\n }\n }\n */\n\n public function handle_fetch_models(): void {\n error_log('Starting handle_fetch_models...');\n check_ajax_referer('waa_admin_nonce', 'nonce');\n \n if (!current_user_can('manage_options')) {\n error_log('Unauthorized access attempt in handle_fetch_models');\n wp_send_json_error(['message' => __('Unauthorized access', 'website-ai-assistant')]);\n return;\n }\n \n $provider = sanitize_text_field($_POST['provider'] ?? '');\n $api_key = sanitize_text_field($_POST['api_key'] ?? '');\n waa_debug_log('handle_fetch_models called', [\n 'provider' => $provider,\n 'has_api_key' => !empty($api_key),\n 'api_key_length' => strlen($api_key),\n 'post_data' => $_POST,\n 'request_method' => $_SERVER['REQUEST_METHOD']\n ]);\n \n $models = [];\n \n switch ($provider) {\n case 'gemini':\n $models = \\Website_Ai_Assistant\\Models\\Gemini_Service::AVAILABLE_MODELS;\n update_option('waa_gemini_models', $models);\n waa_debug_log('Using static Gemini models');\n break;\n case 'openai':\n try {\n $api_key = sanitize_text_field($_POST['api_key'] ?? '');\n waa_debug_log('OpenAI: Processing model fetch request');\n \n waa_debug_log('OpenAI: Processing fetch models request', [\n 'has_api_key' => !empty($api_key),\n 'api_key_length' => strlen($api_key),\n 'api_key_preview' => substr($api_key, 0, 10) . '...'\n ]);\n\n // Check for cached models first\n $cached_models = get_option('waa_openai_models', []);\n $cached_key_hash = get_option('waa_openai_key_hash', '');\n $current_key_hash = md5($api_key);\n \n // Use cached models if available and key matches\n if (!empty($cached_models) && $cached_key_hash === $current_key_hash) {\n $models = $cached_models;\n waa_debug_log('OpenAI: Using cached models');\n break;\n }\n \n if (empty($api_key)) {\n throw new \\Exception(__('API key is required', 'website-ai-assistant'));\n }\n \n // If no cache hit, determine whether to use cache for fetching\n $options = get_option('waa_options', []);\n $force_refresh = isset($_POST['force_refresh']) && $_POST['force_refresh'] === 'true';\n $use_cache = !$force_refresh && empty($options['openai_disable_cache']);\n\n waa_debug_log('OpenAI: Cache Settings:', [\n 'use_cache' => $use_cache,\n 'force_refresh' => $force_refresh ? 'yes' : 'no',\n 'disable_cache_setting' => !empty($options['openai_disable_cache']) ? 'yes' : 'no'\n ]);\n \n if ($use_cache) {\n $cached_models = get_option('waa_openai_models', []);\n $cached_key_hash = get_option('waa_openai_key_hash', '');\n $current_key_hash = md5($api_key);\n\n waa_debug_log('OpenAI: Cache status', [\n 'has_cached_models' => !empty($cached_models),\n 'models_count' => count($cached_models),\n 'cache_key_match' => $cached_key_hash === $current_key_hash,\n 'current_key_hash' => $current_key_hash\n ]);\n\n // Use cached models if available and key matches\n if ($cached_models && $cached_key_hash === $current_key_hash) {\n $models = $cached_models;\n waa_debug_log('OpenAI: Using cached models');\n break;\n }\n }\n \n // If we get here, either cache is disabled or we need fresh models\n waa_debug_log('OpenAI: Fetching fresh models from API');\n $openai_service = new OpenAI_Service($api_key);\n $models = $openai_service->get_available_models();\n \n // Cache the models unless this was a forced refresh\n if (!$force_refresh && !empty($models)) {\n update_option('waa_openai_models', $models);\n update_option('waa_openai_key_hash', md5($api_key));\n waa_debug_log('OpenAI: Cached new models');\n }\n\n // Set default model if none selected\n if (!empty($models)) {\n $options = get_option('waa_options', []);\n if (empty($options['openai_model'])) {\n $first_model = array_key_first($models);\n $options['openai_model'] = $first_model;\n update_option('waa_options', $options);\n waa_debug_log('OpenAI: Set default model:', $first_model);\n }\n }\n } catch (\\Exception $e) {\n wp_send_json_error(['message' => $e->getMessage()]);\n return;\n }\n break;\n case 'deepseek':\n // Check for cached models first\n $cached_models = get_option('waa_deepseek_models', []);\n $cached_key_hash = get_option('waa_deepseek_key_hash', '');\n $api_key = sanitize_text_field($_POST['api_key'] ?? '');\n $current_key_hash = md5($api_key);\n\n // Use cached models if available and key matches\n if (!empty($cached_models) && $cached_key_hash === $current_key_hash) {\n $models = $cached_models;\n waa_debug_log('Deepseek: Using cached models');\n break;\n }\n\n // If no cache hit, validate API key and fetch models\n if (empty($api_key)) {\n throw new \\Exception(__('API key is required', 'website-ai-assistant'));\n }\n\n try {\n $deepseek_service = new Deepseek_Service($api_key, Deepseek_Service::API_ENDPOINT);\n $models = $deepseek_service->get_available_models();\n \n // Cache the models and API key hash\n update_option('waa_deepseek_models', $models);\n update_option('waa_deepseek_key_hash', $current_key_hash);\n waa_debug_log('Deepseek: Cached new models');\n } catch (\\Exception $e) {\n wp_send_json_error(['message' => $e->getMessage()]);\n return;\n }\n break;\n default:\n wp_send_json_error(['message' => __('Invalid provider', 'website-ai-assistant')]);\n return;\n }\n \n wp_send_json_success(['models' => $models]);\n }\n\n /* Commented out duplicate method - preserved for reference\n public function render_select_field(array $args): void {\n $options = get_option('waa_options');\n $field = $args['field'];\n $value = $options[$field] ?? $args['default'] ?? '';\n \n echo '<select name=\"waa_options[' . esc_attr($field) . ']\" id=\"waa_options_' . esc_attr($field) . '\">';\n foreach ($args['options'] as $key => $label) {\n echo '<option value=\"' . esc_attr($key) . '\" ' . selected($value, $key, false) . '>';\n echo esc_html($label);\n echo '</option>';\n }\n echo '</select>';\n \n if (!empty($args['description'])) {\n echo '<p class=\"description\">' . esc_html($args['description']) . '</p>';\n }\n }\n */\n\n public function render_checkbox_field(array $args): void {\n $options = get_option('waa_options');\n $field = $args['field'];\n $checked = isset($options[$field]) && $options[$field] ? 'checked' : '';\n \n echo '<input type=\"checkbox\" name=\"waa_options[' . esc_attr($field) . ']\" ' . $checked . ' value=\"1\">';\n if (!empty($args['description'])) {\n echo '<p class=\"description\">' . esc_html($args['description']) . '</p>';\n }\n }\n\n public function render_display_locations_field(): void {\n $options = get_option('waa_options', []);\n $locations = $options['display_locations'] ?? ['all'];\n ?>\n <fieldset>\n <label>\n <input type=\"checkbox\" name=\"waa_options[display_locations][]\"\n value=\"all\" <?php checked(in_array('all', $locations)); ?>>\n <?php esc_html_e('All Pages', 'website-ai-assistant'); ?>\n </label><br>\n <label>\n <input type=\"checkbox\" name=\"waa_options[display_locations][]\"\n value=\"home\" <?php checked(in_array('home', $locations)); ?>>\n <?php esc_html_e('Home Page', 'website-ai-assistant'); ?>\n </label><br>\n <label>\n <input type=\"checkbox\" name=\"waa_options[display_locations][]\"\n value=\"posts\" <?php checked(in_array('posts', $locations)); ?>>\n <?php esc_html_e('Blog Posts', 'website-ai-assistant'); ?>\n </label><br>\n <label>\n <input type=\"checkbox\" name=\"waa_options[display_locations][]\"\n value=\"pages\" <?php checked(in_array('pages', $locations)); ?>>\n <?php esc_html_e('Pages', 'website-ai-assistant'); ?>\n </label><br>\n <label>\n <input type=\"checkbox\" name=\"waa_options[display_locations][]\"\n value=\"products\" <?php checked(in_array('products', $locations)); ?>>\n <?php esc_html_e('Products', 'website-ai-assistant'); ?>\n </label>\n </fieldset>\n <?php\n }\n\n public function enqueue_admin_assets($hook): void {\n // Only load on our settings page\n if ('settings_page_website-ai-assistant' !== $hook) {\n return;\n }\n\n wp_enqueue_style(\n 'waa-admin-styles',\n WAA_PLUGIN_URL . 'admin/css/admin-settings.css',\n [],\n WAA_VERSION\n );\n\n wp_enqueue_script(\n 'waa-admin-scripts',\n WAA_PLUGIN_URL . 'admin/js/admin-settings.js',\n ['jquery'],\n WAA_VERSION,\n true\n );\n\n wp_localize_script('waa-admin-scripts', 'waaAdmin', [\n 'ajaxUrl' => admin_url('admin-ajax.php'),\n 'nonce' => wp_create_nonce('waa_admin_nonce'),\n 'i18n' => [\n 'loadingModels' => __('Loading available models...', 'website-ai-assistant'),\n 'enterApiKey' => __('Please enter API key first', 'website-ai-assistant'),\n 'selectModel' => __('Select a model', 'website-ai-assistant'),\n 'fetchError' => __('Failed to fetch models', 'website-ai-assistant'),\n 'noModelsFound' => __('No available models found', 'website-ai-assistant'),\n 'fetchingModels' => __('Fetching available models...', 'website-ai-assistant')\n ]\n ]);\n }\n\n public function sanitize_options($input): array {\n waa_debug_log('Sanitizing input options:', [\n 'ai_provider' => $input['ai_provider'] ?? 'not set',\n 'search_provider' => $input['search_provider'] ?? 'not set',\n 'fields_present' => array_keys($input)\n ]);\n\n // Get existing options to preserve any values not in current input\n $existing = get_option('waa_options', []);\n $sanitized = $existing;\n\n // Handle search provider changes\n if (isset($input['search_provider'])) {\n $search_provider = sanitize_text_field($input['search_provider']);\n if (in_array($search_provider, ['google', 'algolia'])) {\n $old_provider = $existing['search_provider'] ?? 'google';\n $sanitized['search_provider'] = $search_provider;\n \n waa_debug_log('Search provider updated:', [\n 'from' => $old_provider,\n 'to' => $search_provider\n ]);\n\n // Only clear settings if they're explicitly empty in the input\n if ($search_provider === 'google') {\n // When switching to Google, preserve existing Algolia settings\n $sanitized['google_search_api_key'] = $input['google_search_api_key'] ?? $existing['google_search_api_key'] ?? '';\n $sanitized['search_engine_id'] = $input['search_engine_id'] ?? $existing['search_engine_id'] ?? '';\n } else if ($search_provider === 'algolia') {\n // When switching to Algolia, preserve existing Google settings\n $sanitized['algolia_app_id'] = $input['algolia_app_id'] ?? $existing['algolia_app_id'] ?? '';\n $sanitized['algolia_search_key'] = $input['algolia_search_key'] ?? $existing['algolia_search_key'] ?? '';\n $sanitized['algolia_admin_key'] = $input['algolia_admin_key'] ?? $existing['algolia_admin_key'] ?? '';\n $sanitized['algolia_index'] = $input['algolia_index'] ?? $existing['algolia_index'] ?? '';\n }\n \n waa_debug_log('Settings after provider change:', [\n 'provider' => $search_provider,\n 'has_google_key' => isset($sanitized['google_search_api_key']),\n 'has_algolia_key' => isset($sanitized['algolia_search_key'])\n ]);\n }\n }\n \n $field_types = [\n 'url' => ['deepseek_endpoint'],\n 'key' => [\n 'gemini_api_key', 'openai_api_key', 'deepseek_api_key',\n 'google_search_api_key', 'search_engine_id',\n 'algolia_app_id', 'algolia_search_key', 'algolia_admin_key'\n ],\n 'text' => ['algolia_index']\n ];\n\n // Process each field type\n foreach ($field_types as $type => $fields) {\n foreach ($fields as $field) {\n if (!isset($input[$field])) continue;\n\n switch ($type) {\n case 'url':\n $sanitized[$field] = esc_url_raw(rtrim($input[$field], '/') . '/');\n break;\n case 'key':\n case 'text':\n $sanitized[$field] = sanitize_text_field($input[$field]);\n if ($type === 'text') {\n waa_debug_log(\"Sanitizing text field: $field\", [\n 'input_value' => $input[$field],\n 'sanitized_value' => $sanitized[$field]\n ]);\n }\n break;\n }\n }\n }\n\n // Provider and model fields\n $provider_model_fields = [\n 'ai_provider',\n 'openai_model',\n 'gemini_model',\n 'deepseek_model',\n 'search_provider',\n 'system_message'\n ];\n\n foreach ($provider_model_fields as $field) {\n if (isset($input[$field])) {\n $sanitized[$field] = sanitize_text_field($input[$field]);\n waa_debug_log(\"Sanitized $field:\", $sanitized[$field]);\n } else {\n waa_debug_log(\"Field not found in input: $field\");\n $sanitized[$field] = '';\n }\n }\n\n // Add special handling for provider-specific model fields\n $provider = $sanitized['ai_provider'] ?? '';\n if ($provider) {\n $model_field = $provider . '_model';\n waa_debug_log(\"Checking provider-specific model field: $model_field\", [\n 'value' => $sanitized[$model_field] ?? 'not set',\n 'provider' => $provider\n ]);\n }\n\n // Handle display locations array\n if (isset($input['display_locations']) && is_array($input['display_locations'])) {\n $sanitized['display_locations'] = array_map('sanitize_text_field', $input['display_locations']);\n } else {\n $sanitized['display_locations'] = ['all']; // Default to all pages if not set\n }\n\n // Handle debug option\n $sanitized['enable_debug'] = isset($input['enable_debug']) ? 1 : 0;\n\n // Sanitize lead generation fields\n $lead_fields = [\n 'enable_lead_collection' => 'bool',\n 'lead_collection_timing' => 'text',\n 'lead_collection_heading' => 'text',\n 'lead_collection_description' => 'text',\n 'fluentcrm_list_id' => 'int',\n 'fluentcrm_tag_id' => 'int',\n 'fluentcrm_status' => 'text'\n ];\n\n foreach ($lead_fields as $field => $type) {\n if (isset($input[$field])) {\n switch ($type) {\n case 'bool':\n $sanitized[$field] = (bool) $input[$field];\n break;\n case 'int':\n $sanitized[$field] = absint($input[$field]);\n break;\n case 'text':\n $sanitized[$field] = sanitize_text_field($input[$field]);\n break;\n }\n }\n }\n\n return $sanitized;\n }\n\n}\n"}, "43f4fa331b6e5efcda109c72c11afecee008edfb": {"t": 1785756321.2304368, "n": 27801, "h": "5388789266ff3622", "c": "<?php\nnamespace Website_Ai_Assistant\\Admin;\n\nclass Admin_Settings {\n private const OPTION_GROUP = 'waa_options';\n private const SETTINGS_PAGE = 'website-ai-assistant';\n\n public function __construct() {\n add_action('admin_menu', [$this, 'add_settings_page']);\n add_action('admin_init', [$this, 'register_settings']);\n add_action('admin_enqueue_scripts', [$this, 'enqueue_admin_assets']);\n }\n\n public function add_settings_page(): void {\n add_options_page(\n __('Website AI Assistant Settings', 'website-ai-assistant'),\n __('Website AI Assistant', 'website-ai-assistant'),\n 'manage_options',\n self::SETTINGS_PAGE,\n [$this, 'render_settings_page']\n );\n }\n\n public function register_settings(): void {\n register_setting(\n 'waa_options',\n 'waa_options',\n [\n 'sanitize_callback' => [$this, 'sanitize_options'],\n 'default' => []\n ]\n );\n\n // API Settings section\n add_settings_section(\n 'waa_api_settings',\n __('API Settings', 'website-ai-assistant'),\n [$this, 'render_api_section'],\n 'website-ai-assistant'\n );\n\n // Search Provider selector\n add_settings_field(\n 'search_provider',\n __('Search Provider', 'website-ai-assistant'),\n [$this, 'render_select_field'],\n 'website-ai-assistant',\n 'waa_api_settings',\n [\n 'field' => 'search_provider',\n 'options' => [\n 'google' => __('Google Custom Search', 'website-ai-assistant'),\n 'algolia' => __('Algolia (WordPress Plugin)', 'website-ai-assistant')\n ],\n 'default' => 'google',\n 'description' => __('Select which search provider to use. Algolia requires the Algolia Search plugin to be installed and configured.', 'website-ai-assistant')\n ]\n );\n\n // Gemini API Key field\n add_settings_field(\n 'gemini_api_key',\n __('Gemini API Key', 'website-ai-assistant'),\n [$this, 'render_text_field'],\n 'website-ai-assistant',\n 'waa_api_settings',\n [\n 'label_for' => 'gemini_api_key',\n 'field_name' => 'gemini_api_key',\n 'type' => 'password'\n ]\n );\n\n // Google Search Fields\n add_settings_field(\n 'google_search_api_key',\n __('Google Search API Key', 'website-ai-assistant'),\n [$this, 'render_text_field'],\n 'website-ai-assistant',\n 'waa_api_settings',\n [\n 'label_for' => 'google_search_api_key',\n 'field_name' => 'google_search_api_key',\n 'type' => 'password',\n 'class' => 'google-search-field'\n ]\n );\n\n add_settings_field(\n 'search_engine_id',\n __('Search Engine ID', 'website-ai-assistant'),\n [$this, 'render_text_field'],\n 'website-ai-assistant',\n 'waa_api_settings',\n [\n 'label_for' => 'search_engine_id',\n 'field_name' => 'search_engine_id',\n 'type' => 'text',\n 'class' => 'google-search-field'\n ]\n );\n\n // Algolia Fields\n add_settings_field(\n 'algolia_app_id',\n __('Algolia Application ID', 'website-ai-assistant'),\n [$this, 'render_text_field'],\n 'website-ai-assistant',\n 'waa_api_settings',\n [\n 'label_for' => 'algolia_app_id',\n 'field_name' => 'algolia_app_id',\n 'type' => 'text',\n 'class' => 'algolia-field'\n ]\n );\n\n add_settings_field(\n 'algolia_search_key',\n __('Algolia Search API Key', 'website-ai-assistant'),\n [$this, 'render_text_field'],\n 'website-ai-assistant',\n 'waa_api_settings',\n [\n 'label_for' => 'algolia_search_key',\n 'field_name' => 'algolia_search_key',\n 'type' => 'password',\n 'class' => 'algolia-field'\n ]\n );\n\n add_settings_field(\n 'algolia_admin_key',\n __('Algolia Admin API Key', 'website-ai-assistant'),\n [$this, 'render_text_field'],\n 'website-ai-assistant',\n 'waa_api_settings',\n [\n 'label_for' => 'algolia_admin_key',\n 'field_name' => 'algolia_admin_key',\n 'type' => 'password',\n 'class' => 'algolia-field'\n ]\n );\n\n add_settings_field(\n 'system_message',\n __('System Message', 'website-ai-assistant'),\n [$this, 'render_textarea_field'],\n self::SETTINGS_PAGE,\n 'waa_api_settings',\n ['field' => 'system_message']\n );\n\n add_settings_field(\n 'max_history',\n __('Max Conversation History', 'website-ai-assistant'),\n [$this, 'render_number_field'],\n self::SETTINGS_PAGE,\n 'waa_api_settings',\n ['field' => 'max_history']\n );\n\n // Add Website Topics field after system message\n add_settings_field(\n 'website_topics',\n __('Website Topics', 'website-ai-assistant'),\n [$this, 'render_textarea_field'],\n self::SETTINGS_PAGE,\n 'waa_api_settings',\n [\n 'field' => 'website_topics',\n 'description' => __('Enter the main topics or subjects your website covers (e.g., \"hydroponics, indoor gardening, plant care\"). This helps the AI understand which questions it should answer in detail.', 'website-ai-assistant')\n ]\n );\n\n // Add new section for Display Settings\n add_settings_section(\n 'waa_display_settings',\n __('Display Settings', 'website-ai-assistant'),\n [$this, 'render_display_section'],\n self::SETTINGS_PAGE\n );\n\n // Add display location field\n add_settings_field(\n 'display_locations',\n __('Show Chat Widget On', 'website-ai-assistant'),\n [$this, 'render_display_locations_field'],\n self::SETTINGS_PAGE,\n 'waa_display_settings'\n );\n\n // Add new section for Lead Collection Settings\n add_settings_section(\n 'waa_lead_settings',\n __('Lead Collection Settings', 'website-ai-assistant'),\n [$this, 'render_lead_section'],\n self::SETTINGS_PAGE\n );\n\n // Add lead collection fields\n add_settings_field(\n 'enable_lead_collection',\n __('Enable Lead Collection', 'website-ai-assistant'),\n [$this, 'render_checkbox_field'],\n self::SETTINGS_PAGE,\n 'waa_lead_settings',\n ['field' => 'enable_lead_collection']\n );\n\n add_settings_field(\n 'lead_collection_timing',\n __('Ask for Contact Info', 'website-ai-assistant'),\n [$this, 'render_select_field'],\n self::SETTINGS_PAGE,\n 'waa_lead_settings',\n [\n 'field' => 'lead_collection_timing',\n 'options' => [\n 'immediate' => __('At the start of conversation', 'website-ai-assistant'),\n 'after_first' => __('After first message', 'website-ai-assistant'),\n 'after_two' => __('After two messages', 'website-ai-assistant'),\n 'end' => __('At end of conversation', 'website-ai-assistant')\n ]\n ]\n );\n\n // FluentCRM List field with priority 10\n add_settings_field(\n 'fluentcrm_list_id',\n __('FluentCRM List', 'website-ai-assistant'),\n [$this, 'render_fluentcrm_lists_field'],\n self::SETTINGS_PAGE,\n 'waa_lead_settings',\n [\n 'field' => 'fluentcrm_list_id',\n 'priority' => 10\n ]\n );\n\n // FluentCRM Tag field with priority 11\n add_settings_field(\n 'fluentcrm_tag_id',\n __('FluentCRM Tag', 'website-ai-assistant'),\n [$this, 'render_fluentcrm_tags_field'],\n self::SETTINGS_PAGE,\n 'waa_lead_settings',\n [\n 'field' => 'fluentcrm_tag_id',\n 'priority' => 11\n ]\n );\n\n // Add after the FluentCRM tag field\n add_settings_field(\n 'fluentcrm_status',\n __('Contact Status', 'website-ai-assistant'),\n [$this, 'render_select_field'],\n self::SETTINGS_PAGE,\n 'waa_lead_settings',\n [\n 'field' => 'fluentcrm_status',\n 'options' => [\n 'subscribed' => __('Subscribed', 'website-ai-assistant'),\n 'pending' => __('Pending', 'website-ai-assistant')\n ],\n 'description' => __('Status for new contacts in FluentCRM', 'website-ai-assistant'),\n 'default' => 'subscribed'\n ]\n );\n\n // Add lead collection message fields\n add_settings_field(\n 'lead_collection_heading',\n __('Lead Collection Heading', 'website-ai-assistant'),\n [$this, 'render_text_field'],\n self::SETTINGS_PAGE,\n 'waa_lead_settings',\n [\n 'field' => 'lead_collection_heading',\n 'description' => __('The heading shown above the contact form', 'website-ai-assistant'),\n 'default' => __('Please share your contact info to continue', 'website-ai-assistant')\n ]\n );\n\n add_settings_field(\n 'lead_collection_description',\n __('Lead Collection Description', 'website-ai-assistant'),\n [$this, 'render_textarea_field'],\n self::SETTINGS_PAGE,\n 'waa_lead_settings',\n [\n 'field' => 'lead_collection_description',\n 'description' => __('Optional description text shown below the heading', 'website-ai-assistant')\n ]\n );\n\n add_settings_field(\n 'privacy_page_url',\n __('Privacy Policy URL', 'website-ai-assistant'),\n [$this, 'render_privacy_page_field'],\n self::SETTINGS_PAGE,\n 'waa_lead_settings',\n [\n 'description' => __('Select your privacy policy page or enter a custom URL', 'website-ai-assistant')\n ]\n );\n\n add_settings_field(\n 'privacy_text',\n __('Privacy Notice Text', 'website-ai-assistant'),\n [$this, 'render_text_field'],\n self::SETTINGS_PAGE,\n 'waa_lead_settings',\n [\n 'field' => 'privacy_text',\n 'description' => __('Text shown with privacy policy link. Use {privacy_policy} for the link.', 'website-ai-assistant'),\n 'default' => __('By continuing, you agree to our {privacy_policy}.', 'website-ai-assistant')\n ]\n );\n\n // Add in register_settings() method after other settings\n add_settings_field(\n 'enable_debug',\n __('Enable Debug Logging', 'website-ai-assistant'),\n [$this, 'render_checkbox_field'],\n self::SETTINGS_PAGE,\n 'waa_api_settings',\n [\n 'field' => 'enable_debug',\n 'description' => __('Log debug information to wp-content/debug.log', 'website-ai-assistant')\n ]\n );\n }\n\n public function render_settings_page(): void {\n if (!current_user_can('manage_options')) {\n return;\n }\n require_once WAA_PLUGIN_DIR . 'admin/views/settings-page.php';\n }\n\n public function enqueue_admin_assets($hook): void {\n if (\"settings_page_\" . self::SETTINGS_PAGE !== $hook) {\n return;\n }\n\n wp_enqueue_style(\n 'waa-admin-settings',\n WAA_PLUGIN_URL . 'admin/css/admin-settings.css',\n [],\n WAA_VERSION\n );\n\n wp_enqueue_script(\n 'waa-admin-settings',\n WAA_PLUGIN_URL . 'admin/js/admin-settings.js',\n ['jquery'],\n WAA_VERSION,\n true\n );\n\n // Add AJAX data for the test buttons\n wp_localize_script('waa-admin-settings', 'waaAdmin', [\n 'ajaxUrl' => admin_url('admin-ajax.php'),\n 'nonce' => wp_create_nonce('waa_admin_nonce'),\n 'testGemini' => __('Testing Gemini API...', 'website-ai-assistant'),\n 'testSearch' => __('Testing Search API...', 'website-ai-assistant'),\n 'enterQuery' => __('Please enter a search query to test.', 'website-ai-assistant'),\n 'ajaxError' => __('Network error occurred. Please try again.', 'website-ai-assistant'),\n 'missingSearchCreds' => __('Please enter both Google Search API key and Search Engine ID.', 'website-ai-assistant'),\n ]);\n }\n\n /**\n * Renders a text field for the settings page\n *\n * @param array $args Field arguments\n */\n public function render_text_field($args): void {\n $options = get_option('waa_options', []);\n $field_name = $args['field'] ?? $args['field_name'] ?? '';\n $field_type = $args['type'] ?? 'text';\n $value = $options[$field_name] ?? $args['default'] ?? '';\n ?>\n <input \n type=\"<?php echo esc_attr($field_type); ?>\"\n id=\"<?php echo esc_attr($field_name); ?>\"\n name=\"waa_options[<?php echo esc_attr($field_name); ?>]\"\n value=\"<?php echo esc_attr($value); ?>\"\n class=\"regular-text\"\n />\n <?php\n }\n\n /**\n * Renders a textarea field for the settings page\n *\n * @param array $args Field arguments\n */\n public function render_textarea_field(array $args): void {\n $options = get_option('waa_options');\n $field = $args['field'];\n $value = $options[$field] ?? '';\n echo '<textarea name=\"waa_options[' . esc_attr($field) . ']\" class=\"large-text\" rows=\"4\">' . esc_textarea($value) . '</textarea>';\n if ($field === 'system_message') {\n echo '<p class=\"description\">' . esc_html__('This message sets the AI\\'s behavior and tone. Leave blank for default.', 'website-ai-assistant') . '</p>';\n }\n }\n\n /**\n * Renders a number field for the settings page\n *\n * @param array $args Field arguments\n */\n public function render_number_field(array $args): void {\n $options = get_option('waa_options');\n $field = $args['field'];\n $value = $options[$field] ?? 10;\n echo '<input type=\"number\" name=\"waa_options[' . esc_attr($field) . ']\" value=\"' . esc_attr($value) . '\" class=\"small-text\" min=\"1\">';\n if ($field === 'max_history') {\n echo '<p class=\"description\">' . esc_html__('Maximum number of messages to keep in conversation history. Default is 10.', 'website-ai-assistant') . '</p>';\n }\n }\n\n /**\n * Renders the API settings section description\n */\n public function render_api_section(): void {\n echo '<p>' . esc_html__('Configure your AI Assistant settings below. You\\'ll need a Gemini API key to use this plugin.', 'website-ai-assistant') . '</p>';\n }\n\n /**\n * Validates and sanitizes the options before saving\n *\n * @param array $input The raw input array\n * @return array The sanitized output array\n */\n public function sanitize_options($input) {\n // Debug logging\n error_log('Sanitizing options - Input: ' . print_r($input, true));\n \n $sanitized = [];\n \n // Handle API keys\n // Process API keys\n $api_fields = ['gemini_api_key', 'google_search_api_key', 'search_engine_id'];\n foreach ($api_fields as $field) {\n $sanitized[$field] = isset($input[$field]) ? sanitize_text_field($input[$field]) : '';\n }\n\n // Process lead collection settings\n $lead_fields = [\n 'enable_lead_collection' => 'bool',\n 'lead_collection_timing' => 'text',\n 'fluentcrm_list_id' => 'int',\n 'fluentcrm_tag_id' => 'int',\n 'fluentcrm_status' => 'text',\n 'lead_collection_heading' => 'text',\n 'lead_collection_description' => 'textarea',\n 'privacy_page_url' => 'url',\n 'privacy_text' => 'text'\n ];\n\n foreach ($lead_fields as $field => $type) {\n switch ($type) {\n case 'bool':\n $sanitized[$field] = isset($input[$field]) ? 1 : 0;\n break;\n case 'int':\n $sanitized[$field] = isset($input[$field]) ? absint($input[$field]) : 0;\n break;\n case 'url':\n $sanitized[$field] = isset($input[$field]) ? esc_url_raw($input[$field]) : '';\n break;\n case 'textarea':\n $sanitized[$field] = isset($input[$field]) ? sanitize_textarea_field($input[$field]) : '';\n break;\n default:\n $sanitized[$field] = isset($input[$field]) ? sanitize_text_field($input[$field]) : '';\n }\n }\n\n // Merge with existing options while preserving unrelated settings\n $existing = get_option('waa_options', []);\n // Merge with new sanitized values taking priority over existing ones\n $sanitized = array_merge($existing, $sanitized);\n $sanitized = array_merge($sanitized, $input);\n \n // Debug logging\n error_log('Sanitized options: ' . print_r($sanitized, true));\n \n return $sanitized;\n }\n\n public function render_display_section(): void {\n echo '<p>' . esc_html__('Configure where the chat widget should appear on your website.', 'website-ai-assistant') . '</p>';\n }\n\n public function render_display_locations_field(): void {\n $options = get_option('waa_options', []);\n $locations = $options['display_locations'] ?? ['all'];\n ?>\n <fieldset>\n <label>\n <input type=\"checkbox\" name=\"waa_options[display_locations][]\" \n value=\"all\" <?php checked(in_array('all', $locations)); ?>>\n <?php esc_html_e('All Pages', 'website-ai-assistant'); ?>\n </label><br>\n \n <label>\n <input type=\"checkbox\" name=\"waa_options[display_locations][]\" \n value=\"home\" <?php checked(in_array('home', $locations)); ?>>\n <?php esc_html_e('Homepage Only', 'website-ai-assistant'); ?>\n </label><br>\n \n <label>\n <input type=\"checkbox\" name=\"waa_options[display_locations][]\" \n value=\"posts\" <?php checked(in_array('posts', $locations)); ?>>\n <?php esc_html_e('Posts', 'website-ai-assistant'); ?>\n </label><br>\n \n <label>\n <input type=\"checkbox\" name=\"waa_options[display_locations][]\" \n value=\"pages\" <?php checked(in_array('pages', $locations)); ?>>\n <?php esc_html_e('Pages', 'website-ai-assistant'); ?>\n </label><br>\n \n <label>\n <input type=\"checkbox\" name=\"waa_options[display_locations][]\" \n value=\"products\" <?php checked(in_array('products', $locations)); ?>>\n <?php esc_html_e('Products', 'website-ai-assistant'); ?>\n </label>\n </fieldset>\n <p class=\"description\">\n <?php esc_html_e('Select where you want the chat widget to appear. \"All Pages\" will override other selections.', 'website-ai-assistant'); ?>\n </p>\n <?php\n }\n\n public function render_lead_section(): void {\n echo '<p>' . esc_html__('Configure settings for collecting user contact information.', 'website-ai-assistant') . '</p>';\n }\n\n public function render_checkbox_field(array $args): void {\n $options = get_option('waa_options');\n $field = $args['field'];\n $checked = (isset($options[$field]) && $options[$field] == 1) ? 'checked' : '';\n \n echo '<input type=\"checkbox\" name=\"waa_options[' . esc_attr($field) . ']\" ' . $checked . ' value=\"1\">';\n }\n\n public function render_select_field(array $args): void {\n $options = get_option('waa_options');\n $field = $args['field'];\n $value = $options[$field] ?? '';\n \n echo '<select name=\"waa_options[' . esc_attr($field) . ']\">';\n foreach ($args['options'] as $key => $label) {\n echo '<option value=\"' . esc_attr($key) . '\" ' . selected($value, $key, false) . '>';\n echo esc_html($label);\n echo '</option>';\n }\n echo '</select>';\n }\n\n /**\n * Renders the FluentCRM lists dropdown\n */\n public function render_fluentcrm_lists_field(array $args): void {\n $options = get_option('waa_options');\n $field = $args['field'];\n $selected_list = $options[$field] ?? '';\n \n if (!function_exists('FluentCrmApi')) {\n echo '<p class=\"description error\">' . \n esc_html__('FluentCRM is not installed or activated.', 'website-ai-assistant') . \n '</p>';\n return;\n }\n\n try {\n $lists = FluentCrmApi('lists')->all();\n \n if (empty($lists)) {\n echo '<p class=\"description\">' . \n esc_html__('No lists found in FluentCRM. Please create a list first.', 'website-ai-assistant') . \n '</p>';\n return;\n }\n\n echo '<select name=\"waa_options[fluentcrm_list_id]\" class=\"regular-text\">';\n echo '<option value=\"\">' . esc_html__('Select a list...', 'website-ai-assistant') . '</option>';\n \n foreach ($lists as $list) {\n echo sprintf(\n '<option value=\"%s\" %s>%s (%d subscribers)</option>',\n esc_attr($list->id),\n selected($selected_list, $list->id, false),\n esc_html($list->title),\n intval($list->subscribers_count)\n );\n }\n \n echo '</select>';\n echo '<p class=\"description\">' . \n esc_html__('Select the FluentCRM list where leads will be added.', 'website-ai-assistant') . \n '</p>';\n\n } catch (\\Exception $e) {\n echo '<p class=\"description error\">' . \n esc_html__('Error loading FluentCRM lists. Please check if FluentCRM is configured correctly.', 'website-ai-assistant') . \n '</p>';\n }\n }\n\n /**\n * Renders the FluentCRM tags dropdown\n */\n public function render_fluentcrm_tags_field(array $args): void {\n $options = get_option('waa_options');\n $field = $args['field'];\n $selected_tag = $options[$field] ?? '';\n \n if (!function_exists('FluentCrmApi')) {\n echo '<p class=\"description error\">' . \n esc_html__('FluentCRM is not installed or activated.', 'website-ai-assistant') . \n '</p>';\n return;\n }\n\n try {\n $tags = FluentCrmApi('tags')->all();\n \n if (empty($tags)) {\n echo '<p class=\"description\">' . \n esc_html__('No tags found in FluentCRM. Please create a tag first.', 'website-ai-assistant') . \n '</p>';\n return;\n }\n\n echo '<select name=\"waa_options[fluentcrm_tag_id]\" class=\"regular-text\">';\n echo '<option value=\"\">' . esc_html__('Select a tag...', 'website-ai-assistant') . '</option>';\n \n foreach ($tags as $tag) {\n echo sprintf(\n '<option value=\"%s\" %s>%s (%d subscribers)</option>',\n esc_attr($tag->id),\n selected($selected_tag, $tag->id, false),\n esc_html($tag->title),\n intval($tag->subscribers_count)\n );\n }\n \n echo '</select>';\n echo '<p class=\"description\">' . \n esc_html__('Select the FluentCRM tag to apply to new contacts.', 'website-ai-assistant') . \n '</p>';\n\n } catch (\\Exception $e) {\n echo '<p class=\"description error\">' . \n esc_html__('Error loading FluentCRM tags.', 'website-ai-assistant') . \n '</p>';\n }\n }\n\n /**\n * Renders the privacy page selector\n */\n public function render_privacy_page_field(array $args): void {\n $options = get_option('waa_options');\n $current_url = $options['privacy_page_url'] ?? '';\n \n // Get list of pages\n $pages = get_pages(['sort_column' => 'post_title']);\n \n echo '<select id=\"waa_privacy_page_select\" name=\"waa_options[privacy_page_url]\" class=\"regular-text\">';\n echo '<option value=\"\">' . esc_html__('Select a page...', 'website-ai-assistant') . '</option>';\n \n foreach ($pages as $page) {\n $page_url = get_permalink($page->ID);\n echo sprintf(\n '<option value=\"%s\" %s>%s</option>',\n esc_attr($page_url),\n selected($current_url, $page_url, false),\n esc_html($page->post_title)\n );\n }\n echo '</select>';\n \n // Custom URL input\n echo '<div style=\"margin-top: 10px;\">';\n echo '<input type=\"text\" id=\"waa_privacy_page_custom\" ';\n echo 'name=\"waa_options[privacy_page_url_custom]\" ';\n echo 'value=\"' . esc_attr($current_url) . '\" ';\n echo 'class=\"regular-text\" placeholder=\"' . esc_attr__('Or enter custom URL', 'website-ai-assistant') . '\">';\n echo '</div>';\n \n if (!empty($args['description'])) {\n echo '<p class=\"description\">' . esc_html($args['description']) . '</p>';\n }\n }\n\n /**\n * Updates the system message to include website topics\n */\n private function get_system_message(): string {\n $options = get_option('waa_options', []);\n $topics = $options['website_topics'] ?? '';\n \n $system_message = __(\n 'You are an AI assistant specifically focused on helping with questions about this website. ',\n 'website-ai-assistant'\n );\n \n if (!empty($topics)) {\n $system_message .= sprintf(\n __('This website focuses on the following topics: %s. ', 'website-ai-assistant'),\n $topics\n );\n }\n \n $system_message .= __(\n 'For questions directly related to these topics and website content, provide detailed answers with relevant links. ' .\n 'For unrelated questions, politely explain that you are specifically here to help with website-related questions and provide only a brief, general response without links.',\n 'website-ai-assistant'\n );\n \n return $system_message;\n }\n} "}}}}