prefix . 'cloudprime_chat_logs';
$charset_collate = $wpdb->get_charset_collate();
$sql = "CREATE TABLE $table_name (
id mediumint(9) NOT NULL AUTO_INCREMENT,
session_id varchar(32) NOT NULL,
user_message text NOT NULL,
ai_response text NOT NULL,
contact_info text DEFAULT NULL,
whmcs_client_id int DEFAULT NULL,
ai_provider varchar(20) DEFAULT 'openrouter',
created_at datetime DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id)
) $charset_collate;";
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
dbDelta($sql);
// Contacts table
$table_name = $wpdb->prefix . 'cloudprime_contacts';
$sql = "CREATE TABLE $table_name (
id mediumint(9) NOT NULL AUTO_INCREMENT,
session_id varchar(32) NOT NULL,
name varchar(255) NOT NULL,
phone varchar(50) NOT NULL,
email varchar(255) DEFAULT NULL,
whmcs_client_id int DEFAULT NULL,
source varchar(50) DEFAULT 'chatbot',
created_at datetime DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id)
) $charset_collate;";
dbDelta($sql);
// Visitor tracking table
$table_name = $wpdb->prefix . 'cloudprime_visitors';
$sql = "CREATE TABLE $table_name (
id BIGINT NOT NULL AUTO_INCREMENT,
ip VARCHAR(45),
user_agent TEXT,
referrer TEXT,
landing_page VARCHAR(512),
geo_country CHAR(3),
geo_city VARCHAR(100),
session_id VARCHAR(64),
first_seen DATETIME DEFAULT CURRENT_TIMESTAMP,
last_seen DATETIME DEFAULT CURRENT_TIMESTAMP,
page_views INT DEFAULT 1,
PRIMARY KEY (id),
KEY session_idx (session_id)
) $charset_collate;";
dbDelta($sql);
cloudprime_debug_log('Enhanced tables created with WHMCS integration');
}
// Admin menu
add_action('admin_menu', function() {
add_menu_page(
'CloudPrime Chatbot',
'CloudPrime Chatbot',
'manage_options',
'cloudprime-chatbot',
'cloudprime_chatbot_admin_page_content',
'dashicons-format-chat',
6
);
add_submenu_page(
'cloudprime-chatbot',
'Chat Logs',
'Chat Logs',
'manage_options',
'cloudprime-chat-logs',
'cloudprime_chatbot_logs_page'
);
add_submenu_page(
'cloudprime-chatbot',
'Contacts',
'Contacts',
'manage_options',
'cloudprime-contacts',
'cloudprime_chatbot_contacts_page'
);
add_submenu_page(
'cloudprime-chatbot',
'WHMCS Settings',
'WHMCS Settings',
'manage_options',
'cloudprime-whmcs',
'cloudprime_whmcs_settings_page'
);
/* NEW: Visitor analytics page */
add_submenu_page(
'cloudprime-chatbot',
'Visitor Analytics',
'Visitor Analytics',
'manage_options',
'cloudprime-analytics',
'cloudprime_analytics_page'
);
});
/* ---------- NEW: Visitor analytics page handler ---------- */
function cloudprime_analytics_page() {
global $wpdb;
$rows = $wpdb->get_results("SELECT * FROM {$wpdb->prefix}cloudprime_visitors ORDER BY last_seen DESC LIMIT 1000");
?>
Visitor Analytics
Export CSV
| IP | Country | City | Landing | Views | Last Seen |
| ip); ?> |
geo_country); ?> |
geo_city); ?> |
landing_page, 5)); ?> |
page_views; ?> |
last_seen); ?> |
get_results("SELECT * FROM {$wpdb->prefix}cloudprime_visitors", ARRAY_A);
header('Content-Type: text/csv');
header('Content-Disposition: attachment;filename=visitors.csv');
$out = fopen('php://output', 'w');
fputcsv($out, array_keys($rows[0] ?? []));
foreach ($rows as $r) fputcsv($out, $r);
fclose($out);
exit;
});
function cloudprime_chatbot_admin_page_content() {
// Handle form submission
if (isset($_POST['submit'])) {
$settings = [
'ai_provider' => sanitize_text_field($_POST['ai_provider'] ?? 'openrouter'),
'openrouter_api_key' => sanitize_text_field($_POST['openrouter_api_key'] ?? ''),
'gemini_api_key' => sanitize_text_field($_POST['gemini_api_key'] ?? ''),
'whatsapp_number' => sanitize_text_field($_POST['whatsapp_number'] ?? ''),
'ai_name' => sanitize_text_field($_POST['ai_name'] ?? 'CloudPrime Assistant'),
'ai_avatar_url' => esc_url_raw($_POST['ai_avatar_url'] ?? ''),
'predefined_questions_setting' => sanitize_textarea_field($_POST['predefined_questions_setting'] ?? ''),
'enable_conditional_whatsapp' => isset($_POST['enable_conditional_whatsapp']) ? 1 : 0,
'notification_email' => sanitize_email($_POST['notification_email'] ?? get_option('admin_email')),
'enable_whmcs_integration' => isset($_POST['enable_whmcs_integration']) ? 1 : 0,
'enable_voice_commands' => isset($_POST['enable_voice_commands']) ? 1 : 0
];
update_option('cloudprime_chatbot_settings', $settings);
echo 'Settings saved successfully!
';
}
$opts = get_option('cloudprime_chatbot_settings', []);
?>
CloudPrime Chatbot Settings
Debug Information
Plugin Status:
Not configured (API key missing)' : 'Configured (' . $provider . ')';
?>
WHMCS Integration:
Enabled' : 'Disabled'; ?>
Voice Commands:
Enabled' : 'Disabled'; ?>
Current Theme:
get_results("SELECT * FROM {$wpdb->prefix}cloudprime_chat_logs ORDER BY created_at DESC LIMIT 100");
?>
Chat Logs
| Date |
Session ID |
User Message |
AI Response |
AI Provider |
WHMCS Client |
Contact Info |
| created_at); ?> |
session_id, 0, 8)); ?>... |
user_message, 10)); ?> |
ai_response, 15)); ?> |
ai_provider ?? 'openrouter'); ?> |
whmcs_client_id ? esc_html($log->whmcs_client_id) : '-'; ?> |
contact_info); ?> |
get_results("SELECT * FROM {$wpdb->prefix}cloudprime_contacts ORDER BY created_at DESC");
?>
Contacts
| Date |
Name |
Phone |
Email |
WHMCS Client ID |
Source |
| created_at); ?> |
name); ?> |
phone); ?> |
email); ?> |
whmcs_client_id ? esc_html($contact->whmcs_client_id) : '-'; ?> |
source); ?> |
esc_url_raw($_POST['whmcs_url'] ?? ''),
'whmcs_api_identifier' => sanitize_text_field($_POST['whmcs_api_identifier'] ?? ''),
'whmcs_api_secret' => sanitize_text_field($_POST['whmcs_api_secret'] ?? ''),
'whmcs_db_host' => sanitize_text_field($_POST['whmcs_db_host'] ?? ''),
'whmcs_db_name' => sanitize_text_field($_POST['whmcs_db_name'] ?? ''),
'whmcs_db_user' => sanitize_text_field($_POST['whmcs_db_user'] ?? ''),
'whmcs_db_pass' => sanitize_text_field($_POST['whmcs_db_pass'] ?? ''),
'whmcs_integration_method' => sanitize_text_field($_POST['whmcs_integration_method'] ?? 'api')
];
update_option('cloudprime_whmcs_settings', $whmcs_settings);
echo 'WHMCS settings saved successfully!
';
}
$whmcs_opts = get_option('cloudprime_whmcs_settings', []);
?>
WHMCS Integration Settings
'GetClientsDetails',
'email' => $email,
'identifier' => $identifier,
'secret' => $secret,
'responsetype' => 'json'
];
$response = wp_remote_post($url . '/includes/api.php', ['body' => $postdata, 'timeout' => 10]);
if (is_wp_error($response)) return null;
$result = json_decode(wp_remote_retrieve_body($response), true);
return isset($result['result']) && $result['result'] === 'success' ? $result : null;
}
function cloudprime_whmcs_db_get_client($email) {
$whmcs_opts = get_option('cloudprime_whmcs_settings', []);
$host = $whmcs_opts['whmcs_db_host'] ?? '';
$dbname = $whmcs_opts['whmcs_db_name'] ?? '';
$username = $whmcs_opts['whmcs_db_user'] ?? '';
$password = $whmcs_opts['whmcs_db_pass'] ?? '';
if (empty($host) || empty($dbname) || empty($username)) return null;
try {
$whmcs_db = new PDO("mysql:host=$host;dbname=$dbname", $username, $password);
$whmcs_db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$stmt = $whmcs_db->prepare("SELECT * FROM tblclients WHERE email = ?");
$stmt->execute([$email]);
$client = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$client) return null;
$stmt = $whmcs_db->prepare("SELECT * FROM tblinvoices WHERE userid = ? ORDER BY id DESC LIMIT 5");
$stmt->execute([$client['id']]);
$invoices = $stmt->fetchAll(PDO::FETCH_ASSOC);
$stmt = $whmcs_db->prepare("SELECT * FROM tbltickets WHERE userid = ? ORDER BY id DESC LIMIT 5");
$stmt->execute([$client['id']]);
$tickets = $stmt->fetchAll(PDO::FETCH_ASSOC);
$stmt = $whmcs_db->prepare("SELECT COUNT(*) as unpaid_count, SUM(total) as unpaid_total FROM tblinvoices WHERE userid = ? AND status = 'Unpaid'");
$stmt->execute([$client['id']]);
$unpaid = $stmt->fetch(PDO::FETCH_ASSOC);
return ['client'=>$client,'invoices'=>$invoices,'tickets'=>$tickets,'unpaid_invoices'=>$unpaid];
} catch (PDOException $e) {
cloudprime_debug_log('WHMCS DB Error: ' . $e->getMessage());
return null;
}
}
/* =================================================================================
* NEW SHARED WHMCS CRUD HELPERS
* ================================================================================= */
function cloudprime_api_call($action, $params = []) {
$opts = get_option('cloudprime_whmcs_settings', []);
$url = rtrim($opts['whmcs_url'] ?? '', '/') . '/includes/api.php';
$id = $opts['whmcs_api_identifier'] ?? '';
$sec = $opts['whmcs_api_secret'] ?? '';
if (!$id || !$sec) return ['error' => 'WHMCS API not configured'];
$body = array_merge($params, ['action' => $action, 'username' => $id, 'password' => $sec, 'responsetype' => 'json']);
$resp = wp_remote_post($url, ['body' => $body, 'timeout' => 15]);
if (is_wp_error($resp)) return ['error' => $resp->get_error_message()];
return json_decode($resp['body'], true) ?: ['error' => 'Invalid JSON'];
}
/* ---------- NEW: Visitor tracking helpers ---------- */
add_action('wp_footer', 'cloudprime_track_visitor');
function cloudprime_track_visitor() {
if (is_admin()) return;
global $wpdb;
$ip = cloudprime_real_ip();
$ua = sanitize_text_field($_SERVER['HTTP_USER_AGENT'] ?? '');
$ref = sanitize_text_field($_SERVER['HTTP_REFERER'] ?? '');
$page = home_url(add_query_arg(null, null));
$sid = cloudprime_session_id();
$country = sanitize_text_field($_SERVER['HTTP_CF_IPCOUNTRY'] ?? '');
$city = '';
$row = $wpdb->get_row($wpdb->prepare(
"SELECT id, page_views FROM {$wpdb->prefix}cloudprime_visitors WHERE session_id = %s",
$sid
));
if ($row) {
$wpdb->update(
"{$wpdb->prefix}cloudprime_visitors",
[
'last_seen' => current_time('mysql'),
'page_views' => $row->page_views + 1
],
['id' => $row->id]
);
} else {
$wpdb->insert(
"{$wpdb->prefix}cloudprime_visitors",
[
'ip' => $ip,
'user_agent' => $ua,
'referrer' => $ref,
'landing_page' => $page,
'geo_country' => $country,
'geo_city' => $city,
'session_id' => $sid
]
);
}
}
function cloudprime_session_id() {
if (isset($_COOKIE['cp_session'])) return $_COOKIE['cp_session'];
$sid = bin2hex(random_bytes(16));
setcookie('cp_session', $sid, time() + 30 * DAY_IN_SECONDS, COOKIEPATH, COOKIE_DOMAIN);
return $sid;
}
function cloudprime_real_ip() {
return $_SERVER['HTTP_CF_CONNECTING_IP']
?? $_SERVER['HTTP_X_FORWARDED_FOR']
?? $_SERVER['REMOTE_ADDR']
?? '0.0.0.0';
}
/* =================================================================================
* NEW WHMCS CRUD ENDPOINTS (add all requested write-actions)
* ================================================================================= */
$whmcs_actions = [
'cloudprime_create_client' => function ($p) { return cloudprime_api_call('AddClient', $p); },
'cloudprime_update_client' => function ($p) { return cloudprime_api_call('UpdateClient', array_merge(['clientid'=>intval($p['client_id'])], $p)); },
'cloudprime_create_invoice' => function ($p) { return cloudprime_api_call('CreateInvoice', ['clientid'=>intval($p['client_id']),'lineitems'=>$p['items']]); },
'cloudprime_pay_invoice' => function ($p) { return cloudprime_api_call('AddInvoicePayment', ['invoiceid'=>intval($p['invoice_id']),'amount'=>floatval($p['amount']),'paymentmethod'=>'credit']); },
'cloudprime_open_ticket' => function ($p) { return cloudprime_api_call('OpenTicket', ['clientid'=>intval($p['client_id']),'deptid'=>intval($p['dept']),'subject'=>sanitize_text_field($p['subject']),'message'=>sanitize_textarea_field($p['message'])]); },
'cloudprime_close_ticket' => function ($p) { return cloudprime_api_call('UpdateTicket', ['ticketid'=>intval($p['ticket_id']),'status'=>'Closed']); },
'cloudprime_order_service' => function ($p) { return cloudprime_api_call('AddOrder', ['clientid'=>intval($p['client_id']),'pid'=>intval($p['pid']),'domain'=>sanitize_text_field($p['domain'])]); },
'cloudprime_suspend_service' => function ($p) { return cloudprime_api_call('ModuleSuspend', ['serviceid'=>intval($p['service_id']),'suspendreason'=>sanitize_text_field($p['reason'])]); },
'cloudprime_domain_action' => function ($p) { return cloudprime_api_call('Domain'.ucfirst(sanitize_text_field($p['action'])), ['domain'=>sanitize_text_field($p['domain']),'regperiod'=>intval($p['years']??1)]); }
];
foreach ($whmcs_actions as $hook => $fn) {
add_action("wp_ajax_$hook", function () use ($fn) {
check_ajax_referer('cloudprime_chat_nonce');
wp_send_json($fn($_POST));
});
}
/* =================================================================================
* ORIGINAL AI FUNCTIONS (unchanged)
* ================================================================================= */
function cloudprime_get_ai_response($prompt, $client_data = null, $provider = 'openrouter') {
$opt = get_option('cloudprime_chatbot_settings');
return $provider === 'gemini'
? cloudprime_get_gemini_response($prompt, $client_data, $opt)
: cloudprime_get_openrouter_response($prompt, $client_data, $opt);
}
function cloudprime_get_gemini_response($prompt, $client_data, $opt) {
$key = $opt['gemini_api_key'] ?? '';
if (!$key) return ['error' => 'Gemini API key not configured'];
$sys = cloudprime_build_system_prompt($client_data);
$body = json_encode([
'contents' => [['parts' => [['text' => $sys . "\n\nUser: " . $prompt]]]],
'generationConfig' => ['temperature' => 0.7, 'maxOutputTokens' => 400]
]);
$resp = wp_remote_post("https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash-latest:generateContent?key=$key", [
'headers' => ['Content-Type' => 'application/json'],
'body' => $body,
'timeout' => 20
]);
if (is_wp_error($resp)) return ['error' => $resp->get_error_message()];
$res = json_decode(wp_remote_retrieve_body($resp), true);
return isset($res['candidates'][0]['content']['parts'][0]['text']) ? ['reply' => $res['candidates'][0]['content']['parts'][0]['text']] : ['error' => 'Invalid Gemini response'];
}
function cloudprime_get_openrouter_response($prompt, $client_data, $opt) {
$key = $opt['openrouter_api_key'] ?? '';
if (!$key) return ['error' => 'OpenRouter API key not configured'];
$sys = cloudprime_build_system_prompt($client_data);
$body = json_encode([
"model" => "openrouter/auto",
"max_tokens" => 400,
"temperature" => 0.7,
"messages" => [["role" => "system", "content" => $sys], ["role" => "user", "content" => $prompt]]
]);
$resp = wp_remote_post("https://openrouter.ai/api/v1/chat/completions", [
"headers" => ["Authorization" => "Bearer $key", "Content-Type" => "application/json"],
"body" => $body,
"timeout" => 20
]);
if (is_wp_error($resp)) return ['error' => $resp->get_error_message()];
$res = json_decode(wp_remote_retrieve_body($resp), true);
return isset($res['choices'][0]['message']['content']) ? ['reply' => $res['choices'][0]['message']['content']] : ['error' => 'Invalid OpenRouter response'];
}
/* ----------------------------------------------------------
* PATCHED system prompt – injects real client data
* ---------------------------------------------------------- */
function cloudprime_build_system_prompt($client_data = null) {
$base_prompt = "You are a helpful assistant for Cloud Prime Connect (cloudprime.co.za), an IT and telecom services provider based in Johannesburg, South Africa.
CloudPrime offers:
- Managed IT services (24/7 monitoring, cybersecurity, helpdesk support)
- Fibre and LTE connectivity solutions
- Yeastar PBX and VoIP systems
- Hotspot installations and WiFi solutions
- Data management and IT consulting
- Cloud services and hosting
- Network security solutions
Contact information:
- Website: cloudprime.co.za/contact
- Phone: +27 10 110 8466
- Email: info@cloudprime.co.za";
if ($client_data && isset($client_data['client'])) {
$client = $client_data['client'];
$base_prompt .= "\n\nCLIENT INFORMATION:\n";
$base_prompt .= "- Client Name: " . $client['firstname'] . " " . $client['lastname'] . "\n";
$base_prompt .= "- Email: " . $client['email'] . "\n";
$base_prompt .= "- Client ID: " . $client['id'] . "\n";
$base_prompt .= "- Status: " . $client['status'] . "\n";
// Unpaid invoices
if (!empty($client_data['unpaid_invoices']) && $client_data['unpaid_invoices']['unpaid_count'] > 0) {
$base_prompt .= "\nUNPAID INVOICES:\n";
$base_prompt .= "- You have " . $client_data['unpaid_invoices']['unpaid_count'] . " unpaid invoice(s)\n";
$base_prompt .= "- Total outstanding: R" . $client_data['unpaid_invoices']['unpaid_total'] . "\n";
} else {
$base_prompt .= "\nUNPAID INVOICES:\n- No unpaid invoices\n";
}
// Recent invoices
if (!empty($client_data['invoices'])) {
$base_prompt .= "\nRECENT INVOICES (last 5):\n";
foreach ($client_data['invoices'] as $inv) {
$base_prompt .= "- Invoice #" . ($inv['invoicenum'] ?? $inv['id']) . " - " . $inv['status'] . " - R" . $inv['total'] . "\n";
}
}
// Recent tickets
if (!empty($client_data['tickets'])) {
$base_prompt .= "\nRECENT SUPPORT TICKETS:\n";
foreach ($client_data['tickets'] as $ticket) {
$base_prompt .= "- Ticket #" . ($ticket['tid'] ?? $ticket['id']) . " - " . $ticket['subject'] . " - " . $ticket['status'] . "\n";
}
}
$base_prompt .= "\nIMPORTANT: When asked about invoices, payments, or account details, use the client information above to provide specific answers. Do NOT ask them to contact support unless it's a complex billing dispute or technical issue.";
}
$base_prompt .= "\n\nBe helpful, professional.";
return $base_prompt;
}
/* =================================================================================
* ORIGINAL AJAX HANDLERS (unchanged)
* ================================================================================= */
add_action('wp_ajax_cloudprime_chat', 'cloudprime_handle_chat_ajax');
add_action('wp_ajax_nopriv_cloudprime_chat', 'cloudprime_handle_chat_ajax');
function cloudprime_handle_chat_ajax() {
check_ajax_referer('cloudprime_chat_nonce', 'nonce');
$message = sanitize_text_field($_POST['message']);
$session_id = sanitize_text_field($_POST['session_id']);
$email = sanitize_email($_POST['email'] ?? '');
$opts = get_option('cloudprime_chatbot_settings');
$provider = $opts['ai_provider'] ?? 'openrouter';
$client_data = null;
$whmcs_client_id = null;
if (!empty($email) && !empty($opts['enable_whmcs_integration'])) {
$client_data = cloudprime_get_whmcs_client_by_email($email);
if ($client_data && isset($client_data['client'])) $whmcs_client_id = $client_data['client']['id'];
}
$ai_response = cloudprime_get_ai_response($message, $client_data, $provider);
if (isset($ai_response['error'])) {
wp_send_json_error($ai_response['error']);
return;
}
global $wpdb;
$wpdb->insert($wpdb->prefix . 'cloudprime_chat_logs', [
'session_id' => $session_id,
'user_message' => $message,
'ai_response' => $ai_response['reply'],
'contact_info' => $email,
'whmcs_client_id' => $whmcs_client_id,
'ai_provider' => $provider,
'created_at' => current_time('mysql')
]);
$show_whatsapp = false;
if (!empty($opts['enable_conditional_whatsapp'])) {
$triggers = ['speak to human','human agent','contact support','call you','cannot help','don\'t know'];
foreach ($triggers as $t) if (stripos($ai_response['reply'], $t) !== false || stripos($message, $t) !== false) {$show_whatsapp = true; break;}
}
wp_send_json_success([
'message' => $ai_response['reply'],
'show_whatsapp' => $show_whatsapp,
'client_info' => $client_data ? [
'name' => $client_data['client']['firstname'] . ' ' . $client_data['client']['lastname'],
'client_id' => $client_data['client']['id'],
'status' => $client_data['client']['status']
] : null
]);
}
/* =================================================================================
* ORIGINAL CONTACT AJAX HANDLER (unchanged)
* ================================================================================= */
add_action('wp_ajax_cloudprime_save_contact', 'cloudprime_save_contact_ajax');
add_action('wp_ajax_nopriv_cloudprime_save_contact', 'cloudprime_save_contact_ajax');
function cloudprime_save_contact_ajax() {
check_ajax_referer('cloudprime_chat_nonce', 'nonce');
$name = sanitize_text_field($_POST['name']);
$phone = sanitize_text_field($_POST['phone']);
$email = sanitize_email($_POST['email']);
$session_id = sanitize_text_field($_POST['session_id']);
$whmcs_client_id = null;
$opts = get_option('cloudprime_chatbot_settings');
if (!empty($opts['enable_whmcs_integration']) && !empty($email)) {
$client_data = cloudprime_get_whmcs_client_by_email($email);
if ($client_data && isset($client_data['client'])) $whmcs_client_id = $client_data['client']['id'];
}
global $wpdb;
$result = $wpdb->insert($wpdb->prefix . 'cloudprime_contacts', [
'session_id' => $session_id,
'name' => $name,
'phone' => $phone,
'email' => $email,
'whmcs_client_id' => $whmcs_client_id,
'source' => 'chatbot',
'created_at' => current_time('mysql')
]);
if ($result) {
$notification_email = $opts['notification_email'] ?? get_option('admin_email');
$subject = 'New Contact from CloudPrime Chatbot';
$message = "New contact submitted via chatbot:\n\nName: $name\nPhone: $phone\nEmail: $email\n" . ($whmcs_client_id ? "WHMCS Client ID: $whmcs_client_id\n" : '') . "Session ID: $session_id\nDate: " . current_time('mysql') . "\n";
wp_mail($notification_email, $subject, $message);
wp_send_json_success([
'message' => 'Thank you! Your contact information has been saved.',
'predefined_questions' => array_filter(explode("\n", $opts['predefined_questions_setting'] ?? ''))
]);
} else {
wp_send_json_error('Failed to save contact information');
}
}
/* =================================================================================
* ORIGINAL FRONT-END CHATBOT (unchanged except voice fix)
* ================================================================================= */
add_action('wp_footer', 'cloudprime_chatbot_frontend');
function cloudprime_chatbot_frontend() {
$opts = get_option('cloudprime_chatbot_settings');
$provider = $opts['ai_provider'] ?? 'openrouter';
$key_field = $provider === 'gemini' ? 'gemini_api_key' : 'openrouter_api_key';
if (empty($opts[$key_field])) return;
$ai_name = $opts['ai_name'] ?? 'CloudPrime Assistant';
$ai_avatar = $opts['ai_avatar_url'] ?? '';
$whatsapp_number = $opts['whatsapp_number'] ?? '';
$predefined_questions = array_filter(explode("\n", $opts['predefined_questions_setting'] ?? ''));
$enable_voice = !empty($opts['enable_voice_commands']);
?>