<?php
if (!defined('ABSPATH')) exit;

require_once('qtrAlarmTypes.php');
require_once('qtrLogger.php');

/**
 * Alarm Factory - generates standardized alarm messages with HTML and plain text formats
 *
 * Each alarm type has a dedicated template with:
 * - subject: Email subject line
 * - title: Alarm title
 * - severity: info|warning|error|critical
 * - body: HTML formatted message with placeholders for parameters
 *
 * Returns both formats:
 * - body_html: For email sending (styled HTML)
 * - body: For database storage (plain text for dashboard)
 *
 * Usage:
 *   $alarm = CQtrAlarmFactory::generate(
 *       CQtrAlarmTypes::TYPE_LOGIN_FAILED,
 *       ['username' => 'admin', 'ip' => '192.168.1.1', 'timestamp' => date('Y-m-d H:i:s')]
 *   );
 *   echo $alarm['subject'];     // Email subject
 *   echo $alarm['body_html'];   // HTML body for email
 *   echo $alarm['body'];        // Plain text body for database
 *   echo $alarm['severity'];    // info|warning|error|critical
 */
class CQtrAlarmFactory
{
    private static $templates = array();
    private static $initialized = false;

    /**
     * Initialize alarm templates
     * Called once on first use
     */
    private static function init_templates()
    {
        if (self::$initialized) return;
        self::$initialized = true;

        // ========== BRUTE FORCE ALARMS ==========

        self::register_template(CQtrAlarmTypes::TYPE_BRUTE_FORCE_BLACKLIST, array(
            'subject' => 'Security Alert: Blacklisted IP Login Attempt',
            'title' => 'Blacklisted IP Login Attempt',
            'severity' => 'critical',
            'body_html' => '<p><strong>A login attempt was detected from a blacklisted IP address.</strong></p>'
                . '<p>This IP has been identified as a known threat and has been previously blocked.</p>'
                . '<ul>'
                . '<li><strong>Site:</strong> {site_name}</li>'
                . '<li><strong>IP Address:</strong> {ip}</li>'
                . '<li><strong>Username Attempted:</strong> {username}</li>'
                . '<li><strong>Timestamp:</strong> {timestamp}</li>'
                . '</ul>'
                . '<p style="color: #d9534f;"><strong>Action Taken:</strong> Login attempt was blocked.</p>',
            'body_text' => 'A login attempt was detected from a blacklisted IP address ({ip}).'
        ));

        self::register_template(CQtrAlarmTypes::TYPE_BRUTE_FORCE_IP_LOCK, array(
            'subject' => 'Security Alert: Login Blocked - IP Lock Active',
            'title' => 'Brute-Force IP-Based Lock Applied',
            'severity' => 'warning',
            'body_html' => '<p><strong>Login attempts from an IP address have exceeded the allowed threshold.</strong></p>'
                . '<p>The IP has been temporarily locked to prevent brute force attacks.</p>'
                . '<ul>'
                . '<li><strong>Site:</strong> {site_name}</li>'
                . '<li><strong>IP Address:</strong> {ip}</li>'
                . '<li><strong>Username Attempted:</strong> {username}</li>'
                . '<li><strong>Timestamp:</strong> {timestamp}</li>'
                . '</ul>'
                . '<p><strong>Status:</strong> IP address locked until reset.</p>',
            'body_text' => 'IP lock applied for {ip} (username: {username}).'
        ));

        self::register_template(CQtrAlarmTypes::TYPE_BRUTE_FORCE_COMBO_LOCK, array(
            'subject' => 'Security Alert: Login Blocked - User+IP Lock',
            'title' => 'User and IP-Based Lock Applied',
            'severity' => 'warning',
            'body_html' => '<p><strong>Combined user and IP-based lock has been applied.</strong></p>'
                . '<p>This user account and IP combination has exceeded failed login attempts.</p>'
                . '<ul>'
                . '<li><strong>Site:</strong> {site_name}</li>'
                . '<li><strong>IP Address:</strong> {ip}</li>'
                . '<li><strong>Username:</strong> {username}</li>'
                . '<li><strong>Timestamp:</strong> {timestamp}</li>'
                . '</ul>'
                . '<p><strong>Status:</strong> User+IP combination locked.</p>',
            'body_text' => 'User+IP lock applied for {username} from {ip}.'
        ));

        self::register_template(CQtrAlarmTypes::TYPE_BRUTE_FORCE_SOFT_LOCK, array(
            'subject' => 'Security Alert: Soft Lock Applied - Multiple Failed Logins',
            'title' => 'Soft Lock Applied',
            'severity' => 'warning',
            'body_html' => '<p><strong>Multiple failed login attempts detected. A soft lock has been applied.</strong></p>'
                . '<p>Access is temporarily restricted to prevent brute force attacks.</p>'
                . '<ul>'
                . '<li><strong>Site:</strong> {site_name}</li>'
                . '<li><strong>IP Address:</strong> {ip}</li>'
                . '<li><strong>Username:</strong> {username}</li>'
                . '<li><strong>Failed Attempts (10m):</strong> {fails10m}</li>'
                . '<li><strong>Lock Duration:</strong> {lock_duration}</li>'
                . '<li><strong>Timestamp:</strong> {timestamp}</li>'
                . '</ul>'
                . '<p><strong>Status:</strong> Access temporarily restricted.</p>',
            'body_text' => 'Soft lock applied for {username} from {ip}. Failed attempts: {fails10m}. Duration: {lock_duration}.'
        ));

        self::register_template(CQtrAlarmTypes::TYPE_BRUTE_FORCE_HARD_LOCK, array(
            'subject' => 'CRITICAL: Hard Lock Escalation - Repeated Attack',
            'title' => 'Hard Lock Escalation - Critical Threat',
            'severity' => 'critical',
            'body_html' => '<p style="color: #d9534f;"><strong>CRITICAL: A hard lock has been escalated due to repeated brute force attacks.</strong></p>'
                . '<p>This represents an escalation from soft lock due to continued attack attempts.</p>'
                . '<ul>'
                . '<li><strong>Site:</strong> {site_name}</li>'
                . '<li><strong>IP Address:</strong> {ip}</li>'
                . '<li><strong>Username:</strong> {username}</li>'
                . '<li><strong>Failed Attempts (10m):</strong> {fails10m}</li>'
                . '<li><strong>Lock Duration:</strong> {lock_duration}</li>'
                . '<li><strong>Timestamp:</strong> {timestamp}</li>'
                . '</ul>'
                . '<p style="color: #d9534f;"><strong>Action Required:</strong> Review logs and consider additional security measures.</p>',
            'body_text' => 'CRITICAL: Hard lock escalated for {username} from {ip}. Failed attempts: {fails10m}. Action required.'
        ));

        self::register_template(CQtrAlarmTypes::TYPE_BRUTE_FORCE_SPRAY, array(
            'subject' => 'CRITICAL: Spray Attack Detected',
            'title' => 'Spray Attack - Multiple Users Targeted',
            'severity' => 'critical',
            'body_html' => '<p style="color: #d9534f;"><strong>CRITICAL: A spray attack has been detected.</strong></p>'
                . '<p>Multiple user accounts are being targeted from the same IP address.</p>'
                . '<ul>'
                . '<li><strong>Site:</strong> {site_name}</li>'
                . '<li><strong>Source IP:</strong> {ip}</li>'
                . '<li><strong>Number of Distinct Users Targeted:</strong> {distinct_users}</li>'
                . '<li><strong>Failed Attempts (10m):</strong> {fails10m}</li>'
                . '<li><strong>Timestamp:</strong> {timestamp}</li>'
                . '</ul>'
                . '<p style="color: #d9534f;"><strong>Threat Level:</strong> High - Coordinated attack pattern detected.</p>',
            'body_text' => 'CRITICAL: Spray attack from {ip} targeting {distinct_users} users. Failed attempts: {fails10m}.'
        ));

        self::register_template(CQtrAlarmTypes::TYPE_BRUTE_FORCE_UNLOCK_SENT, array(
            'subject' => 'Admin Lock: Unlock Link Sent',
            'title' => 'Unlock Link Sent to Administrator',
            'severity' => 'info',
            'body_html' => '<p><strong>An unlock link has been sent to the administrator.</strong></p>'
                . '<p>This allows manual unlocking of a locked account or IP.</p>'
                . '<ul>'
                . '<li><strong>Site:</strong> {site_name}</li>'
                . '<li><strong>IP Address:</strong> {ip}</li>'
                . '<li><strong>Username:</strong> {username}</li>'
                . '<li><strong>Timestamp:</strong> {timestamp}</li>'
                . '</ul>'
                . '<p><strong>Note:</strong> Check your email for the unlock link.</p>',
            'body_text' => 'Unlock link sent for {username} from {ip}.'
        ));

        // ========== ADMIN ACCOUNT LOCKED ==========

        self::register_template(CQtrAlarmTypes::TYPE_ADMIN_ACCOUNT_LOCKED, array(
            'subject' => 'WordPress Admin Account Temporary Restricted',
            'title' => 'WordPress Admin Account Temporary Restricted',
            'severity' => 'warning',
            'body_html' => '<p>Hello,</p>'
                . '<p>Your WordPress administrator account has been temporarily restricted after several unsuccessful login attempts. This is a standard security measure to help protect your site.</p>'
                . '<p><strong>Automatic recovery</strong></p>'
                . '<p>Access is restored automatically within 30–60 minutes. Once the restriction expires, you can log in normally.</p>'
                . '<p><strong>Immediate recovery (if access is needed sooner)</strong></p>'
                . '<p>A site administrator can temporarily disable login protection by adding the following line to the <code>wp-config.php</code> file:</p>'
                . '<p><code>define(\'QTR_BRUTEFORCE_DISABLE\', true);</code></p>'
                . '<p>After logging in successfully, this line should be removed to keep your site protected.</p>'
                . '<p>If you did not attempt to log in, we recommend updating your password once access is restored.</p>'
                . '<p>This message was sent automatically by your WordPress security system.</p>'
                . '<hr />'
                . '<p><strong>Blocked User Details:</strong></p>'
                . '<ul>'
                . '<li>Site: <code>{site_name}</code></li>'
                . '<li>Username: <code>{username}</code></li>'
                . '<li>Email: <code>{email}</code></li>'
                . '<li>IP Address: <code>{ip}</code></li>'
                . '</ul>',
            'body_text' => 'Admin login locked for user {username} ({email}) from {ip}.'
        ));

        // ========== LOGIN SECURITY ALARMS ==========

        self::register_template(CQtrAlarmTypes::TYPE_LOGIN_FAILED, array(
            'subject' => 'Security Alert: Admin Login Failed',
            'title' => 'Failed Administrator Login',
            'severity' => 'warning',
            'body_html' => '<p><strong>A failed administrator login attempt has been detected.</strong></p>'
                . '<ul>'
                . '<li><strong>Username Attempted:</strong> {username}</li>'
                . '<li><strong>IP Address:</strong> {ip}</li>'
                . '<li><strong>Timestamp:</strong> {timestamp}</li>'
                . '</ul>'
                . '<p>If this was not you, ensure your password is secure.</p>',
            'body_text' => 'Failed admin login attempt for {username} from {ip}.'
        ));

        self::register_template(CQtrAlarmTypes::TYPE_LOGIN_FAILED_WARNING, array(
            'subject' => 'Security Warning: Multiple Admin Login Failures',
            'title' => 'Multiple Failed Administrator Logins',
            'severity' => 'warning',
            'body_html' => '<p><strong>Multiple failed login attempts detected for an administrator account.</strong></p>'
                . '<ul>'
                . '<li><strong>Username:</strong> {username}</li>'
                . '<li><strong>Failures in Last Hour:</strong> {failure_count}</li>'
                . '<li><strong>Affected IPs:</strong> {affected_ips}</li>'
                . '<li><strong>Last Attempt:</strong> {timestamp}</li>'
                . '</ul>'
                . '<p>If these were not your attempts, change your password immediately.</p>',
            'body_text' => 'Multiple login failures detected for {username}: {failure_count} attempts in the last hour.'
        ));

        self::register_template(CQtrAlarmTypes::TYPE_LOGIN_FAILED_CRITICAL, array(
            'subject' => 'CRITICAL: Brute Force Attack Detected on Admin Account',
            'title' => 'Brute Force Attack - Immediate Action Required',
            'severity' => 'critical',
            'body_html' => '<p><strong>A brute force attack has been detected targeting your administrator account!</strong></p>'
                . '<p><strong>This requires immediate attention.</strong></p>'
                . '<ul>'
                . '<li><strong>Username Under Attack:</strong> {username}</li>'
                . '<li><strong>Total Failed Attempts:</strong> {failure_count}</li>'
                . '<li><strong>Attack Duration:</strong> {attack_duration}</li>'
                . '<li><strong>Attacking IPs:</strong> {affected_ips}</li>'
                . '</ul>'
                . '<p><strong>Recommended Actions:</strong></p>'
                . '<ol>'
                . '<li>Change your password immediately</li>'
                . '<li>Enable two-factor authentication (2FA) if available</li>'
                . '<li>Review and update your access control list</li>'
                . '<li>Monitor your site for unauthorized access</li>'
                . '</ol>',
            'body_text' => 'CRITICAL: Brute force attack detected on {username} with {failure_count} attempts.'
        ));

        self::register_template(CQtrAlarmTypes::TYPE_LOGIN_FAILED_SUMMARY, array(
            'subject' => 'Daily Login Failure Summary - {site_name}',
            'title' => 'Daily Administrator Login Security Report',
            'severity' => 'info',
            'body_html' => '<p><strong>Your daily login security summary for the past 24 hours.</strong></p>'
                . '<p><strong>Summary:</strong></p>'
                . '<ul>'
                . '<li><strong>Website:</strong> {site_name}</li>'
                . '<li><strong>Total Failed Attempts:</strong> {total_failures}</li>'
                . '<li><strong>Affected Usernames:</strong> {affected_users}</li>'
                . '<li><strong>Unique IP Addresses:</strong> {unique_ips}</li>'
                . '<li><strong>Reporting Period:</strong> {period}</li>'
                . '</ul>'
                . '<p>Review the details above and take appropriate security measures if needed.</p>',
            'body_text' => 'Daily login failure summary: {total_failures} attempts across {affected_users} user(s) from {unique_ips} IP(s).'
        ));

        self::register_template(CQtrAlarmTypes::TYPE_LOGIN_SUCCESS, array(
            'subject' => 'Admin Login Successful',
            'title' => 'Administrator Login Successful',
            'severity' => 'info',
            'body_html' => '<p><strong>An administrator has successfully logged in to {site_name}.</strong></p>'
                . '<ul>'
                . '<li><strong>Website:</strong> {site_name}</li>'
                . '<li><strong>Username:</strong> {username}</li>'
                . '<li><strong>IP Address:</strong> {ip}</li>'
                . '<li><strong>Timestamp:</strong> {timestamp}</li>'
                . '</ul>'
                . '<p>If this was not you, your account may be compromised.</p>',
            'body_text' => 'Admin login successful at {site_name}: {username} from {ip}.'
        ));

        // ========== ADMIN MONITORING ALARMS ==========

        self::register_template(CQtrAlarmTypes::TYPE_ADMIN_ADDED, array(
            'subject' => 'CRITICAL: New Administrator Account Created',
            'title' => 'New Administrator Added - Critical Alert',
            'severity' => 'critical',
            'body_html' => '<p style="color: #d9534f;"><strong>CRITICAL: A new administrator account has been created.</strong></p>'
                . '<p>This is a significant security event that requires immediate attention.</p>'
                . '<ul>'
                . '<li><strong>Site:</strong> {site_name}</li>'
                . '<li><strong>New Administrator(s):</strong> {user_list}</li>'
                . '<li><strong>Timestamp:</strong> {timestamp}</li>'
                . '</ul>'
                . '<p style="color: #d9534f;"><strong>Warning:</strong> Verify this change immediately. Unauthorized admin accounts are a critical security threat.</p>',
            'body_text' => 'CRITICAL: New administrator account created: {user_list}. Verify immediately.'
        ));

        self::register_template(CQtrAlarmTypes::TYPE_ADMIN_REMOVED, array(
            'subject' => 'Alert: Administrator Account Removed',
            'title' => 'Administrator Account Removed',
            'severity' => 'warning',
            'body_html' => '<p><strong>An administrator account has been removed.</strong></p>'
                . '<ul>'
                . '<li><strong>Site:</strong> {site_name}</li>'
                . '<li><strong>Removed Administrator(s):</strong> {user_list}</li>'
                . '<li><strong>Timestamp:</strong> {timestamp}</li>'
                . '</ul>'
                . '<p>Ensure this removal was authorized.</p>',
            'body_text' => 'Administrator account removed: {user_list}. Verify authorization.'
        ));

        self::register_template(CQtrAlarmTypes::TYPE_ADMIN_ROLE_CHANGED, array(
            'subject' => 'CRITICAL: User Role Changed to Administrator',
            'title' => 'User Promoted to Administrator - Critical Alert',
            'severity' => 'critical',
            'body_html' => '<p style="color: #d9534f;"><strong>CRITICAL: A user\'s role has been changed to administrator.</strong></p>'
                . '<p>This is a significant security event that requires immediate attention.</p>'
                . '<ul>'
                . '<li><strong>Site:</strong> {site_name}</li>'
                . '<li><strong>User Promoted:</strong> {user_list}</li>'
                . '<li><strong>User Email:</strong> {user_email}</li>'
                . '<li><strong>Timestamp:</strong> {timestamp}</li>'
                . '</ul>'
                . '<p style="color: #d9534f;"><strong>Warning:</strong> Verify this change immediately. Unauthorized admin promotions are a critical security threat.</p>',
            'body_text' => 'CRITICAL: User role changed to administrator: {user_list}. Verify immediately.'
        ));

        // ========== BOT PROTECTION ALARMS ==========

        self::register_template(CQtrAlarmTypes::TYPE_BOT_BLOCK, array(
            'subject' => 'Security: Bot/Attack Protection Triggered',
            'title' => 'Bot or Attack Blocked',
            'severity' => 'info',
            'body_html' => '<p><strong>Bot protection or attack prevention has been triggered.</strong></p>'
                . '<ul>'
                . '<li><strong>Source IP:</strong> {ip}</li>'
                . '<li><strong>Risk Level:</strong> {risk_level}</li>'
                . '<li><strong>Reason:</strong> {reason}</li>'
                . '<li><strong>Endpoint:</strong> {endpoint}</li>'
                . '<li><strong>Timestamp:</strong> {timestamp}</li>'
                . '</ul>'
                . '<p><strong>Status:</strong> Malicious request blocked.</p>',
            'body_text' => 'Bot protection triggered for {ip}. Risk: {risk_level}. Reason: {reason}.'
        ));
    }

    /**
     * Generate alarm message from template
     *
     * @param string $alarm_type Type constant from CQtrAlarmTypes
     * @param array $params Parameters to replace in template (e.g., ['ip' => '192.168.1.1', 'username' => 'admin'])
     *
     * @return array|WP_Error Array with keys:
     *                        - subject: Email subject line
     *                        - title: Alarm title
     *                        - severity: info|warning|error|critical
     *                        - body: Plain text body (for database storage)
     *                        - body_html: HTML body (for email sending)
     *                        or WP_Error if template not found
     */
    public static function generate($alarm_type, $params = array())
    {
        self::init_templates();

        if (!isset(self::$templates[$alarm_type])) {
            $logger = new CQtrLogger();
            $logger->Error("Unknown alarm type: " . $alarm_type);
            return new WP_Error('unknown_alarm_type', 'Alarm type not found: ' . $alarm_type);
        }

        $template = self::$templates[$alarm_type];
        $logger = new CQtrLogger();

        // Validate that all required parameters are provided
        $body_html_template = $template['body_html'];
        preg_match_all('/\{([a-z_]+)\}/i', $body_html_template, $matches);
        $required_params = isset($matches[1]) ? array_unique($matches[1]) : array();

        foreach ($required_params as $param_name) {
            if (!isset($params[$param_name])) {
                $logger->Warning("Missing parameter '{$param_name}' for alarm type: " . $alarm_type);
            }
        }

        // Replace parameters in both HTML and plain text bodies
        $body_html = self::replace_params($template['body_html'], $params);
        $body_plain = self::replace_params($template['body_text'], $params);

        // Determine severity (may be overridden for dynamic risk-based alarms)
        $severity = $template['severity'];
        if ($alarm_type === CQtrAlarmTypes::TYPE_BOT_BLOCK && isset($params['risk_level'])) {
            $severity = self::map_risk_level_to_severity($params['risk_level']);
        }

        return array(
            'subject' => $template['subject'],
            'title' => $template['title'],
            'severity' => $severity,
            'body' => $body_plain,        // Plain text for database storage
            'body_html' => $body_html,    // HTML for email sending
        );
    }

    /**
     * Replace template placeholders with actual values
     *
     * @param string $template Template string with {placeholder} patterns
     * @param array $params Key-value pairs for replacement
     * 
     * @return string Template with placeholders replaced and HTML-escaped
     */
    private static function replace_params($template, $params = array())
    {
        $search = array();
        $replace = array();

        foreach ((array)$params as $key => $value) {
            $search[] = '{' . $key . '}';
            // HTML escape to prevent injection
            $replace[] = htmlspecialchars((string)$value, ENT_QUOTES, 'UTF-8');
        }

        $result = str_replace($search, $replace, $template);

        // Remove any unreplaced placeholders
        $result = preg_replace('/\{[a-z_]+\}/i', '', $result);

        return $result;
    }

    /**
     * Map risk level text to alarm severity level
     * 
     * Converts risk classification (from bot protection or other sources)
     * to appropriate alarm severity for notifications and dashboard display.
     * 
     * @param string $risk_level Risk level text (info|warning|critical|emergency)
     * @return string Alarm severity (info|warning|error|critical)
     */
    private static function map_risk_level_to_severity(string $risk_level): string
    {
        $risk_level = strtolower(trim($risk_level));
        
        $mapping = [
            'info'      => 'info',      // Low risk → info severity
            'warning'   => 'warning',   // Medium risk → warning severity
            'critical'  => 'error',     // High risk → error severity
            'emergency' => 'critical',  // Severe risk → critical severity
        ];
        
        return isset($mapping[$risk_level]) ? $mapping[$risk_level] : 'warning';
    }

    /**
     * Convert HTML alarm body to plain text
     * Useful for email clients that don't support HTML
     *
     * @param string $html HTML content
     *
     * @return string Plain text version
     */
    public static function to_plain_text($html)
    {
        // Remove HTML tags
        $text = strip_tags($html);

        // Decode HTML entities
        $text = html_entity_decode($text, ENT_QUOTES, 'UTF-8');

        // Clean up whitespace
        $text = preg_replace('/\s+/', ' ', $text);
        $text = trim($text);

        return $text;
    }

    /**
     * Register a custom alarm template
     * Allows plugins to add custom alarm types
     *
     * @param string $alarm_type Unique alarm type identifier
     * @param array $template Template definition with keys: subject, title, severity, body
     *
     * @return bool True if registered successfully
     */
    public static function register_template($alarm_type, $template)
    {
        self::init_templates();

        if (!isset($template['subject']) || !isset($template['title']) || 
            !isset($template['severity']) || !isset($template['body_html']) || !isset($template['body_text'])) {
            $logger = new CQtrLogger();
            $logger->Error("Invalid template for alarm type: " . $alarm_type . ". Missing required keys (subject, title, severity, body_html, body_text).");
            return false;
        }

        self::$templates[$alarm_type] = $template;
        return true;
    }

    /**
     * Get all registered alarm types
     *
     * @return array List of all registered alarm type identifiers
     */
    public static function get_all_types()
    {
        self::init_templates();
        return array_keys(self::$templates);
    }

    /**
     * Get template for a specific alarm type (for inspection/testing)
     *
     * @param string $alarm_type Alarm type identifier
     *
     * @return array|null Template array or null if not found
     */
    public static function get_template($alarm_type)
    {
        self::init_templates();
        return isset(self::$templates[$alarm_type]) ? self::$templates[$alarm_type] : null;
    }

    /**
     * Format alarm for email sending (complete, ready-to-send HTML body)
     *
     * Wraps factory-generated body_html with metadata headers and Quttera footer
     *
     * @param int $alarm_id Database alarm ID
     * @param array $alarm Pre-generated alarm array from generate()
     * @param string $created_at Timestamp of alarm creation (Y-m-d H:i:s)
     *
     * @return string Complete HTML email body ready for wp_mail()
     */
    public static function format_email_body($alarm_id, $alarm, $created_at)
    {
        $severity = isset($alarm['severity']) ? strtoupper($alarm['severity']) : 'INFO';
        $body_html = isset($alarm['body_html']) ? $alarm['body_html'] : '';

        // Append Quttera footer to alarm body
        $footer = '<hr style="border:none;border-top:1px solid #e5e7eb;margin:20px 0">' . "\n"
            . '<div style="font-size:12px;color:#6b7280;font-family:Arial,sans-serif;line-height:1.4;">' . "\n"
            . '  © ' . date('Y') . ' Quttera, Inc. All rights reserved.<br>' . "\n"
            . '  WordPress Malware Scanner — ' . "\n"
            . '  <a href="https://quttera.com/wordpress-malware-scanner"' . "\n"
            . '     style="color:#2563eb;text-decoration:none;"' . "\n"
            . '     target="_blank" rel="noopener noreferrer">' . "\n"
            . '     https://quttera.com/wordpress-malware-scanner' . "\n"
            . '  </a>' . "\n"
            . '  <br>' . "\n"
            . '  Support: <a href="mailto:support@quttera.com"' . "\n"
            . '            style="color:#2563eb;text-decoration:none;">' . "\n"
            . '            support@quttera.com' . "\n"
            . '         </a>' . "\n"
            . '</div>' . "\n";

        $body_html .= $footer;

        // Build complete email body with metadata header + factory HTML body + footer
        $email_body = sprintf(
            "<div style='font-family: Arial, sans-serif; font-size: 14px;'>"
            . "<p><strong>Alarm ID:</strong> %d</p>"
            . "<p><strong>Severity:</strong> %s</p>"
            . "<p><strong>Time:</strong> %s</p>"
            . "<hr style='border: 1px solid #ddd; margin: 20px 0;'>"
            . "%s"
            . "</div>",
            (int)$alarm_id,
            $severity,
            $created_at,
            $body_html
        );

        return $email_body;
    }
}
