<?php
// Permission checking is now handled by the permission system in auto-prepend.php

$message = '';
$message_type = '';
$run_output = '';

// Config file paths
$config_file = '/etc/whp/ai-monitor.conf';
$config_default = '/root/whp/configs/ai-monitor.conf.default';
$api_key_file = '/etc/whp/ai-monitor.key';
$db_path = '/var/lib/whp-ai-monitor/monitor.db';
$log_file = '/var/log/whp-ai-monitor.log';

/**
 * Write an INI file with sections
 */
function write_ini_file_sections($filename, $data) {
    $content = '';
    foreach ($data as $section => $values) {
        $content .= "[$section]\n";
        foreach ($values as $key => $value) {
            $content .= "$key = $value\n";
        }
        $content .= "\n";
    }
    file_put_contents($filename, $content);
    chmod($filename, 0600);
}

/**
 * Load config from INI file with fallbacks
 */
function load_ai_monitor_config($config_file, $config_default) {
    $config = [];

    // Try loading from default first for base values
    if (file_exists($config_default)) {
        $config = @parse_ini_file($config_default, true);
        if ($config === false) {
            $config = [];
        }
    }

    // Override with actual config if it exists
    if (file_exists($config_file)) {
        $actual = @parse_ini_file($config_file, true);
        if ($actual !== false) {
            foreach ($actual as $section => $values) {
                if (!isset($config[$section])) {
                    $config[$section] = [];
                }
                foreach ($values as $key => $value) {
                    $config[$section][$key] = $value;
                }
            }
        }
    }

    // Hardcoded defaults if nothing loaded
    if (empty($config)) {
        $config = [
            'general' => ['enabled' => 'true', 'db_path' => '/var/lib/whp-ai-monitor/monitor.db'],
            'ai' => [
                'base_url' => 'http://localhost:4000/v1',
                'api_key_file' => '/etc/whp/ai-monitor.key',
                'basic_model' => 'gpt-4o-mini',
                'advanced_model' => 'claude-sonnet-4-20250514',
                'max_calls_per_run' => '10',
                'max_calls_per_day' => '100',
            ],
            // Section name and key names match whp-log-monitor-ai.py and
            // whp_monitor_core.attempt_remediation -- both engines read this
            // exact section. Defaults are conservative: disabled + dry_run on
            // so an upgrade never starts restarting things until the operator
            // explicitly toggles both.
            'remediation' => [
                'enabled' => 'false',
                'dry_run' => 'true',
                'require_high_confidence' => 'true',
                'cooldown_minutes' => '60',
                'max_remediations_per_hour' => '5',
                'circuit_breaker_threshold' => '3',
                'backup_load_multiplier' => '4.0',
                'backup_swap_threshold' => '90',
                'allowed_services' => 'httpd,php-fpm,proftpd,whp-terminal,whp-backup-upload',
                'allowed_containers' => 'mysql,postgresql,haproxy-manager,memcache',
            ],
            'notifications' => [
                'enabled' => 'false',
                'discord_webhook_url' => '',
                'slack_webhook_url' => '',
                'telegram_bot_token' => '',
                'telegram_chat_id' => '',
            ],
            'log_sources' => [
                'apache_error' => '/var/log/httpd/error_log',
                'phpfpm_error' => '/var/log/php-fpm/www-error.log',
                'haproxy_watchdog' => '/var/log/haproxy-watchdog.log',
                'backup_log' => '/var/log/whp-backup.log',
                'wordpress_update' => '/var/log/wordpress-auto-update.log',
                'security_monitor' => '/var/log/whp-log-monitor.log',
                'proftpd' => '/var/log/proftpd/proftpd.log',
                'dmesg' => 'true',
            ],
            'docker_containers' => ['system' => 'mysql,postgresql,haproxy-manager,memcache'],
            'customer_monitoring' => ['enabled' => 'false', 'sites' => ''],
            'systemd_services' => ['monitor' => 'httpd,php-fpm,docker,proftpd,whp-terminal,whp-backup-upload'],
        ];
    }

    return $config;
}

/**
 * Get a config value with a default
 */
function cfg($config, $section, $key, $default = '') {
    return isset($config[$section][$key]) ? $config[$section][$key] : $default;
}

/**
 * Check if a config value is truthy
 */
function cfg_bool($config, $section, $key, $default = false) {
    if (!isset($config[$section][$key])) {
        return $default;
    }
    $val = strtolower(trim($config[$section][$key]));
    return in_array($val, ['true', '1', 'yes', 'on']);
}

/**
 * Send a test notification to configured channels
 */
function send_test_notifications($discord_url, $slack_url, $telegram_token, $telegram_chat_id) {
    $results = [];
    $hostname = gethostname();
    $test_message = "\xF0\x9F\xA7\xAA WHP AI Monitor \xe2\x80\x94 Test notification from " . $hostname;

    // Discord
    if (!empty($discord_url)) {
        $payload = json_encode(['content' => $test_message]);
        $ch = curl_init($discord_url);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
        curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_TIMEOUT, 10);
        $response = curl_exec($ch);
        $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $error = curl_error($ch);
        curl_close($ch);
        if ($http_code >= 200 && $http_code < 300) {
            $results[] = 'Discord: OK';
        } else {
            $results[] = 'Discord: Failed (HTTP ' . $http_code . ($error ? ', ' . $error : '') . ')';
        }
    }

    // Slack
    if (!empty($slack_url)) {
        $payload = json_encode(['text' => $test_message]);
        $ch = curl_init($slack_url);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
        curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_TIMEOUT, 10);
        $response = curl_exec($ch);
        $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $error = curl_error($ch);
        curl_close($ch);
        if ($http_code >= 200 && $http_code < 300) {
            $results[] = 'Slack: OK';
        } else {
            $results[] = 'Slack: Failed (HTTP ' . $http_code . ($error ? ', ' . $error : '') . ')';
        }
    }

    // Telegram
    if (!empty($telegram_token) && !empty($telegram_chat_id)) {
        $url = 'https://api.telegram.org/bot' . $telegram_token . '/sendMessage';
        $payload = json_encode(['chat_id' => $telegram_chat_id, 'text' => $test_message]);
        $ch = curl_init($url);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
        curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_TIMEOUT, 10);
        $response = curl_exec($ch);
        $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $error = curl_error($ch);
        curl_close($ch);
        if ($http_code >= 200 && $http_code < 300) {
            $results[] = 'Telegram: OK';
        } else {
            $results[] = 'Telegram: Failed (HTTP ' . $http_code . ($error ? ', ' . $error : '') . ')';
        }
    }

    if (empty($results)) {
        return 'No notification channels configured to test.';
    }

    return implode(' | ', $results);
}

// Handle form submissions
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    if (!validate_csrf_token()) {
        $message = 'Invalid or expired CSRF token. Please refresh the page and try again.';
        $message_type = 'danger';
    } elseif (isset($_POST['action'])) {
        switch ($_POST['action']) {
            case 'update_config':
                $config = [];

                // [general]
                $config['general'] = [
                    'enabled' => isset($_POST['general_enabled']) ? 'true' : 'false',
                    'db_path' => '/var/lib/whp-ai-monitor/monitor.db',
                ];

                // [ai]
                $base_url = trim($_POST['ai_base_url'] ?? 'http://localhost:4000/v1');
                $basic_model = trim($_POST['ai_basic_model'] ?? 'gpt-4o-mini');
                $advanced_model = trim($_POST['ai_advanced_model'] ?? 'claude-sonnet-4-20250514');
                $max_per_run = max(1, min(50, intval($_POST['ai_max_calls_per_run'] ?? 10)));
                $max_per_day = max(1, min(500, intval($_POST['ai_max_calls_per_day'] ?? 100)));

                $config['ai'] = [
                    'base_url' => $base_url,
                    'api_key_file' => $api_key_file,
                    'basic_model' => $basic_model,
                    'advanced_model' => $advanced_model,
                    'max_calls_per_run' => $max_per_run,
                    'max_calls_per_day' => $max_per_day,
                ];

                // Save API key to separate file
                $api_key_value = trim($_POST['ai_api_key'] ?? '');
                if (!empty($api_key_value)) {
                    $key_dir = dirname($api_key_file);
                    if (!is_dir($key_dir)) {
                        @mkdir($key_dir, 0700, true);
                    }
                    file_put_contents($api_key_file, $api_key_value);
                    chmod($api_key_file, 0600);
                }

                // [remediation] -- section name + key names line up with
                // the engine in whp-log-monitor-ai.py and the shared guard
                // in whp_monitor_core.attempt_remediation.
                $cooldown   = max(5, min(120, intval($_POST['remediation_cooldown_minutes'] ?? 60)));
                $max_hour   = max(1, min(20,  intval($_POST['remediation_max_per_hour'] ?? 5)));
                $circuit    = max(1, min(10,  intval($_POST['remediation_circuit_breaker'] ?? 3)));
                $load_mult  = max(1.0, min(10.0, floatval($_POST['remediation_load_multiplier'] ?? 4.0)));
                $swap_pct   = max(50,  min(99,  intval($_POST['remediation_swap_threshold'] ?? 90)));
                $allowed_svc = trim($_POST['remediation_allowed_services'] ?? 'httpd,php-fpm,proftpd,whp-terminal,whp-backup-upload');
                $allowed_ctr = trim($_POST['remediation_allowed_containers'] ?? 'mysql,postgresql,haproxy-manager,memcache');
                // Sanitize: comma list of [a-z0-9_-]+ tokens.
                $clean_list = function ($s) {
                    $parts = preg_split('/\s*,\s*/', $s) ?: [];
                    $out = [];
                    foreach ($parts as $p) {
                        if (preg_match('/^[a-zA-Z0-9._-]+$/', $p)) $out[] = $p;
                    }
                    return implode(',', $out);
                };

                $config['remediation'] = [
                    'enabled'                  => isset($_POST['remediation_enabled']) ? 'true' : 'false',
                    'dry_run'                  => isset($_POST['remediation_dry_run']) ? 'true' : 'false',
                    'require_high_confidence'  => isset($_POST['remediation_require_high_conf']) ? 'true' : 'false',
                    'cooldown_minutes'         => $cooldown,
                    'max_remediations_per_hour'=> $max_hour,
                    'circuit_breaker_threshold'=> $circuit,
                    'backup_load_multiplier'   => $load_mult,
                    'backup_swap_threshold'    => $swap_pct,
                    'allowed_services'         => $clean_list($allowed_svc),
                    'allowed_containers'       => $clean_list($allowed_ctr),
                ];

                // Drop the legacy [auto_remediation] section if it still
                // exists in the current config -- it was orphaned by the
                // section-name mismatch and reading it on the next reload
                // would just be confusing.
                if (isset($config['auto_remediation'])) {
                    unset($config['auto_remediation']);
                }

                // [notifications]
                $config['notifications'] = [
                    'enabled' => isset($_POST['notifications_enabled']) ? 'true' : 'false',
                    'discord_webhook_url' => trim($_POST['notifications_discord_url'] ?? ''),
                    'discord_role_critical' => trim($_POST['notifications_discord_role_critical'] ?? ''),
                    'discord_role_warning' => trim($_POST['notifications_discord_role_warning'] ?? ''),
                    'discord_role_info' => trim($_POST['notifications_discord_role_info'] ?? ''),
                    'slack_webhook_url' => trim($_POST['notifications_slack_url'] ?? ''),
                    'telegram_bot_token' => trim($_POST['notifications_telegram_token'] ?? ''),
                    'telegram_chat_id' => trim($_POST['notifications_telegram_chat_id'] ?? ''),
                ];

                // [log_sources]
                $config['log_sources'] = [
                    'apache_error' => isset($_POST['log_apache_enabled']) ? trim($_POST['log_apache_path'] ?? '/var/log/httpd/error_log') : '',
                    'phpfpm_error' => isset($_POST['log_phpfpm_enabled']) ? trim($_POST['log_phpfpm_path'] ?? '/var/log/php-fpm/www-error.log') : '',
                    'haproxy_watchdog' => isset($_POST['log_haproxy_enabled']) ? trim($_POST['log_haproxy_path'] ?? '/var/log/haproxy-watchdog.log') : '',
                    'backup_log' => isset($_POST['log_backup_enabled']) ? trim($_POST['log_backup_path'] ?? '/var/log/whp-backup.log') : '',
                    'wordpress_update' => isset($_POST['log_wordpress_enabled']) ? trim($_POST['log_wordpress_path'] ?? '/var/log/wordpress-auto-update.log') : '',
                    'security_monitor' => isset($_POST['log_security_enabled']) ? trim($_POST['log_security_path'] ?? '/var/log/whp-log-monitor.log') : '',
                    'proftpd' => isset($_POST['log_proftpd_enabled']) ? trim($_POST['log_proftpd_path'] ?? '/var/log/proftpd/proftpd.log') : '',
                    'dmesg' => isset($_POST['log_dmesg_enabled']) ? 'true' : 'false',
                ];

                // [docker_containers]
                $system_containers = trim($_POST['docker_system_containers'] ?? 'mysql,postgresql,haproxy-manager,memcache');
                $system_containers = preg_replace('/\s*,\s*/', ',', $system_containers);
                $config['docker_containers'] = [
                    'system' => $system_containers,
                ];

                // [customer_monitoring] section retired — global toggle lives in
                // /docker/whp/settings.json (managed by Customer Monitoring
                // Management card below) and the site list in
                // whp.ai_monitor_subscriptions.

                // [systemd_services]
                $systemd_list = trim($_POST['systemd_services_list'] ?? 'httpd,php-fpm,docker,proftpd,whp-terminal,whp-backup-upload');
                $systemd_list = preg_replace('/\s*,\s*/', ',', $systemd_list);
                $config['systemd_services'] = [
                    'monitor' => $systemd_list,
                ];

                // Ensure config directory exists
                $config_dir = dirname($config_file);
                if (!is_dir($config_dir)) {
                    @mkdir($config_dir, 0700, true);
                }

                // Write config
                try {
                    write_ini_file_sections($config_file, $config);
                    $message = 'Configuration saved successfully.';
                    $message_type = 'success';
                } catch (Exception $e) {
                    $message = 'Error saving configuration: ' . $e->getMessage();
                    $message_type = 'danger';
                    error_log('AI Monitor config save error: ' . $e->getMessage());
                }
                break;

            case 'run_now':
                $script = '/root/whp/scripts/whp-log-monitor-ai.py';
                if (!file_exists($script)) {
                    $message = 'AI Monitor script not found at ' . $script;
                    $message_type = 'danger';
                } else {
                    $cmd = 'timeout 120 python3 ' . escapeshellarg($script) . ' --mode critical --verbose 2>&1';
                    $run_output = shell_exec($cmd);
                    if ($run_output === null) {
                        $run_output = '(No output returned)';
                    }
                    $message = 'AI Monitor run completed.';
                    $message_type = 'success';
                }
                break;

            case 'test_notification':
                $discord_url = trim($_POST['test_discord_url'] ?? '');
                $slack_url = trim($_POST['test_slack_url'] ?? '');
                $telegram_token = trim($_POST['test_telegram_token'] ?? '');
                $telegram_chat_id = trim($_POST['test_telegram_chat_id'] ?? '');

                $result = send_test_notifications($discord_url, $slack_url, $telegram_token, $telegram_chat_id);
                $message = 'Test notification results: ' . $result;

                // Determine message type based on results
                if (strpos($result, 'Failed') !== false && strpos($result, 'OK') !== false) {
                    $message_type = 'warning';
                } elseif (strpos($result, 'Failed') !== false) {
                    $message_type = 'danger';
                } elseif (strpos($result, 'No notification') !== false) {
                    $message_type = 'warning';
                } else {
                    $message_type = 'success';
                }
                break;

            case 'toggle_customer_monitoring':
                try {
                    $settings = [];
                    if (file_exists('/docker/whp/settings.json')) {
                        $settings = json_decode(file_get_contents('/docker/whp/settings.json'), true) ?: [];
                    }
                    if (!isset($settings['customer_monitoring'])) {
                        $settings['customer_monitoring'] = [];
                    }
                    $current = !empty($settings['customer_monitoring']['enabled']);
                    $settings['customer_monitoring']['enabled'] = !$current;
                    file_put_contents('/docker/whp/settings.json', json_encode($settings, JSON_PRETTY_PRINT));
                    chmod('/docker/whp/settings.json', 0600);
                    $message = 'Customer monitoring ' . (!$current ? 'enabled' : 'disabled') . ' globally.';
                    $message_type = 'success';
                } catch (Exception $e) {
                    $message = 'Error toggling customer monitoring: ' . $e->getMessage();
                    $message_type = 'danger';
                }
                break;

            case 'enable_site_monitoring':
                try {
                    $site_id = intval($_POST['site_id'] ?? 0);
                    $notification_email = trim($_POST['notification_email'] ?? '');
                    if ($site_id <= 0) {
                        throw new Exception('Invalid site selected.');
                    }
                    require_once('/docker/whp/web/libs/mysqlmgmt.php');
                    $mysql_cm = new mysqlmgmt();
                    $db_cm = $mysql_cm->getMySQLConnection();
                    $db_cm->exec("USE whp");
                    // Lookup site username
                    $stmt_cm = $db_cm->prepare("SELECT username FROM sites WHERE id = ?");
                    $stmt_cm->execute([$site_id]);
                    $site_row = $stmt_cm->fetch(PDO::FETCH_ASSOC);
                    if (!$site_row) {
                        throw new Exception('Site not found.');
                    }
                    $stmt_cm = $db_cm->prepare("INSERT INTO ai_monitor_subscriptions (site_id, username, notification_email, status, activated_at) VALUES (?, ?, ?, 'active', NOW())");
                    $stmt_cm->execute([$site_id, $site_row['username'], $notification_email ?: null]);
                    $message = 'AI monitoring enabled for site.';
                    $message_type = 'success';
                } catch (Exception $e) {
                    $message = 'Error enabling monitoring: ' . $e->getMessage();
                    $message_type = 'danger';
                }
                break;

            case 'disable_site_monitoring':
                try {
                    $sub_id = intval($_POST['subscription_id'] ?? 0);
                    if ($sub_id <= 0) {
                        throw new Exception('Invalid subscription.');
                    }
                    require_once('/docker/whp/web/libs/mysqlmgmt.php');
                    $mysql_cm = new mysqlmgmt();
                    $db_cm = $mysql_cm->getMySQLConnection();
                    $db_cm->exec("USE whp");
                    $stmt_cm = $db_cm->prepare("UPDATE ai_monitor_subscriptions SET status = 'cancelled', cancelled_at = NOW() WHERE id = ?");
                    $stmt_cm->execute([$sub_id]);
                    $message = 'Subscription deactivated.';
                    $message_type = 'success';
                } catch (Exception $e) {
                    $message = 'Error deactivating subscription: ' . $e->getMessage();
                    $message_type = 'danger';
                }
                break;

            case 'update_review_limit':
                try {
                    $sub_id = intval($_POST['subscription_id'] ?? 0);
                    $new_limit = max(1, min(50, intval($_POST['daily_review_limit'] ?? 3)));
                    if ($sub_id <= 0) {
                        throw new Exception('Invalid subscription.');
                    }
                    require_once('/docker/whp/web/libs/mysqlmgmt.php');
                    $mysql_cm = new mysqlmgmt();
                    $db_cm = $mysql_cm->getMySQLConnection();
                    $db_cm->exec("USE whp");
                    $stmt_cm = $db_cm->prepare("UPDATE ai_monitor_subscriptions SET daily_review_limit = ? WHERE id = ?");
                    $stmt_cm->execute([$new_limit, $sub_id]);
                    $message = 'Daily review limit updated to ' . $new_limit . '.';
                    $message_type = 'success';
                } catch (Exception $e) {
                    $message = 'Error updating review limit: ' . $e->getMessage();
                    $message_type = 'danger';
                }
                break;
        }
    }
}

// Load current config
$config = load_ai_monitor_config($config_file, $config_default);
$db_path = cfg($config, 'general', 'db_path', '/var/lib/whp-ai-monitor/monitor.db');

// Read API key. SECURITY: never render the raw key into the page (its value
// attribute is visible in page source / DOM snapshots regardless of an
// <input type=password> mask). We only compute a masked preview (bullets +
// last 4 chars) for display; the real key stays server-side. The save handler
// already only writes a new key when the field is non-empty, so leaving the
// field blank preserves the stored key.
$current_api_key = '';
$api_key_is_set = false;
$api_key_mask = '';
if (file_exists($api_key_file)) {
    $current_api_key = trim(file_get_contents($api_key_file));
    if ($current_api_key !== '') {
        $api_key_is_set = true;
        $last4 = strlen($current_api_key) >= 4 ? substr($current_api_key, -4) : $current_api_key;
        $api_key_mask = str_repeat("\xE2\x80\xA2", 10) . $last4; // ••••••••••XXXX
    }
}

// Load site list for customer monitoring selector
$all_sites = [];
$monitored_sites_list = array_filter(array_map('trim', explode(',', cfg($config, 'customer_monitoring', 'sites', ''))));
try {
    require_once('/docker/whp/web/libs/mysqlmgmt.php');
    $MySQLMgmt = new mysqlmgmt();
    $whp_db = $MySQLMgmt->getMySQLConnection();
    if ($whp_db) {
        $stmt = $whp_db->query("
            SELECT s.id, s.site_name, COALESCE(sd.fqdn, d.domain_name) as primary_domain
            FROM whp.sites s
            JOIN whp.domains d ON s.primary_domain_id = d.id
            LEFT JOIN whp.site_domains sd ON s.id = sd.site_id AND sd.is_primary = 1
            ORDER BY primary_domain ASC
        ");
        $all_sites = $stmt->fetchAll(PDO::FETCH_ASSOC);
    }
} catch (Exception $e) {
    error_log('AI Monitor: Failed to load sites list: ' . $e->getMessage());
}

// Read stats from SQLite database. $last_run_ts holds a Unix timestamp
// (or null) so the view layer can render via whp_local_time(); a separate
// $last_run_time is kept only for back-compat fallbacks.
$last_run_ts = null;
$last_run_time = 'Never';
$total_errors_tracked = 0;
$remediations_attempted = 0;
$api_calls_today = 0;
$daily_limit = intval(cfg($config, 'ai', 'max_calls_per_day', '100'));
// Minute-cadence poll heartbeat (health_api + haproxy_stats sources).
$poll_heartbeats = [];

if (file_exists($db_path)) {
    try {
        $pdo = new PDO('sqlite:' . $db_path);
        $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

        // Last run time
        $stmt = $pdo->query("SELECT MAX(last_check) as last_check FROM log_positions");
        $row = $stmt->fetch(PDO::FETCH_ASSOC);
        if ($row && !empty($row['last_check'])) {
            $last_run_ts = intval($row['last_check']);
            $last_run_time = date('M j, Y g:i A', $last_run_ts);
        }

        // Minute-cadence poll heartbeats. Table created by whp-monitor-poll.py.
        try {
            $stmt = $pdo->query("SELECT source, last_run_at, last_status, last_error FROM poll_heartbeat");
            foreach ($stmt as $hb) {
                $poll_heartbeats[$hb['source']] = [
                    'last_run_at' => intval($hb['last_run_at']),
                    'status'      => $hb['last_status'],
                    'error'       => $hb['last_error'],
                ];
            }
        } catch (Throwable $_e) { /* table may not exist yet */ }

        // Total errors tracked
        $stmt = $pdo->query("SELECT COUNT(*) as cnt FROM errors");
        $row = $stmt->fetch(PDO::FETCH_ASSOC);
        if ($row) {
            $total_errors_tracked = intval($row['cnt']);
        }

        // Remediations attempted
        $stmt = $pdo->query("SELECT COUNT(*) as cnt FROM remediation_log");
        $row = $stmt->fetch(PDO::FETCH_ASSOC);
        if ($row) {
            $remediations_attempted = intval($row['cnt']);
        }

        // API calls today — daily_api_calls table has date (TEXT) + count (INTEGER)
        $stmt = $pdo->query("SELECT count FROM daily_api_calls WHERE date = date('now')");
        $row = $stmt->fetch(PDO::FETCH_ASSOC);
        if ($row) {
            $api_calls_today = intval($row['count']);
        }

        // Recent health-check transitions (last 7d, capped at 100). Powers
        // the timeline card so root can correlate Uptime Kuma alerts with
        // what the panel itself detected. Table is created by
        // whp-monitor-poll.py's ensure_sqlite_schema; older DB files may not
        // have it yet, so we wrap in try/catch.
        $health_transitions = [];
        try {
            $cutoff = time() - 7 * 86400;
            $stmt = $pdo->prepare("
                SELECT subsystem, prev_status, new_status, prev_severity, new_severity,
                       detail_json, ai_diagnosis, mysql_signature, transitioned_at
                  FROM health_transitions
                 WHERE transitioned_at >= ?
                 ORDER BY transitioned_at DESC
                 LIMIT 100
            ");
            $stmt->execute([$cutoff]);
            $health_transitions = $stmt->fetchAll(PDO::FETCH_ASSOC);
        } catch (Throwable $_e) { /* table may not exist yet */ }

        $pdo = null;
    } catch (Exception $e) {
        // Database may not exist yet or tables may differ
        error_log('AI Monitor DB read error: ' . $e->getMessage());
    }
}

// Read last 20 lines of log file
$log_lines = '';
if (file_exists($log_file)) {
    $output = shell_exec('tail -n 20 ' . escapeshellarg($log_file) . ' 2>&1');
    $log_lines = $output !== null ? $output : '';
}

// Determine enabled status for display
$is_enabled = cfg_bool($config, 'general', 'enabled', false);

// Log source definitions for the form
$log_source_defs = [
    'apache' => ['key' => 'apache_error', 'label' => 'Apache Error Log', 'default_path' => '/var/log/httpd/error_log'],
    'phpfpm' => ['key' => 'phpfpm_error', 'label' => 'PHP-FPM Error Log', 'default_path' => '/var/log/php-fpm/www-error.log'],
    'haproxy' => ['key' => 'haproxy_watchdog', 'label' => 'HAProxy Watchdog Log', 'default_path' => '/var/log/haproxy-watchdog.log'],
    'backup' => ['key' => 'backup_log', 'label' => 'Backup Log', 'default_path' => '/var/log/whp-backup.log'],
    'wordpress' => ['key' => 'wordpress_update', 'label' => 'WordPress Update Log', 'default_path' => '/var/log/wordpress-auto-update.log'],
    'security' => ['key' => 'security_monitor', 'label' => 'Security Monitor Log', 'default_path' => '/var/log/whp-log-monitor.log'],
    'proftpd' => ['key' => 'proftpd', 'label' => 'ProFTPD Log', 'default_path' => '/var/log/proftpd/proftpd.log'],
];
?>
<?php if (!empty($message)): ?>
<div class="row">
    <div class="col-sm-12">
        <div class="alert alert-<?php echo $message_type; ?> alert-dismissible" role="alert">
            <button type="button" class="close" data-bs-dismiss="alert" aria-label="Close">
                <span aria-hidden="true">&times;</span>
            </button>
            <?php echo htmlspecialchars($message); ?>
        </div>
    </div>
</div>
<?php endif; ?>

<?php
// UX: the page was ~6 always-expanded sections requiring heavy scrolling to
// reach Save. We group them into themed accordions via whp_accordion(). Because
// some sections contain their own independent <form>s (Status' "Run Now",
// Customer Monitoring's toggles) and others live inside the single main config
// <form>, the page is rendered as three stacked always-open accordion segments
// (Status | Configuration | Customer Monitoring) so no form is ever nested
// inside another. Each section's existing markup is captured verbatim via
// output buffering and passed through unchanged.
require_once('/docker/whp/web/includes/whp-accordion.php');
?>
<!-- Status Card (accordion segment 1) -->
<?php ob_start(); ?>
<div class="row g-4 mb-4">
    <div class="col-12">
        <div class="card">
            <div class="card-header d-flex justify-content-between align-items-center">
                <h5 class="card-title mb-0"><i class="fa fa-brain"></i> AI Log Monitor Status</h5>
                <span class="badge bg-<?php echo $is_enabled ? 'success' : 'secondary'; ?> fs-6">
                    <?php echo $is_enabled ? 'Enabled' : 'Disabled'; ?>
                </span>
            </div>
            <div class="card-body">
                <?php if (!empty($poll_heartbeats)): ?>
                <div class="d-flex flex-wrap gap-3 align-items-center mb-3 p-3 rounded border"
                     style="background: var(--bs-tertiary-bg, rgba(128,128,128,0.08)); color: var(--bs-body-color);">
                    <strong class="me-2 d-inline-flex align-items-center">
                        <i class="fa fa-heartbeat text-danger me-2" aria-hidden="true"></i>
                        Minute-cadence poll
                    </strong>
                    <?php
                    $sourceLabels = [
                        'health_api'    => 'Health API',
                        'haproxy_stats' => 'HAProxy stats',
                    ];
                    foreach ($sourceLabels as $key => $label):
                        $hb = $poll_heartbeats[$key] ?? null;
                        if (!$hb) {
                            $color = 'secondary';
                            $msg   = 'never';
                        } else {
                            $age = time() - $hb['last_run_at'];
                            if ($hb['status'] !== 'ok') {
                                $color = 'danger';
                            } elseif ($age <= 90) {
                                $color = 'success';
                            } elseif ($age <= 300) {
                                $color = 'warning';
                            } else {
                                $color = 'danger';
                            }
                            $msg = $age < 60
                                ? "{$age}s ago"
                                : ($age < 3600 ? floor($age / 60) . 'm ago' : floor($age / 3600) . 'h ago');
                        }
                    ?>
                    <span class="d-inline-flex align-items-center">
                        <span class="badge bg-<?php echo $color; ?> me-2" style="font-size: 0.85em;">●</span>
                        <span><?php echo htmlspecialchars($label); ?>:&nbsp;<strong><?php echo htmlspecialchars($msg); ?></strong></span>
                        <?php if ($hb && $hb['status'] !== 'ok' && !empty($hb['error'])): ?>
                            <small class="text-danger ms-2" title="<?php echo htmlspecialchars($hb['error']); ?>">— <?php echo htmlspecialchars(substr($hb['error'], 0, 80)); ?></small>
                        <?php endif; ?>
                    </span>
                    <?php endforeach; ?>
                    <span class="ms-auto small d-inline-flex align-items-center"
                          style="color: var(--bs-body-color); opacity: 0.75;">
                        <i class="fa fa-info-circle me-2" aria-hidden="true"></i>
                        Updates every minute via <code style="background: var(--bs-secondary-bg, rgba(128,128,128,0.18)); padding: 1px 6px; border-radius: 3px;">whp-monitor-poll</code> cron.
                        <span class="ms-2"><span class="badge bg-success" style="font-size: 0.7em;">●</span> = ran &lt;90s ago</span>
                    </span>
                </div>
                <?php endif; ?>
                <div class="row g-4 mb-4">
                    <div class="col-md-3">
                        <div class="card h-100 border">
                            <div class="card-body text-center">
                                <h6 class="text-muted mb-1">Last Run</h6>
                                <h5 class="mb-0"><?php echo $last_run_ts ? whp_local_time($last_run_ts, 'M j, Y g:i A') : htmlspecialchars($last_run_time); ?></h5>
                            </div>
                        </div>
                    </div>
                    <div class="col-md-3">
                        <div class="card h-100 border">
                            <div class="card-body text-center">
                                <h6 class="text-muted mb-1">Errors Tracked</h6>
                                <h5 class="mb-0 text-warning"><?php echo $total_errors_tracked; ?></h5>
                            </div>
                        </div>
                    </div>
                    <div class="col-md-3">
                        <div class="card h-100 border">
                            <div class="card-body text-center">
                                <h6 class="text-muted mb-1">Remediations</h6>
                                <h5 class="mb-0 text-info"><?php echo $remediations_attempted; ?></h5>
                            </div>
                        </div>
                    </div>
                    <div class="col-md-3">
                        <div class="card h-100 border">
                            <div class="card-body text-center">
                                <h6 class="text-muted mb-1">API Calls Today</h6>
                                <h5 class="mb-0 <?php echo ($api_calls_today >= $daily_limit) ? 'text-danger' : 'text-success'; ?>">
                                    <?php echo $api_calls_today; ?> / <?php echo $daily_limit; ?>
                                </h5>
                            </div>
                        </div>
                    </div>
                </div>

                <!-- Health Check Timeline -->
                <div class="card mb-3">
                    <div class="card-header d-flex justify-content-between align-items-center">
                        <span><i class="fa fa-heartbeat"></i> Health Check Timeline (last 7d)</span>
                        <span class="text-muted small"><?php echo count($health_transitions); ?> events</span>
                    </div>
                    <div class="card-body p-0">
                        <?php if (empty($health_transitions)): ?>
                            <p class="text-muted text-center py-3 mb-0">
                                No health transitions recorded in the last 7 days.
                                Either everything has been healthy (good) or the row-per-event log
                                hasn't accumulated yet (this feature ships with v2026.04.121+).
                            </p>
                        <?php else: ?>
                        <div class="table-responsive">
                            <table class="table table-sm table-hover mb-0">
                                <thead>
                                    <tr>
                                        <th>Time</th>
                                        <th>Subsystem</th>
                                        <th>Transition</th>
                                        <th>Severity</th>
                                        <th>AI Diagnosis</th>
                                    </tr>
                                </thead>
                                <tbody>
                                <?php foreach ($health_transitions as $t):
                                    $whenTs = intval($t['transitioned_at']);
                                    $isRecovery = $t['new_status'] === 'healthy';
                                    // Color each row by its resulting status (consistent with the
                                    // severity badge below). Keying off transition direction left rows
                                    // that de-escalated into warning (e.g. critical -> warning) with no
                                    // class, so they rendered as a neutral row.
                                    $rowClass = $t['new_status'] === 'critical' ? 'table-danger'
                                              : ($t['new_status'] === 'warning' ? 'table-warning' : 'table-success');
                                    $diagSnip = $t['ai_diagnosis'] ? mb_substr($t['ai_diagnosis'], 0, 220) : '';
                                    $tierStr = '';
                                    if (!empty($t['new_severity']) || !empty($t['prev_severity'])) {
                                        $tierStr = "tier {$t['prev_severity']} -> {$t['new_severity']}";
                                    }
                                ?>
                                    <tr class="<?php echo $rowClass; ?>">
                                        <td class="small text-nowrap"><?php echo whp_local_time($whenTs, 'M j H:i:s'); ?></td>
                                        <td class="small"><code><?php echo htmlspecialchars($t['subsystem']); ?></code></td>
                                        <td class="small text-nowrap">
                                            <?php echo htmlspecialchars($t['prev_status']); ?>
                                            &rarr;
                                            <strong><?php echo htmlspecialchars($t['new_status']); ?></strong>
                                            <?php if ($tierStr): ?><span class="text-muted ms-1">(<?php echo htmlspecialchars($tierStr); ?>)</span><?php endif; ?>
                                        </td>
                                        <td class="small">
                                            <span class="badge bg-<?php echo $t['new_status'] === 'critical' ? 'danger' : ($t['new_status'] === 'warning' ? 'warning text-dark' : 'success'); ?>">
                                                <?php echo htmlspecialchars($t['new_status']); ?>
                                            </span>
                                        </td>
                                        <td class="small">
                                            <?php if ($diagSnip): ?>
                                                <details>
                                                    <summary><?php echo htmlspecialchars($diagSnip) . (strlen($t['ai_diagnosis']) > 220 ? '...' : ''); ?></summary>
                                                    <pre class="small mt-2 mb-0" style="white-space: pre-wrap;"><?php echo htmlspecialchars($t['ai_diagnosis']); ?></pre>
                                                </details>
                                            <?php elseif ($isRecovery): ?>
                                                <?php // No text-muted here -- the row already has table-success
                                                      // background which Bootstrap themes per data-theme.
                                                      // text-muted forced light-gray text that became
                                                      // unreadable on the dark-mode green background. Inherit
                                                      // the row's color and add a checkmark for visual cue. ?>
                                                <span class="fw-semibold"><i class="fa fa-check"></i> recovered</span>
                                            <?php else: ?>
                                                <span class="text-body-secondary">-</span>
                                            <?php endif; ?>
                                        </td>
                                    </tr>
                                <?php endforeach; ?>
                                </tbody>
                            </table>
                        </div>
                        <?php endif; ?>
                    </div>
                </div>

                <!-- Run Now -->
                <div class="row mb-3">
                    <div class="col-12">
                        <form method="POST" action="" class="d-inline">
                            <input type="hidden" name="csrf_token" value="<?php echo get_csrf_token(); ?>">
                            <input type="hidden" name="action" value="run_now">
                            <button type="submit" class="btn btn-primary" onclick="this.disabled=true;this.innerHTML='<i class=\'fa fa-spinner fa-spin\'></i> Running...';this.form.submit();">
                                <i class="fa fa-play"></i> Run Now (Critical Mode)
                            </button>
                        </form>
                    </div>
                </div>

                <?php if (!empty($run_output)): ?>
                <div class="row mb-3">
                    <div class="col-12">
                        <h6>Run Output:</h6>
                        <pre class="bg-dark text-light p-3 rounded" style="max-height: 400px; overflow-y: auto;"><?php echo htmlspecialchars($run_output); ?></pre>
                    </div>
                </div>
                <?php endif; ?>

                <!-- View Logs -->
                <div class="row">
                    <div class="col-12">
                        <h6><i class="fa fa-file-text-o"></i> Recent Log (last 20 lines)</h6>
                        <?php if (!empty($log_lines)): ?>
                        <pre class="bg-dark text-light p-3 rounded" style="max-height: 300px; overflow-y: auto; font-size: 0.85em;"><?php echo htmlspecialchars($log_lines); ?></pre>
                        <?php else: ?>
                        <p class="text-muted">No log file found at <?php echo htmlspecialchars($log_file); ?></p>
                        <?php endif; ?>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>
<?php $sec_status = ob_get_clean(); ?>
<?php
// Accordion segment 1: Status (primary section, open on load).
echo whp_accordion('ai-monitor-status', [
    ['title' => 'AI Log Monitor Status', 'body' => $sec_status, 'open' => true],
], ['always_open' => true]);
?>

<!-- Main Configuration Form (accordion segment 2 lives inside this form) -->
<form method="POST" action="" id="aiMonitorConfigForm">
    <input type="hidden" name="csrf_token" value="<?php echo get_csrf_token(); ?>">
    <input type="hidden" name="action" value="update_config">

    <!-- AI Configuration + Auto-Remediation (side by side) -->
    <?php ob_start(); ?>
    <div class="row g-4 mb-4">
        <!-- AI Configuration Card -->
        <div class="col-md-6">
            <div class="card h-100">
                <div class="card-header">
                    <h5 class="card-title mb-0"><i class="fa fa-cogs"></i> AI Configuration</h5>
                </div>
                <div class="card-body">
                    <div class="mb-3">
                        <div class="form-check form-switch">
                            <input class="form-check-input" type="checkbox" id="general_enabled" name="general_enabled" value="1"
                                   <?php echo cfg_bool($config, 'general', 'enabled') ? 'checked' : ''; ?>>
                            <label class="form-check-label" for="general_enabled"><strong>Enable AI Monitor</strong></label>
                        </div>
                    </div>

                    <div class="mb-3">
                        <label class="form-label" for="ai_base_url">LiteLLM Base URL</label>
                        <input type="text" class="form-control" id="ai_base_url" name="ai_base_url"
                               value="<?php echo htmlspecialchars(cfg($config, 'ai', 'base_url', 'http://localhost:4000/v1')); ?>"
                               placeholder="http://localhost:4000/v1">
                    </div>

                    <div class="mb-3">
                        <label class="form-label" for="ai_api_key">API Key</label>
                        <?php // SECURITY: the field starts masked and EMPTY and the raw
                              // key is NEVER written into page source (not in value, not
                              // in a data-* attribute). Only a last-4 preview is shown in
                              // the placeholder. The Reveal toggle shows/hides whatever the
                              // operator types (a replacement key). Submitting the field
                              // blank keeps the stored key (see the !empty($api_key_value)
                              // guard in the save handler). ?>
                        <div class="input-group">
                            <input type="password" class="form-control" id="ai_api_key" name="ai_api_key"
                                   value=""
                                   autocomplete="off"
                                   data-key-set="<?php echo $api_key_is_set ? '1' : '0'; ?>"
                                   placeholder="<?php echo $api_key_is_set ? htmlspecialchars($api_key_mask) . ' (leave blank to keep)' : 'Enter API key (stored in ' . htmlspecialchars($api_key_file) . ')'; ?>">
                            <button class="btn btn-outline-secondary" type="button"
                                    id="aiApiKeyRevealBtn"
                                    aria-label="Reveal API key"
                                    onclick="revealAiApiKey(this)">
                                <i class="fa fa-eye"></i>
                            </button>
                        </div>
                        <small class="text-muted">Stored separately in <?php echo htmlspecialchars($api_key_file); ?>. <?php echo $api_key_is_set ? 'A key is set (shown masked above); leave blank to keep it, or type a new key to replace it.' : 'No key set yet.'; ?></small>
                    </div>

                    <div class="mb-3">
                        <label class="form-label" for="ai_basic_model">Basic Model</label>
                        <input type="text" class="form-control" id="ai_basic_model" name="ai_basic_model"
                               value="<?php echo htmlspecialchars(cfg($config, 'ai', 'basic_model', 'gpt-4o-mini')); ?>"
                               placeholder="gpt-4o-mini">
                        <small class="text-muted">Used for triage and simple error analysis</small>
                    </div>

                    <div class="mb-3">
                        <label class="form-label" for="ai_advanced_model">Advanced Model</label>
                        <input type="text" class="form-control" id="ai_advanced_model" name="ai_advanced_model"
                               value="<?php echo htmlspecialchars(cfg($config, 'ai', 'advanced_model', 'claude-sonnet-4-20250514')); ?>"
                               placeholder="claude-sonnet-4-20250514">
                        <small class="text-muted">Used for complex diagnosis (escalated from basic)</small>
                    </div>

                    <div class="row">
                        <div class="col-md-6">
                            <div class="mb-3">
                                <label class="form-label" for="ai_max_calls_per_run">Max Calls Per Run</label>
                                <input type="number" class="form-control" id="ai_max_calls_per_run" name="ai_max_calls_per_run"
                                       value="<?php echo intval(cfg($config, 'ai', 'max_calls_per_run', '10')); ?>"
                                       min="1" max="50">
                            </div>
                        </div>
                        <div class="col-md-6">
                            <div class="mb-3">
                                <label class="form-label" for="ai_max_calls_per_day">Max Calls Per Day</label>
                                <input type="number" class="form-control" id="ai_max_calls_per_day" name="ai_max_calls_per_day"
                                       value="<?php echo intval(cfg($config, 'ai', 'max_calls_per_day', '100')); ?>"
                                       min="1" max="500">
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>

        <!-- Auto-Remediation Card -->
        <div class="col-md-6">
            <div class="card h-100">
                <div class="card-header">
                    <h5 class="card-title mb-0"><i class="fa fa-wrench"></i> Auto-Remediation</h5>
                </div>
                <div class="card-body">
                    <?php // Hidden by default; inline script unhides it iff the user
                          // has not dismissed it previously. Dismiss state lives in
                          // localStorage so it persists across reloads on this browser. ?>
                    <div id="remediation-rollout-tip"
                         class="alert alert-warning alert-dismissible small mb-3 fade show d-none"
                         role="alert">
                        <i class="fa fa-exclamation-triangle"></i>
                        <strong>Recommended rollout:</strong> leave <em>Enabled</em> off until you have watched
                        a few days of dry-run output, then turn <em>Enabled</em> on but keep <em>Dry-run mode</em>
                        on. Once the would-have-done log looks right, finally turn <em>Dry-run mode</em> off.
                        <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
                    </div>
                    <script>
                    (function() {
                        var tip = document.getElementById('remediation-rollout-tip');
                        if (!tip) return;
                        var KEY = 'whp_remediation_rollout_dismissed';
                        try {
                            if (localStorage.getItem(KEY) !== '1') {
                                tip.classList.remove('d-none');
                            }
                            tip.addEventListener('closed.bs.alert', function() {
                                try { localStorage.setItem(KEY, '1'); } catch (_e) {}
                            });
                        } catch (_e) {
                            // localStorage blocked (private browsing, etc.) -- always show.
                            tip.classList.remove('d-none');
                        }
                    })();
                    </script>

                    <div class="mb-3">
                        <div class="form-check form-switch">
                            <input class="form-check-input" type="checkbox" id="remediation_enabled" name="remediation_enabled" value="1"
                                   <?php echo cfg_bool($config, 'remediation', 'enabled') ? 'checked' : ''; ?>>
                            <label class="form-check-label" for="remediation_enabled"><strong>Enable Auto-Remediation</strong></label>
                        </div>
                    </div>

                    <div class="mb-3">
                        <div class="form-check form-switch">
                            <input class="form-check-input" type="checkbox" id="remediation_dry_run" name="remediation_dry_run" value="1"
                                   <?php echo cfg_bool($config, 'remediation', 'dry_run', true) ? 'checked' : ''; ?>>
                            <label class="form-check-label" for="remediation_dry_run">
                                <strong>Dry-run mode</strong> (log decisions, do not execute)
                            </label>
                        </div>
                        <small class="text-muted">Runs the full pipeline (allowlist + guards) but stops before the actual restart command. Use to validate decisions safely.</small>
                    </div>

                    <div class="mb-3">
                        <div class="form-check">
                            <input class="form-check-input" type="checkbox" id="remediation_require_high_conf" name="remediation_require_high_conf" value="1"
                                   <?php echo cfg_bool($config, 'remediation', 'require_high_confidence', true) ? 'checked' : ''; ?>>
                            <label class="form-check-label" for="remediation_require_high_conf">
                                Require <code>confidence=high</code> from AI before acting
                            </label>
                        </div>
                    </div>

                    <hr>

                    <h6 class="mb-2"><i class="fa fa-shield"></i> Backup-protection guard</h6>
                    <p class="small text-muted mb-2">
                        While a backup is running we refuse to restart anything <strong>unless</strong>
                        the system is at imminent risk of collapse. "At risk" is when 1-min loadavg
                        exceeds <code>multiplier × cores</code> AND swap usage exceeds <code>%</code>.
                        In that state the engine pauses the backup instead of restarting.
                    </p>
                    <div class="row g-2 mb-3">
                        <div class="col-6">
                            <label class="form-label small" for="remediation_load_multiplier">Load × cores</label>
                            <input type="number" step="0.5" class="form-control form-control-sm" id="remediation_load_multiplier" name="remediation_load_multiplier"
                                   value="<?php echo htmlspecialchars(cfg($config, 'remediation', 'backup_load_multiplier', '4.0')); ?>"
                                   min="1" max="10">
                        </div>
                        <div class="col-6">
                            <label class="form-label small" for="remediation_swap_threshold">Swap %</label>
                            <input type="number" class="form-control form-control-sm" id="remediation_swap_threshold" name="remediation_swap_threshold"
                                   value="<?php echo intval(cfg($config, 'remediation', 'backup_swap_threshold', '90')); ?>"
                                   min="50" max="99">
                        </div>
                    </div>

                    <hr>

                    <div class="mb-3">
                        <label class="form-label" for="remediation_cooldown_minutes">Cooldown Between Remediations (minutes)</label>
                        <input type="number" class="form-control" id="remediation_cooldown_minutes" name="remediation_cooldown_minutes"
                               value="<?php echo intval(cfg($config, 'remediation', 'cooldown_minutes', '60')); ?>"
                               min="5" max="120">
                    </div>
                    <div class="mb-3">
                        <label class="form-label" for="remediation_max_per_hour">Max Remediations Per Hour</label>
                        <input type="number" class="form-control" id="remediation_max_per_hour" name="remediation_max_per_hour"
                               value="<?php echo intval(cfg($config, 'remediation', 'max_remediations_per_hour', '5')); ?>"
                               min="1" max="20">
                    </div>
                    <div class="mb-3">
                        <label class="form-label" for="remediation_circuit_breaker">Circuit Breaker Threshold</label>
                        <input type="number" class="form-control" id="remediation_circuit_breaker" name="remediation_circuit_breaker"
                               value="<?php echo intval(cfg($config, 'remediation', 'circuit_breaker_threshold', '3')); ?>"
                               min="1" max="10">
                        <small class="text-muted">Consecutive failures before auto-remediation is paused entirely.</small>
                    </div>

                    <hr>

                    <div class="mb-3">
                        <label class="form-label" for="remediation_allowed_services">Allowed services (comma-separated)</label>
                        <input type="text" class="form-control form-control-sm" id="remediation_allowed_services" name="remediation_allowed_services"
                               value="<?php echo htmlspecialchars(cfg($config, 'remediation', 'allowed_services', 'httpd,php-fpm,proftpd,whp-terminal,whp-backup-upload')); ?>">
                        <small class="text-muted">
                            Host-side <code>systemctl restart</code>. <code>httpd</code> and <code>php-fpm</code>
                            ARE the control panel &mdash; if they're down the panel is unreachable, so they need
                            to be restartable. Risk is managed by dry-run + confidence + cooldown, not by the allowlist.
                        </small>
                    </div>
                    <div class="mb-3">
                        <label class="form-label" for="remediation_allowed_containers">Allowed containers (comma-separated)</label>
                        <input type="text" class="form-control form-control-sm" id="remediation_allowed_containers" name="remediation_allowed_containers"
                               value="<?php echo htmlspecialchars(cfg($config, 'remediation', 'allowed_containers', 'mysql,postgresql,haproxy-manager,memcache')); ?>">
                        <small class="text-muted">
                            <code>docker restart &lt;name&gt;</code> on infrastructure containers.
                            <strong>Customer-site containers</strong> (named <code>&lt;domain&gt;-NN</code>) are
                            also auto-allowed when the engine recognises them in the WHP <code>site_domains</code>
                            table &mdash; you don't need to enumerate them here.
                        </small>
                    </div>

                    <hr>

                    <h6 class="mb-2"><i class="fa fa-list-ol"></i> Category &rarr; action mapping</h6>
                    <p class="small text-muted mb-2">
                        Hardcoded in <code>whp_monitor_core.CATEGORY_ACTIONS</code>. Listed here so root can audit.
                    </p>
                    <table class="table table-sm small mb-0">
                        <thead>
                            <tr><th>Category</th><th>Auto-action</th></tr>
                        </thead>
                        <tbody>
                            <tr><td><code>haproxy_unhealthy</code></td><td><code>docker restart haproxy-manager</code></td></tr>
                            <tr><td><code>connection_storm</code></td><td><code>docker restart haproxy-manager</code></td></tr>
                            <tr><td><code>docker_degraded</code></td><td><code>docker restart &lt;ai-named container&gt;</code></td></tr>
                            <tr><td><code>swap_pressure</code></td><td><code>docker restart &lt;ai-named container&gt;</code></td></tr>
                            <tr><td><code>cpu_pressure</code></td><td class="text-muted">none (no safe blanket fix)</td></tr>
                            <tr><td><code>disk_full</code></td><td class="text-muted">none (use the cleanup banner)</td></tr>
                        </tbody>
                    </table>
                </div>
            </div>
        </div>
    </div>
    <?php $sec_aiconfig = ob_get_clean(); ?>

    <!-- Notifications Card -->
    <?php ob_start(); ?>
    <div class="row g-4 mb-4">
        <div class="col-12">
            <div class="card">
                <div class="card-header">
                    <h5 class="card-title mb-0"><i class="fa fa-bell"></i> Notifications</h5>
                </div>
                <div class="card-body">
                    <div class="mb-3">
                        <div class="form-check form-switch">
                            <input class="form-check-input" type="checkbox" id="notifications_enabled" name="notifications_enabled" value="1"
                                   <?php echo cfg_bool($config, 'notifications', 'enabled') ? 'checked' : ''; ?>>
                            <label class="form-check-label" for="notifications_enabled"><strong>Enable Notifications</strong></label>
                        </div>
                    </div>

                    <div class="row">
                        <div class="col-md-6">
                            <div class="mb-3">
                                <label class="form-label" for="notifications_discord_url"><i class="fa fa-comment"></i> Discord Webhook URL</label>
                                <input type="text" class="form-control" id="notifications_discord_url" name="notifications_discord_url"
                                       value="<?php echo htmlspecialchars(cfg($config, 'notifications', 'discord_webhook_url')); ?>"
                                       placeholder="https://discord.com/api/webhooks/...">
                            </div>
                            <div class="mb-3">
                                <label class="form-label">Discord @Role Mentions <small class="text-muted">(Role ID — right-click role in Discord, Copy ID)</small></label>
                                <div class="row g-2">
                                    <div class="col-md-4">
                                        <div class="input-group input-group-sm">
                                            <span class="input-group-text">Critical</span>
                                            <input type="text" class="form-control" name="notifications_discord_role_critical"
                                                   value="<?php echo htmlspecialchars(cfg($config, 'notifications', 'discord_role_critical')); ?>"
                                                   placeholder="Role ID">
                                        </div>
                                    </div>
                                    <div class="col-md-4">
                                        <div class="input-group input-group-sm">
                                            <span class="input-group-text">Warning</span>
                                            <input type="text" class="form-control" name="notifications_discord_role_warning"
                                                   value="<?php echo htmlspecialchars(cfg($config, 'notifications', 'discord_role_warning')); ?>"
                                                   placeholder="Role ID">
                                        </div>
                                    </div>
                                    <div class="col-md-4">
                                        <div class="input-group input-group-sm">
                                            <span class="input-group-text">Info</span>
                                            <input type="text" class="form-control" name="notifications_discord_role_info"
                                                   value="<?php echo htmlspecialchars(cfg($config, 'notifications', 'discord_role_info')); ?>"
                                                   placeholder="Role ID">
                                        </div>
                                    </div>
                                </div>
                            </div>
                        </div>
                        <div class="col-md-6">
                            <div class="mb-3">
                                <label class="form-label" for="notifications_slack_url"><i class="fa fa-slack"></i> Slack Webhook URL</label>
                                <input type="text" class="form-control" id="notifications_slack_url" name="notifications_slack_url"
                                       value="<?php echo htmlspecialchars(cfg($config, 'notifications', 'slack_webhook_url')); ?>"
                                       placeholder="https://hooks.slack.com/services/...">
                            </div>
                        </div>
                    </div>

                    <div class="row">
                        <div class="col-md-6">
                            <div class="mb-3">
                                <label class="form-label" for="notifications_telegram_token"><i class="fa fa-paper-plane"></i> Telegram Bot Token</label>
                                <input type="text" class="form-control" id="notifications_telegram_token" name="notifications_telegram_token"
                                       value="<?php echo htmlspecialchars(cfg($config, 'notifications', 'telegram_bot_token')); ?>"
                                       placeholder="123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11">
                            </div>
                        </div>
                        <div class="col-md-6">
                            <div class="mb-3">
                                <label class="form-label" for="notifications_telegram_chat_id"><i class="fa fa-paper-plane"></i> Telegram Chat ID</label>
                                <input type="text" class="form-control" id="notifications_telegram_chat_id" name="notifications_telegram_chat_id"
                                       value="<?php echo htmlspecialchars(cfg($config, 'notifications', 'telegram_chat_id')); ?>"
                                       placeholder="-1001234567890">
                            </div>
                        </div>
                    </div>

                    <button type="button" class="btn btn-outline-info btn-sm" id="btnTestNotification">
                        <i class="fa fa-paper-plane-o"></i> Test Notification
                    </button>
                    <small class="text-muted ms-2">Sends a test message using the values currently entered above (does not require saving first)</small>
                </div>
            </div>
        </div>
    </div>
    <?php $sec_notifications = ob_get_clean(); ?>

    <!-- Log Sources Card -->
    <?php ob_start(); ?>
    <div class="row g-4 mb-4">
        <div class="col-12">
            <div class="card">
                <div class="card-header">
                    <h5 class="card-title mb-0"><i class="fa fa-file-text"></i> Log Sources</h5>
                </div>
                <div class="card-body">
                    <h6 class="mb-3">Log Files</h6>
                    <?php foreach ($log_source_defs as $slug => $def):
                        $current_path = cfg($config, 'log_sources', $def['key'], '');
                        $is_log_enabled = !empty($current_path) && $current_path !== 'false';
                        $display_path = ($is_log_enabled && $current_path !== 'true') ? $current_path : $def['default_path'];
                    ?>
                    <div class="row mb-2 align-items-center">
                        <div class="col-md-3">
                            <div class="form-check">
                                <input class="form-check-input log-source-toggle" type="checkbox"
                                       id="log_<?php echo $slug; ?>_enabled" name="log_<?php echo $slug; ?>_enabled" value="1"
                                       data-target="log_<?php echo $slug; ?>_path"
                                       <?php echo $is_log_enabled ? 'checked' : ''; ?>>
                                <label class="form-check-label" for="log_<?php echo $slug; ?>_enabled">
                                    <?php echo htmlspecialchars($def['label']); ?>
                                </label>
                            </div>
                        </div>
                        <div class="col-md-9">
                            <input type="text" class="form-control form-control-sm" id="log_<?php echo $slug; ?>_path" name="log_<?php echo $slug; ?>_path"
                                   value="<?php echo htmlspecialchars($display_path); ?>"
                                   <?php echo $is_log_enabled ? '' : 'disabled'; ?>>
                        </div>
                    </div>
                    <?php endforeach; ?>

                    <!-- dmesg (boolean only, no path) -->
                    <div class="row mb-2 align-items-center">
                        <div class="col-md-3">
                            <div class="form-check">
                                <input class="form-check-input" type="checkbox"
                                       id="log_dmesg_enabled" name="log_dmesg_enabled" value="1"
                                       <?php echo cfg_bool($config, 'log_sources', 'dmesg') ? 'checked' : ''; ?>>
                                <label class="form-check-label" for="log_dmesg_enabled">dmesg (kernel log)</label>
                            </div>
                        </div>
                        <div class="col-md-9">
                            <small class="text-muted">Reads from kernel ring buffer via dmesg command</small>
                        </div>
                    </div>

                    <hr>

                    <!-- Docker Containers -->
                    <h6 class="mb-3">Docker Containers</h6>
                    <div class="mb-3">
                        <label class="form-label" for="docker_system_containers">System Containers (comma-separated)</label>
                        <input type="text" class="form-control" id="docker_system_containers" name="docker_system_containers"
                               value="<?php echo htmlspecialchars(cfg($config, 'docker_containers', 'system', 'mysql,postgresql,haproxy-manager,memcache')); ?>"
                               placeholder="mysql,postgresql,haproxy-manager,memcache">
                    </div>

                    <hr>

                    <!-- Customer Site Monitoring has moved to the Customer
                         Monitoring Management card below. -->

                    <!-- Systemd Services -->
                    <h6 class="mb-3">Systemd Services</h6>
                    <div class="mb-3">
                        <label class="form-label" for="systemd_services_list">Services to Monitor (comma-separated)</label>
                        <input type="text" class="form-control" id="systemd_services_list" name="systemd_services_list"
                               value="<?php echo htmlspecialchars(cfg($config, 'systemd_services', 'monitor', 'httpd,php-fpm,docker,proftpd,whp-terminal,whp-backup-upload')); ?>"
                               placeholder="httpd,php-fpm,docker,proftpd,whp-terminal,whp-backup-upload">
                        <small class="text-muted">Monitored via journalctl for recent errors</small>
                    </div>
                </div>
            </div>
        </div>
    </div>
    <?php $sec_logsources = ob_get_clean(); ?>
    <?php
    // Accordion segment 2: the main configuration form's sections. Rendered
    // INSIDE the config <form> so all inputs still submit together. The first
    // item (AI Configuration) stays open on load.
    echo whp_accordion('ai-monitor-config', [
        ['title' => 'AI Configuration & Auto-Remediation', 'body' => $sec_aiconfig, 'open' => true],
        ['title' => 'Notifications',                       'body' => $sec_notifications],
        ['title' => 'Log Sources',                         'body' => $sec_logsources],
    ], ['always_open' => true]);
    ?>

    <!-- Save Button (kept outside the accordion so it is always reachable) -->
    <div class="row g-4 mb-4">
        <div class="col-12">
            <button type="submit" class="btn btn-success btn-lg">
                <i class="fa fa-save"></i> Save Configuration
            </button>
        </div>
    </div>
</form>

<!-- Customer Monitoring Management -->
<?php
// Load customer monitoring data
$cm_global_enabled = false;
$cm_settings = [];
if (file_exists('/docker/whp/settings.json')) {
    $cm_settings = json_decode(file_get_contents('/docker/whp/settings.json'), true) ?: [];
    $cm_global_enabled = !empty($cm_settings['customer_monitoring']['enabled']);
}

$cm_subscriptions = [];
$cm_available_sites = [];
try {
    if (!isset($whp_db) || !$whp_db) {
        require_once('/docker/whp/web/libs/mysqlmgmt.php');
        $MySQLMgmt_cm = new mysqlmgmt();
        $whp_db_cm = $MySQLMgmt_cm->getMySQLConnection();
    } else {
        $whp_db_cm = $whp_db;
    }
    if ($whp_db_cm) {
        // Active subscriptions
        $stmt_cm = $whp_db_cm->query("
            SELECT sub.*, s.site_name, d.domain_name as primary_domain,
                   (SELECT COUNT(*) FROM whp.ai_monitor_issues i
                      WHERE i.subscription_id = sub.id AND i.status = 'open') as open_issues,
                   (SELECT COUNT(*) FROM whp.ai_monitor_suppressions sup
                      WHERE sup.site_id = sub.site_id) as suppressions
            FROM whp.ai_monitor_subscriptions sub
            JOIN whp.sites s ON sub.site_id = s.id
            JOIN whp.domains d ON s.primary_domain_id = d.id
            ORDER BY sub.status ASC, sub.activated_at DESC
        ");
        $cm_subscriptions = $stmt_cm->fetchAll(PDO::FETCH_ASSOC);

        // Sites without active subscriptions
        $stmt_cm = $whp_db_cm->query("
            SELECT s.id, s.site_name, d.domain_name as domain, s.username
            FROM whp.sites s
            JOIN whp.domains d ON s.primary_domain_id = d.id
            WHERE s.id NOT IN (SELECT site_id FROM whp.ai_monitor_subscriptions WHERE status = 'active')
            ORDER BY s.username, s.site_name
        ");
        $cm_available_sites = $stmt_cm->fetchAll(PDO::FETCH_ASSOC);
    }
} catch (Exception $e) {
    error_log('AI Monitor: Failed to load customer monitoring data: ' . $e->getMessage());
}
?>
<?php ob_start(); ?>
<div class="row g-4 mb-4">
    <div class="col-12">
        <div class="card">
            <div class="card-header d-flex justify-content-between align-items-center">
                <h5 class="card-title mb-0"><i class="fa fa-users"></i> Customer Monitoring Management</h5>
                <div class="d-flex align-items-center gap-2">
                    <a href="index.php?page=ai-monitor-customer" class="btn btn-outline-primary btn-sm">
                        <i class="fa fa-bar-chart me-1"></i>View Site Reports
                    </a>
                    <span class="badge bg-<?php echo $cm_global_enabled ? 'success' : 'secondary'; ?> fs-6">
                        <?php echo $cm_global_enabled ? 'Enabled' : 'Disabled'; ?>
                    </span>
                </div>
            </div>
            <div class="card-body">

                <!-- Global Toggle -->
                <div class="row mb-4">
                    <div class="col-12">
                        <form method="POST" action="" class="d-inline">
                            <input type="hidden" name="csrf_token" value="<?php echo get_csrf_token(); ?>">
                            <input type="hidden" name="action" value="toggle_customer_monitoring">
                            <button type="submit" class="btn btn-<?php echo $cm_global_enabled ? 'warning' : 'success'; ?> btn-sm">
                                <i class="fa fa-power-off"></i> <?php echo $cm_global_enabled ? 'Disable' : 'Enable'; ?> Customer Monitoring Globally
                            </button>
                        </form>
                        <small class="text-muted ms-2">Controls <code>settings.json &rarr; customer_monitoring.enabled</code></small>
                    </div>
                </div>

                <!-- Subscription List Table -->
                <h6 class="mb-3"><i class="fa fa-list"></i> Active Subscriptions</h6>
                <?php if (empty($cm_subscriptions)): ?>
                <p class="text-muted">No subscriptions found.</p>
                <?php else: ?>
                <div class="table-responsive mb-4">
                    <table class="table table-striped table-hover table-sm align-middle">
                        <thead>
                            <tr>
                                <th>Site Name</th>
                                <th>Domain</th>
                                <th>Username</th>
                                <th>Status</th>
                                <th>Open Issues</th>
                                <th>Suppressions</th>
                                <th>Daily Review Limit</th>
                                <th>Activated At</th>
                                <th>Actions</th>
                            </tr>
                        </thead>
                        <tbody>
                            <?php foreach ($cm_subscriptions as $sub): ?>
                            <tr>
                                <td><?php echo htmlspecialchars($sub['site_name']); ?></td>
                                <td><code><?php echo htmlspecialchars($sub['primary_domain']); ?></code></td>
                                <td><?php echo htmlspecialchars($sub['username']); ?></td>
                                <td>
                                    <?php
                                    $badge_class = 'secondary';
                                    if ($sub['status'] === 'active') $badge_class = 'success';
                                    elseif ($sub['status'] === 'suspended') $badge_class = 'warning';
                                    elseif ($sub['status'] === 'cancelled') $badge_class = 'danger';
                                    ?>
                                    <span class="badge bg-<?php echo $badge_class; ?>"><?php echo htmlspecialchars(ucfirst($sub['status'])); ?></span>
                                </td>
                                <td>
                                    <?php if (intval($sub['open_issues']) > 0): ?>
                                    <span class="badge bg-warning text-dark"><?php echo intval($sub['open_issues']); ?></span>
                                    <?php else: ?>
                                    <span class="text-muted">0</span>
                                    <?php endif; ?>
                                </td>
                                <td>
                                    <?php if (intval($sub['suppressions'] ?? 0) > 0): ?>
                                    <span class="badge bg-secondary"><?php echo intval($sub['suppressions']); ?></span>
                                    <?php else: ?>
                                    <span class="text-muted">0</span>
                                    <?php endif; ?>
                                </td>
                                <td>
                                    <form method="POST" action="" class="d-inline-flex align-items-center gap-1">
                                        <input type="hidden" name="csrf_token" value="<?php echo get_csrf_token(); ?>">
                                        <input type="hidden" name="action" value="update_review_limit">
                                        <input type="hidden" name="subscription_id" value="<?php echo intval($sub['id']); ?>">
                                        <input type="number" name="daily_review_limit" class="form-control form-control-sm" style="width: 70px;"
                                               value="<?php echo intval($sub['daily_review_limit']); ?>" min="1" max="50">
                                        <button type="submit" class="btn btn-outline-primary btn-sm" title="Update limit">
                                            <i class="fa fa-check"></i>
                                        </button>
                                    </form>
                                </td>
                                <td><?php echo $sub['activated_at'] ? whp_local_time($sub['activated_at'], 'M j, Y g:i A') : 'N/A'; ?></td>
                                <td>
                                    <?php if ($sub['status'] === 'active'): ?>
                                    <form method="POST" action="" class="d-inline" onsubmit="return confirm('Deactivate monitoring for this site?');">
                                        <input type="hidden" name="csrf_token" value="<?php echo get_csrf_token(); ?>">
                                        <input type="hidden" name="action" value="disable_site_monitoring">
                                        <input type="hidden" name="subscription_id" value="<?php echo intval($sub['id']); ?>">
                                        <button type="submit" class="btn btn-outline-danger btn-sm" title="Deactivate">
                                            <i class="fa fa-times"></i> Deactivate
                                        </button>
                                    </form>
                                    <?php else: ?>
                                    <span class="text-muted">-</span>
                                    <?php endif; ?>
                                </td>
                            </tr>
                            <?php endforeach; ?>
                        </tbody>
                    </table>
                </div>
                <?php endif; ?>

                <!-- Enable Monitoring Form -->
                <hr>
                <h6 class="mb-3"><i class="fa fa-plus-circle"></i> Enable Monitoring for a Site</h6>
                <?php if (empty($cm_available_sites)): ?>
                <p class="text-muted">All sites already have active monitoring subscriptions, or no sites exist.</p>
                <?php else: ?>
                <form method="POST" action="" class="row g-3 align-items-end">
                    <input type="hidden" name="csrf_token" value="<?php echo get_csrf_token(); ?>">
                    <input type="hidden" name="action" value="enable_site_monitoring">
                    <div class="col-md-4">
                        <label class="form-label" for="cm_site_id">Site</label>
                        <select class="form-control" id="cm_site_id" name="site_id" required>
                            <option value="">-- Select a site --</option>
                            <?php foreach ($cm_available_sites as $avail_site): ?>
                            <option value="<?php echo intval($avail_site['id']); ?>">
                                <?php echo htmlspecialchars($avail_site['domain']); ?>
                                <?php if (!empty($avail_site['site_name'])): ?>
                                    (<?php echo htmlspecialchars($avail_site['site_name']); ?>)
                                <?php endif; ?>
                                — <?php echo htmlspecialchars($avail_site['username']); ?>
                            </option>
                            <?php endforeach; ?>
                        </select>
                    </div>
                    <div class="col-md-4">
                        <label class="form-label" for="cm_notification_email">Notification Email <small class="text-muted">(optional)</small></label>
                        <input type="email" class="form-control" id="cm_notification_email" name="notification_email" placeholder="user@example.com">
                    </div>
                    <div class="col-md-4">
                        <button type="submit" class="btn btn-success">
                            <i class="fa fa-plus"></i> Enable Monitoring
                        </button>
                    </div>
                </form>
                <?php endif; ?>

            </div>
        </div>
    </div>
</div>
<?php $sec_customer = ob_get_clean(); ?>
<?php
// Accordion segment 3: Customer Monitoring Management. Has its own independent
// forms, so it is rendered OUTSIDE the main config <form> as its own segment.
echo whp_accordion('ai-monitor-customer-mgmt', [
    ['title' => 'Customer Monitoring Management', 'body' => $sec_customer],
], ['always_open' => true]);
?>

<!-- Hidden form for Test Notification (submitted via JS) -->
<form method="POST" action="" id="testNotificationForm" style="display:none;">
    <input type="hidden" name="csrf_token" value="<?php echo get_csrf_token(); ?>">
    <input type="hidden" name="action" value="test_notification">
    <input type="hidden" name="test_discord_url" id="test_discord_url">
    <input type="hidden" name="test_slack_url" id="test_slack_url">
    <input type="hidden" name="test_telegram_token" id="test_telegram_token">
    <input type="hidden" name="test_telegram_chat_id" id="test_telegram_chat_id">
</form>

<script>
// Toggle password visibility
function togglePasswordVisibility(inputId, btn) {
    var input = document.getElementById(inputId);
    if (input.type === 'password') {
        input.type = 'text';
        btn.innerHTML = '<i class="fa fa-eye-slash"></i>';
    } else {
        input.type = 'password';
        btn.innerHTML = '<i class="fa fa-eye"></i>';
    }
}

// Reveal/hide the API key field on demand. The stored key is never sent to the
// browser, so this only shows/hides whatever replacement key the operator types.
// The currently stored key is previewed (last 4) in the field placeholder.
function revealAiApiKey(btn) {
    var input = document.getElementById('ai_api_key');
    if (!input) return;
    var icon = btn.querySelector('i');
    if (input.type === 'password') {
        input.type = 'text';
        if (icon) { icon.classList.remove('fa-eye'); icon.classList.add('fa-eye-slash'); }
        btn.setAttribute('aria-label', 'Hide API key');
    } else {
        input.type = 'password';
        if (icon) { icon.classList.remove('fa-eye-slash'); icon.classList.add('fa-eye'); }
        btn.setAttribute('aria-label', 'Reveal API key');
    }
}

// Toggle log source path fields based on checkbox state
document.querySelectorAll('.log-source-toggle').forEach(function(checkbox) {
    checkbox.addEventListener('change', function() {
        var targetId = this.getAttribute('data-target');
        var target = document.getElementById(targetId);
        if (target) {
            target.disabled = !this.checked;
        }
    });
});

// Test Notification button handler
document.getElementById('btnTestNotification').addEventListener('click', function() {
    // Copy current form values into the hidden test form
    document.getElementById('test_discord_url').value = document.getElementById('notifications_discord_url').value;
    document.getElementById('test_slack_url').value = document.getElementById('notifications_slack_url').value;
    document.getElementById('test_telegram_token').value = document.getElementById('notifications_telegram_token').value;
    document.getElementById('test_telegram_chat_id').value = document.getElementById('notifications_telegram_chat_id').value;

    // Submit the hidden form
    this.disabled = true;
    this.innerHTML = '<i class="fa fa-spinner fa-spin"></i> Sending...';
    document.getElementById('testNotificationForm').submit();
});
</script>
