<?php

namespace VulnTitan\Services;

class WeeklySummaryEmailService
{
    protected const OPTION_LAST_SENT_PERIOD = 'vulntitan_weekly_summary_last_sent_period';
    protected const OPTION_LAST_SENT_AT = 'vulntitan_weekly_summary_last_sent_at';
    protected const SEND_LOCK_TRANSIENT = 'vulntitan_weekly_summary_send_lock';
    protected const DEFAULT_SEND_DAY = 1;
    protected const DEFAULT_SEND_HOUR = 8;
    protected const DEFAULT_SEND_MINUTE = 0;

    public static function sendScheduledDigest(): void
    {
        self::sendWeeklySummaryEmail(false);
    }

    public static function sendWeeklySummaryEmail(bool $force = false): bool
    {
        if (!FirewallService::isWeeklySummaryEmailEnabled() && !$force) {
            return false;
        }

        $digest = FirewallService::getWeeklyDigestData(7);
        $periodKey = (string) ($digest['period']['key'] ?? '');

        if (!$force && $periodKey !== '' && get_option(self::OPTION_LAST_SENT_PERIOD, '') === $periodKey) {
            return false;
        }

        if (!$force && !self::acquireSendLock($periodKey)) {
            return false;
        }

        try {
            $recipient = apply_filters(
                'vulntitan_weekly_summary_email_recipient',
                FirewallService::getWeeklySummaryEmailRecipient(),
                $digest
            );

            $recipient = is_string($recipient) ? sanitize_email($recipient) : '';
            if ($recipient === '' || !is_email($recipient)) {
                return false;
            }

            $shouldSend = (bool) apply_filters(
                'vulntitan_weekly_summary_should_send',
                true,
                $digest,
                $recipient,
                $force
            );

            if (!$shouldSend) {
                return false;
            }

            $subject = (string) apply_filters(
                'vulntitan_weekly_summary_email_subject',
                self::buildSubject($digest),
                $digest
            );

            $message = (string) apply_filters(
                'vulntitan_weekly_summary_email_message',
                self::renderMessage($digest),
                $digest
            );

            $headers = apply_filters(
                'vulntitan_weekly_summary_email_headers',
                ['Content-Type: text/html; charset=UTF-8'],
                $digest
            );

            if (!is_array($headers)) {
                $headers = [$headers];
            }

            $sent = wp_mail($recipient, $subject, $message, $headers);

            if ($sent && $periodKey !== '') {
                update_option(self::OPTION_LAST_SENT_PERIOD, $periodKey, false);
                update_option(self::OPTION_LAST_SENT_AT, gmdate('Y-m-d H:i:s'), false);
            }

            return (bool) $sent;
        } finally {
            if (!$force) {
                self::releaseSendLock();
            }
        }
    }

    public static function getNextScheduleTimestamp(): int
    {
        $timezone = self::getWpTimezone();
        $targetDay = max(1, min(7, (int) apply_filters('vulntitan_weekly_summary_schedule_day', self::DEFAULT_SEND_DAY)));
        $targetHour = max(0, min(23, (int) apply_filters('vulntitan_weekly_summary_schedule_hour', self::DEFAULT_SEND_HOUR)));
        $targetMinute = max(0, min(59, (int) apply_filters('vulntitan_weekly_summary_schedule_minute', self::DEFAULT_SEND_MINUTE)));
        $now = new \DateTimeImmutable('now', $timezone);
        $candidate = $now->setTime($targetHour, $targetMinute, 0);
        $currentWeekday = (int) $now->format('N');

        if ($currentWeekday !== $targetDay || $now >= $candidate) {
            $daysUntil = ($targetDay - $currentWeekday + 7) % 7;
            if ($daysUntil === 0) {
                $daysUntil = 7;
            }

            $candidate = $candidate->modify('+' . $daysUntil . ' days');
        }

        return $candidate->getTimestamp();
    }

    protected static function acquireSendLock(string $periodKey): bool
    {
        $lockValue = get_transient(self::SEND_LOCK_TRANSIENT);
        if (is_string($lockValue) && $lockValue !== '' && $lockValue === $periodKey) {
            return false;
        }

        set_transient(
            self::SEND_LOCK_TRANSIENT,
            $periodKey !== '' ? $periodKey : 'locked',
            10 * MINUTE_IN_SECONDS
        );

        return true;
    }

    protected static function releaseSendLock(): void
    {
        delete_transient(self::SEND_LOCK_TRANSIENT);
    }

    protected static function buildSubject(array $digest): string
    {
        $host = wp_parse_url(home_url('/'), PHP_URL_HOST);
        $siteLabel = is_string($host) && $host !== '' ? $host : get_bloginfo('name');
        $blocked = self::formatNumber((int) ($digest['totals']['blocked'] ?? 0));

        return sprintf(
            __('[VulnTitan] %1$s weekly security digest: %2$s blocked events', 'vulntitan'),
            wp_specialchars_decode((string) $siteLabel, ENT_QUOTES),
            $blocked
        );
    }

    protected static function renderMessage(array $digest): string
    {
        $siteName = wp_specialchars_decode(get_bloginfo('name'), ENT_QUOTES);
        $siteUrl = home_url('/');
        $logoUrl = defined('VULNTITAN_PLUGIN_URL')
            ? trailingslashit(VULNTITAN_PLUGIN_URL) . 'assets/img/vulntitan-logo-2.png'
            : '';
        $totals = is_array($digest['totals'] ?? null) ? $digest['totals'] : [];
        $daily = is_array($digest['daily'] ?? null) ? $digest['daily'] : [];
        $topPaths = is_array($digest['top_paths'] ?? null) ? $digest['top_paths'] : [];
        $topRules = is_array($digest['top_rules'] ?? null) ? $digest['top_rules'] : [];
        $period = is_array($digest['period'] ?? null) ? $digest['period'] : [];
        $periodLabel = trim((string) ($period['start_local_display'] ?? '') . ' - ' . (string) ($period['end_local_display'] ?? ''));
        $blockedTotal = (int) ($totals['blocked'] ?? 0);
        $formsBlocked = (int) ($totals['forms_blocked'] ?? 0);
        $loginFailed = (int) ($totals['login_failed'] ?? 0);
        $lockouts = (int) ($totals['login_lockout'] ?? 0);
        $sqli = (int) ($totals['sqli'] ?? 0);
        $commandInjection = (int) ($totals['command_injection'] ?? 0);
        $commentSpamBlocked = (int) ($totals['comment_spam_blocked'] ?? 0);
        $commentSpamHeld = (int) ($totals['comment_spam_held'] ?? 0);
        $commentPendingReview = (int) ($totals['comment_pending_review'] ?? 0);
        $commentRateLimited = (int) ($totals['comment_rate_limited'] ?? 0);
        $uniqueAttackers = (int) ($totals['unique_attackers'] ?? 0);
        $commentQueueTotal = $commentSpamHeld + $commentPendingReview;
        $commentSpamStopped = $commentSpamBlocked + $commentRateLimited;
        $posture = self::getPostureSummary($totals);
        $preheader = sprintf(
            __('%1$s weekly security digest for %2$s. %3$s blocked events, %4$s failed logins, %5$s form spam blocks, %6$s queued comments.', 'vulntitan'),
            'VulnTitan',
            $siteName,
            self::formatNumber($blockedTotal),
            self::formatNumber($loginFailed),
            self::formatNumber($formsBlocked),
            self::formatNumber($commentQueueTotal)
        );
        $generatedAt = self::formatLocalTimestamp(time(), 'M j, Y H:i');
        $policySnapshot = self::buildPolicySnapshot();
        $highlights = self::buildHighlights($daily, $totals);

        $metricCards = [
            [
                'label' => __('Blocked Events', 'vulntitan'),
                'value' => $blockedTotal,
                'note' => __('Firewall, login shield, comment shield, and form shield interventions', 'vulntitan'),
                'accent' => '#0f9bd7',
            ],
            [
                'label' => __('Failed Logins', 'vulntitan'),
                'value' => $loginFailed,
                'note' => __('Credentials rejected before access', 'vulntitan'),
                'accent' => '#f59e0b',
            ],
            [
                'label' => __('IP Lockouts', 'vulntitan'),
                'value' => $lockouts,
                'note' => __('Repeated login abuse contained', 'vulntitan'),
                'accent' => '#ef4444',
            ],
            [
                'label' => __('Form Spam Blocks', 'vulntitan'),
                'value' => $formsBlocked,
                'note' => __('Blocked Contact Form 7 and Fluent Forms submissions', 'vulntitan'),
                'accent' => '#22c55e',
            ],
            [
                'label' => __('Comment Spam Blocks', 'vulntitan'),
                'value' => $commentSpamStopped,
                'note' => __('Spam comments denied before publication', 'vulntitan'),
                'accent' => '#8b5cf6',
            ],
            [
                'label' => __('Comment Queue Holds', 'vulntitan'),
                'value' => $commentQueueTotal,
                'note' => __('Comment Shield holds plus WordPress moderation queue entries', 'vulntitan'),
                'accent' => '#f97316',
            ],
            [
                'label' => __('SQLi Blocks', 'vulntitan'),
                'value' => $sqli,
                'note' => __('Malicious query payloads denied', 'vulntitan'),
                'accent' => '#14b8a6',
            ],
            [
                'label' => __('Unique Attack Sources', 'vulntitan'),
                'value' => $uniqueAttackers,
                'note' => __('Distinct blocked IP fingerprints observed', 'vulntitan'),
                'accent' => '#2563eb',
            ],
        ];

        $threatRows = [
            [
                'label' => __('Form Spam Blocks', 'vulntitan'),
                'value' => $formsBlocked,
                'tone' => '#22c55e',
            ],
            [
                'label' => __('Comment Pending Review', 'vulntitan'),
                'value' => $commentPendingReview,
                'tone' => '#f59e0b',
            ],
            [
                'label' => __('Command Injection Blocks', 'vulntitan'),
                'value' => $commandInjection,
                'tone' => '#f97316',
            ],
            [
                'label' => __('Path Traversal Blocks', 'vulntitan'),
                'value' => (int) ($totals['path_traversal'] ?? 0),
                'tone' => '#8b5cf6',
            ],
            [
                'label' => __('Sensitive File Probes', 'vulntitan'),
                'value' => (int) ($totals['sensitive_file_probe'] ?? 0),
                'tone' => '#06b6d4',
            ],
            [
                'label' => __('Blocked Login Attempts', 'vulntitan'),
                'value' => (int) ($totals['login_blocked'] ?? 0),
                'tone' => '#e11d48',
            ],
            [
                'label' => __('Comment Spam Held', 'vulntitan'),
                'value' => $commentSpamHeld,
                'tone' => '#0f9bd7',
            ],
            [
                'label' => __('Comment Rate Limits', 'vulntitan'),
                'value' => $commentRateLimited,
                'tone' => '#7c3aed',
            ],
            [
                'label' => __('Recovered Login Sessions', 'vulntitan'),
                'value' => (int) ($totals['login_recovered'] ?? 0),
                'tone' => '#10b981',
            ],
            [
                'label' => __('Unique Attack Sources', 'vulntitan'),
                'value' => $uniqueAttackers,
                'tone' => '#2563eb',
            ],
        ];

        $html = '<!doctype html><html><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0">' . self::renderEmailStyles() . '</head><body class="vt-body" style="margin:0;padding:0;background-color:#edf2f7;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif;color:#0f172a;">';
        $html .= '<div style="display:none;max-height:0;overflow:hidden;opacity:0;color:transparent;">' . esc_html($preheader) . '</div>';
        $html .= '<table role="presentation" width="100%" cellspacing="0" cellpadding="0" border="0" class="vt-shell" style="background-color:#edf2f7;margin:0;padding:24px 0;width:100%;"><tr><td align="center">';
        $html .= '<table role="presentation" width="100%" cellspacing="0" cellpadding="0" border="0" class="vt-container" style="max-width:720px;width:100%;margin:0 auto;">';

        $html .= '<tr><td class="vt-section-pad" style="padding:0 16px 16px 16px;">';
        $html .= '<table role="presentation" width="100%" cellspacing="0" cellpadding="0" border="0" style="background-color:#0b1726;border-radius:24px;overflow:hidden;">';
        $html .= '<tr><td class="vt-card-pad" style="padding:18px 24px;background-color:#09111d;border-bottom:1px solid #14324f;">';
        $html .= '<table role="presentation" width="100%" cellspacing="0" cellpadding="0" border="0"><tr>';
        $html .= '<td style="vertical-align:middle;">';
        if ($logoUrl !== '') {
            $html .= '<img src="' . esc_url($logoUrl) . '" alt="VulnTitan" width="158" style="display:block;width:158px;max-width:100%;height:auto;border:0;">';
        } else {
            $html .= '<span style="display:inline-block;font-size:20px;font-weight:800;letter-spacing:0.02em;color:#f8fafc;">VulnTitan</span>';
        }
        $html .= '</td>';
        $html .= '<td align="right" class="vt-brand-right" style="vertical-align:middle;padding-left:16px;">';
        $html .= '<span style="display:inline-block;font-size:12px;font-weight:700;letter-spacing:0.14em;text-transform:uppercase;color:#38bdf8;">Weekly Digest</span>';
        $html .= '</td>';
        $html .= '</tr></table>';
        $html .= '</td></tr>';
        $html .= '<tr><td class="vt-card-pad" style="padding:30px 24px 28px 24px;background-color:#0b1726;">';
        $html .= '<table role="presentation" width="100%" cellspacing="0" cellpadding="0" border="0" class="vt-stack-table"><tr>';
        $html .= '<td class="vt-hero-left" style="vertical-align:top;padding-right:16px;">';
        $html .= '<div class="vt-hero-title" style="font-size:28px;line-height:1.2;font-weight:800;color:#f8fafc;margin:0 0 10px 0;">' . esc_html($siteName) . '</div>';
        $html .= '<div style="font-size:15px;line-height:1.7;color:#cbd5e1;margin:0 0 18px 0;">' . esc_html__('Your firewall and login telemetry summary for the previous 7 complete days.', 'vulntitan') . '</div>';
        $html .= '<div class="vt-inline-chip" style="display:inline-block;padding:9px 14px;border-radius:999px;background-color:#11263c;color:#7dd3fc;font-size:12px;font-weight:700;letter-spacing:0.08em;text-transform:uppercase;">' . esc_html($periodLabel) . '</div>';
        $html .= '</td>';
        $html .= '<td align="right" class="vt-hero-right" style="vertical-align:top;width:220px;">';
        $html .= '<table role="presentation" cellspacing="0" cellpadding="0" border="0" class="vt-blocked-card" style="width:220px;background-color:#0f2237;border:1px solid #1d4061;border-radius:20px;">';
        $html .= '<tr><td style="padding:18px 18px 8px 18px;font-size:12px;letter-spacing:0.12em;text-transform:uppercase;color:#93c5fd;font-weight:700;">' . esc_html__('Blocked This Week', 'vulntitan') . '</td></tr>';
        $html .= '<tr><td class="vt-blocked-value" style="padding:0 18px 8px 18px;font-size:38px;line-height:1;font-weight:800;color:#ffffff;">' . esc_html(self::formatNumber($blockedTotal)) . '</td></tr>';
        $html .= '<tr><td style="padding:0 18px 18px 18px;font-size:13px;line-height:1.7;color:#cbd5e1;">' . esc_html($posture['summary']) . '</td></tr>';
        $html .= '</table>';
        $html .= '</td>';
        $html .= '</tr></table>';
        $html .= '</td></tr>';
        $html .= '</table>';
        $html .= '</td></tr>';

        $html .= '<tr><td class="vt-section-pad" style="padding:0 16px 16px 16px;">' . self::renderMetricGrid($metricCards) . '</td></tr>';

        $html .= '<tr><td class="vt-section-pad" style="padding:0 16px 16px 16px;">';
        $html .= '<table role="presentation" width="100%" cellspacing="0" cellpadding="0" border="0" style="background-color:#ffffff;border:1px solid #dbe6f0;border-radius:24px;">';
        $html .= '<tr><td class="vt-card-pad" style="padding:24px 24px 14px 24px;">';
        $html .= '<div style="font-size:20px;line-height:1.3;font-weight:800;color:#0f172a;margin:0 0 8px 0;">' . esc_html__('Threat Breakdown', 'vulntitan') . '</div>';
        $html .= '<div style="font-size:14px;line-height:1.7;color:#475569;">' . esc_html__('A focused view of what the firewall, login shield, comment shield, and form shield handled during the reporting window.', 'vulntitan') . '</div>';
        $html .= '</td></tr>';
        $html .= '<tr><td class="vt-card-pad" style="padding:0 24px 24px 24px;">' . self::renderThreatBreakdown($threatRows) . '</td></tr>';
        $html .= '</table>';
        $html .= '</td></tr>';

        $html .= '<tr><td class="vt-section-pad" style="padding:0 16px 16px 16px;">';
        $html .= '<table role="presentation" width="100%" cellspacing="0" cellpadding="0" border="0" class="vt-stack-table">';
        $html .= '<tr>';
        $html .= '<td class="vt-two-col-left" style="width:58%;padding:0 8px 0 0;vertical-align:top;">' . self::renderDailyHistory($daily) . '</td>';
        $html .= '<td class="vt-two-col-right" style="width:42%;padding:0 0 0 8px;vertical-align:top;">' . self::renderHighlightsPanel($highlights, $topPaths, $topRules) . '</td>';
        $html .= '</tr>';
        $html .= '</table>';
        $html .= '</td></tr>';

        $html .= '<tr><td class="vt-section-pad" style="padding:0 16px 16px 16px;">';
        $html .= '<table role="presentation" width="100%" cellspacing="0" cellpadding="0" border="0" style="background-color:#ffffff;border:1px solid #dbe6f0;border-radius:24px;">';
        $html .= '<tr><td class="vt-card-pad" style="padding:24px 24px 14px 24px;">';
        $html .= '<div style="font-size:20px;line-height:1.3;font-weight:800;color:#0f172a;margin:0 0 8px 0;">' . esc_html__('Protection Profile', 'vulntitan') . '</div>';
        $html .= '<div style="font-size:14px;line-height:1.7;color:#475569;">' . esc_html__('Authentication, WAF, anti-spam, and telemetry controls that shaped the detections shown above.', 'vulntitan') . '</div>';
        $html .= '</td></tr>';
        $html .= '<tr><td class="vt-card-pad" style="padding:0 24px 24px 24px;">' . $policySnapshot . '</td></tr>';
        $html .= '</table>';
        $html .= '</td></tr>';

        $html .= '<tr><td class="vt-section-pad" style="padding:0 16px 0 16px;">';
        $html .= '<table role="presentation" width="100%" cellspacing="0" cellpadding="0" border="0" style="background-color:#0f172a;border-radius:24px;">';
        $html .= '<tr><td class="vt-card-pad" style="padding:22px 24px;">';
        $html .= '<div style="font-size:14px;line-height:1.8;color:#cbd5e1;">';
        $html .= esc_html__('Generated by VulnTitan for your primary site administrator.', 'vulntitan') . ' ';
        $html .= '<a href="' . esc_url($siteUrl) . '" style="color:#7dd3fc;text-decoration:none;">' . esc_html($siteUrl) . '</a>';
        $html .= '<br>' . esc_html(sprintf(__('Report generated %s', 'vulntitan'), $generatedAt));
        $html .= '</div>';
        $html .= '</td></tr>';
        $html .= '</table>';
        $html .= '</td></tr>';

        $html .= '</table>';
        $html .= '</td></tr></table>';
        $html .= '</body></html>';

        return $html;
    }

    protected static function renderMetricCard(string $label, int $value, string $note, string $accent): string
    {
        return '<table role="presentation" width="100%" cellspacing="0" cellpadding="0" border="0" class="vt-metric-card" style="background-color:#ffffff;border:1px solid #dbe6f0;border-radius:20px;">'
            . '<tr><td style="padding:20px 20px 8px 20px;font-size:12px;font-weight:700;letter-spacing:0.12em;text-transform:uppercase;color:' . esc_attr($accent) . ';">' . esc_html($label) . '</td></tr>'
            . '<tr><td class="vt-metric-value" style="padding:0 20px 8px 20px;font-size:34px;line-height:1;font-weight:800;color:#0f172a;">' . esc_html(self::formatNumber($value)) . '</td></tr>'
            . '<tr><td style="padding:0 20px 20px 20px;font-size:14px;line-height:1.7;color:#475569;">' . esc_html($note) . '</td></tr>'
            . '</table>';
    }

    protected static function renderMetricGrid(array $cards): string
    {
        $html = '<table role="presentation" width="100%" cellspacing="0" cellpadding="0" border="0" class="vt-metric-grid">';
        $chunks = array_chunk($cards, 2);

        foreach ($chunks as $rowIndex => $rowCards) {
            $html .= '<tr class="vt-metric-row">';

            foreach ($rowCards as $cardIndex => $card) {
                $isLastColumn = $cardIndex === count($rowCards) - 1;
                $paddingRight = $isLastColumn ? '0' : '8px';
                $paddingLeft = $cardIndex === 0 ? '0' : '8px';
                $paddingBottom = $rowIndex < count($chunks) - 1 ? '16px' : '0';

                $html .= '<td class="vt-metric-cell" style="width:50%;padding:0 ' . $paddingRight . ' ' . $paddingBottom . ' ' . $paddingLeft . ';vertical-align:top;">';
                $html .= self::renderMetricCard(
                    (string) ($card['label'] ?? ''),
                    (int) ($card['value'] ?? 0),
                    (string) ($card['note'] ?? ''),
                    (string) ($card['accent'] ?? '#0f9bd7')
                );
                $html .= '</td>';
            }

            if (count($rowCards) === 1) {
                $paddingBottom = $rowIndex < count($chunks) - 1 ? '16px' : '0';
                $html .= '<td class="vt-metric-cell" style="width:50%;padding:0 0 ' . $paddingBottom . ' 8px;vertical-align:top;"></td>';
            }

            $html .= '</tr>';
        }

        $html .= '</table>';

        return $html;
    }

    protected static function renderThreatBreakdown(array $rows): string
    {
        $html = '<table role="presentation" width="100%" cellspacing="0" cellpadding="0" border="0">';

        foreach ($rows as $index => $row) {
            $border = $index < count($rows) - 1 ? 'border-bottom:1px solid #e2e8f0;' : '';
            $html .= '<tr>';
            $html .= '<td style="padding:14px 0;' . $border . 'font-size:14px;line-height:1.6;color:#334155;">';
            $html .= '<span style="display:inline-block;width:10px;height:10px;border-radius:999px;background-color:' . esc_attr((string) $row['tone']) . ';margin-right:10px;"></span>';
            $html .= esc_html((string) $row['label']);
            $html .= '</td>';
            $html .= '<td align="right" style="padding:14px 0;' . $border . 'font-size:16px;line-height:1.4;font-weight:800;color:#0f172a;">' . esc_html(self::formatNumber((int) $row['value'])) . '</td>';
            $html .= '</tr>';
        }

        $html .= '</table>';

        return $html;
    }

    protected static function renderDailyHistory(array $daily): string
    {
        $maxBlocked = 0;
        foreach ($daily as $day) {
            $counts = is_array($day['counts'] ?? null) ? $day['counts'] : [];
            $maxBlocked = max($maxBlocked, (int) ($counts['blocked'] ?? 0));
        }

        $html = '<table role="presentation" width="100%" cellspacing="0" cellpadding="0" border="0" style="background-color:#ffffff;border:1px solid #dbe6f0;border-radius:24px;">';
        $html .= '<tr><td class="vt-card-pad" style="padding:24px 24px 14px 24px;">';
        $html .= '<div style="font-size:20px;line-height:1.3;font-weight:800;color:#0f172a;margin:0 0 8px 0;">' . esc_html__('7-Day Activity Timeline', 'vulntitan') . '</div>';
        $html .= '<div style="font-size:14px;line-height:1.7;color:#475569;">' . esc_html__('Blocked traffic, login pressure, form abuse, and comment moderation signals day by day.', 'vulntitan') . '</div>';
        $html .= '</td></tr>';
        $html .= '<tr><td class="vt-card-pad" style="padding:0 24px 24px 24px;">';

        foreach ($daily as $index => $day) {
            $counts = is_array($day['counts'] ?? null) ? $day['counts'] : [];
            $blocked = (int) ($counts['blocked'] ?? 0);
            $formsBlocked = (int) ($counts['forms_blocked'] ?? 0);
            $commentStopped = (int) ($counts['comment_spam_blocked'] ?? 0) + (int) ($counts['comment_rate_limited'] ?? 0);
            $commentQueue = (int) ($counts['comment_spam_held'] ?? 0) + (int) ($counts['comment_pending_review'] ?? 0);
            $percent = ($maxBlocked > 0 && $blocked > 0) ? max(12, (int) round(($blocked / $maxBlocked) * 100)) : 0;
            $border = $index < count($daily) - 1 ? 'border-bottom:1px solid #e2e8f0;' : '';

            $html .= '<table role="presentation" width="100%" cellspacing="0" cellpadding="0" border="0" style="' . $border . '">';
            $html .= '<tr>';
            $html .= '<td class="vt-daily-label" style="padding:12px 0;width:110px;font-size:13px;font-weight:700;color:#0f172a;vertical-align:top;">' . esc_html((string) ($day['label'] ?? '')) . '</td>';
            $html .= '<td class="vt-daily-data" style="padding:12px 14px 12px 0;vertical-align:top;">';
            $html .= '<div style="height:8px;border-radius:999px;background-color:#e2e8f0;overflow:hidden;margin:5px 0 10px 0;">';
            $html .= '<span style="display:block;height:8px;width:' . esc_attr((string) $percent) . '%;background-color:#0f9bd7;border-radius:999px;"></span>';
            $html .= '</div>';
            $html .= '<div style="font-size:12px;line-height:1.8;color:#64748b;">';
            $html .= esc_html__('Blocked', 'vulntitan') . ': <strong style="color:#0f172a;">' . esc_html(self::formatNumber($blocked)) . '</strong> &nbsp; ';
            $html .= esc_html__('Forms', 'vulntitan') . ': <strong style="color:#0f172a;">' . esc_html(self::formatNumber($formsBlocked)) . '</strong> &nbsp; ';
            $html .= esc_html__('Comment Stops', 'vulntitan') . ': <strong style="color:#0f172a;">' . esc_html(self::formatNumber($commentStopped)) . '</strong> &nbsp; ';
            $html .= esc_html__('Queue', 'vulntitan') . ': <strong style="color:#0f172a;">' . esc_html(self::formatNumber($commentQueue)) . '</strong> &nbsp; ';
            $html .= esc_html__('Failed Logins', 'vulntitan') . ': <strong style="color:#0f172a;">' . esc_html(self::formatNumber((int) ($counts['login_failed'] ?? 0))) . '</strong> &nbsp; ';
            $html .= esc_html__('SQLi', 'vulntitan') . ': <strong style="color:#0f172a;">' . esc_html(self::formatNumber((int) ($counts['sqli'] ?? 0))) . '</strong> &nbsp; ';
            $html .= esc_html__('Cmd', 'vulntitan') . ': <strong style="color:#0f172a;">' . esc_html(self::formatNumber((int) ($counts['command_injection'] ?? 0))) . '</strong> &nbsp; ';
            $html .= esc_html__('Events', 'vulntitan') . ': <strong style="color:#0f172a;">' . esc_html(self::formatNumber((int) ($counts['total_events'] ?? 0))) . '</strong>';
            $html .= '</div>';
            $html .= '</td>';
            $html .= '</tr>';
            $html .= '</table>';
        }

        $html .= '</td></tr></table>';

        return $html;
    }

    protected static function renderHighlightsPanel(array $highlights, array $topPaths, array $topRules): string
    {
        $html = '<table role="presentation" width="100%" cellspacing="0" cellpadding="0" border="0" style="background-color:#ffffff;border:1px solid #dbe6f0;border-radius:24px;margin-bottom:16px;">';
        $html .= '<tr><td class="vt-card-pad" style="padding:24px 24px 14px 24px;">';
        $html .= '<div style="font-size:20px;line-height:1.3;font-weight:800;color:#0f172a;margin:0 0 8px 0;">' . esc_html__('Highlights', 'vulntitan') . '</div>';
        $html .= '<div style="font-size:14px;line-height:1.7;color:#475569;">' . esc_html__('The most important takeaways from this reporting period.', 'vulntitan') . '</div>';
        $html .= '</td></tr>';
        $html .= '<tr><td class="vt-card-pad" style="padding:0 24px 24px 24px;">';

        foreach ($highlights as $index => $highlight) {
            $border = $index < count($highlights) - 1 ? 'border-bottom:1px solid #e2e8f0;' : '';
            $html .= '<div style="padding:12px 0;' . $border . '">';
            $html .= '<div style="font-size:12px;font-weight:700;letter-spacing:0.12em;text-transform:uppercase;color:#0f9bd7;margin-bottom:6px;">' . esc_html((string) ($highlight['title'] ?? '')) . '</div>';
            $html .= '<div style="font-size:14px;line-height:1.7;color:#334155;">' . esc_html((string) ($highlight['body'] ?? '')) . '</div>';
            $html .= '</div>';
        }

        $html .= '</td></tr></table>';

        $html .= self::renderTopListPanel(
            __('Top Targeted Paths', 'vulntitan'),
            $topPaths,
            static function (array $row): array {
                return [
                    'label' => (string) ($row['path'] ?? '/'),
                    'value' => self::formatNumber((int) ($row['hits'] ?? 0)),
                ];
            },
            __('No blocked paths were recorded in this period.', 'vulntitan')
        );

        $html .= '<div style="height:16px;line-height:16px;">&nbsp;</div>';

        $html .= self::renderTopListPanel(
            __('Most Triggered Rules', 'vulntitan'),
            $topRules,
            static function (array $row): array {
                $label = (string) ($row['matched_pattern'] ?? '');
                if ($label === '') {
                    $label = (string) ($row['rule_id'] ?? '');
                }
                if ($label === '') {
                    $label = (string) ($row['rule_group'] ?? __('Firewall Rule', 'vulntitan'));
                }

                return [
                    'label' => $label,
                    'value' => self::formatNumber((int) ($row['hits'] ?? 0)),
                    'meta' => self::humanizeRuleContext(
                        (string) ($row['rule_group'] ?? ''),
                        (string) ($row['rule_id'] ?? '')
                    ),
                ];
            },
            __('No firewall, login, or form-shield rules were triggered in this period.', 'vulntitan')
        );

        return $html;
    }

    protected static function renderTopListPanel(string $title, array $rows, callable $formatter, string $emptyText): string
    {
        $html = '<table role="presentation" width="100%" cellspacing="0" cellpadding="0" border="0" style="background-color:#ffffff;border:1px solid #dbe6f0;border-radius:24px;">';
        $html .= '<tr><td class="vt-card-pad" style="padding:24px 24px 14px 24px;">';
        $html .= '<div style="font-size:18px;line-height:1.3;font-weight:800;color:#0f172a;margin:0 0 8px 0;">' . esc_html($title) . '</div>';
        $html .= '</td></tr>';
        $html .= '<tr><td class="vt-card-pad" style="padding:0 24px 24px 24px;">';

        if (!$rows) {
            $html .= '<div style="font-size:14px;line-height:1.7;color:#64748b;">' . esc_html($emptyText) . '</div>';
            $html .= '</td></tr></table>';

            return $html;
        }

        foreach ($rows as $index => $row) {
            $item = $formatter($row);
            $border = $index < count($rows) - 1 ? 'border-bottom:1px solid #e2e8f0;' : '';
            $html .= '<table role="presentation" width="100%" cellspacing="0" cellpadding="0" border="0" style="' . $border . '">';
            $html .= '<tr>';
            $html .= '<td style="padding:12px 0;vertical-align:top;">';
            $html .= '<div style="font-size:14px;line-height:1.6;font-weight:700;color:#0f172a;">' . esc_html((string) ($item['label'] ?? '')) . '</div>';
            if (!empty($item['meta'])) {
                $html .= '<div style="font-size:12px;line-height:1.7;color:#64748b;">' . esc_html((string) $item['meta']) . '</div>';
            }
            $html .= '</td>';
            $html .= '<td align="right" style="padding:12px 0;vertical-align:top;font-size:16px;line-height:1.4;font-weight:800;color:#0f172a;">' . esc_html((string) ($item['value'] ?? '0')) . '</td>';
            $html .= '</tr>';
            $html .= '</table>';
        }

        $html .= '</td></tr></table>';

        return $html;
    }

    protected static function buildPolicySnapshot(): string
    {
        $settings = FirewallService::getSettings();
        $loginUrl = FirewallService::getCustomLoginUrl();
        $rows = [
            [
                'label' => __('Firewall Runtime', 'vulntitan'),
                'value' => !empty($settings['enabled']) ? __('Enabled', 'vulntitan') : __('Disabled', 'vulntitan'),
            ],
            [
                'label' => __('Login Shield', 'vulntitan'),
                'value' => !empty($settings['login_protection_enabled']) ? __('Enabled', 'vulntitan') : __('Disabled', 'vulntitan'),
            ],
            [
                'label' => __('Custom Login Route', 'vulntitan'),
                'value' => $loginUrl !== '' ? $loginUrl : __('Default WordPress login path', 'vulntitan'),
            ],
            [
                'label' => __('Two-Factor Authentication', 'vulntitan'),
                'value' => self::buildTwoFactorSummary($settings),
            ],
            [
                'label' => __('CAPTCHA Coverage', 'vulntitan'),
                'value' => self::buildCaptchaSummary($settings),
            ],
            [
                'label' => __('XML-RPC Policy', 'vulntitan'),
                'value' => self::buildXmlrpcSummary($settings),
            ],
            [
                'label' => __('Weak Password Blocking', 'vulntitan'),
                'value' => !empty($settings['weak_password_blocking_enabled']) ? __('Enabled', 'vulntitan') : __('Disabled', 'vulntitan'),
            ],
            [
                'label' => __('Max Failed Attempts', 'vulntitan'),
                'value' => self::formatNumber((int) ($settings['max_attempts'] ?? 0)),
            ],
            [
                'label' => __('Lockout Duration', 'vulntitan'),
                'value' => sprintf(
                    __('%s minutes', 'vulntitan'),
                    self::formatNumber((int) ($settings['lockout_minutes'] ?? 0))
                ),
            ],
            [
                'label' => __('SQLi Rule Set', 'vulntitan'),
                'value' => !empty($settings['waf_sqli_enabled']) ? __('Enabled', 'vulntitan') : __('Disabled', 'vulntitan'),
            ],
            [
                'label' => __('Command Injection Rule Set', 'vulntitan'),
                'value' => !empty($settings['waf_command_injection_enabled']) ? __('Enabled', 'vulntitan') : __('Disabled', 'vulntitan'),
            ],
            [
                'label' => __('Learning Mode', 'vulntitan'),
                'value' => self::buildLearningModeSummary($settings),
            ],
            [
                'label' => __('Proxy Trust Handling', 'vulntitan'),
                'value' => self::buildProxyTrustSummary($settings),
            ],
            [
                'label' => __('Comment Shield', 'vulntitan'),
                'value' => !empty($settings['comment_shield_enabled']) ? __('Enabled', 'vulntitan') : __('Disabled', 'vulntitan'),
            ],
            [
                'label' => __('Suspicious Comment Action', 'vulntitan'),
                'value' => (($settings['comment_suspicious_action'] ?? 'hold') === 'block')
                    ? __('Block immediately', 'vulntitan')
                    : __('Hold for moderation', 'vulntitan'),
            ],
            [
                'label' => __('Minimum Submit Time', 'vulntitan'),
                'value' => sprintf(
                    __('%s seconds', 'vulntitan'),
                    self::formatNumber((int) ($settings['submission_min_submit_seconds'] ?? $settings['comment_min_submit_seconds'] ?? 0))
                ),
            ],
            [
                'label' => __('Guest Link Limit', 'vulntitan'),
                'value' => sprintf(
                    __('%s links', 'vulntitan'),
                    self::formatNumber((int) ($settings['submission_max_links'] ?? $settings['comment_max_links'] ?? 0))
                ),
            ],
            [
                'label' => __('Submission Rate Window', 'vulntitan'),
                'value' => sprintf(
                    __('%1$s attempts / %2$s minutes', 'vulntitan'),
                    self::formatNumber((int) ($settings['submission_rate_limit_attempts'] ?? $settings['comment_rate_limit_attempts'] ?? 0)),
                    self::formatNumber((int) ($settings['submission_rate_limit_window_minutes'] ?? $settings['comment_rate_limit_window_minutes'] ?? 0))
                ),
            ],
            [
                'label' => __('Form Shield', 'vulntitan'),
                'value' => !empty($settings['form_shield_enabled']) ? __('Enabled', 'vulntitan') : __('Disabled', 'vulntitan'),
            ],
            [
                'label' => __('Protected Form Providers', 'vulntitan'),
                'value' => self::buildFormProvidersSummary($settings),
            ],
            [
                'label' => __('Log Retention', 'vulntitan'),
                'value' => sprintf(
                    __('%s days', 'vulntitan'),
                    self::formatNumber((int) ($settings['log_retention_days'] ?? 0))
                ),
            ],
        ];

        $html = '<table role="presentation" width="100%" cellspacing="0" cellpadding="0" border="0">';
        foreach ($rows as $index => $row) {
            $border = $index < count($rows) - 1 ? 'border-bottom:1px solid #e2e8f0;' : '';
            $html .= '<tr>';
            $html .= '<td class="vt-policy-label" style="padding:12px 0;' . $border . 'font-size:14px;line-height:1.7;color:#475569;width:42%;">' . esc_html((string) $row['label']) . '</td>';
            $html .= '<td class="vt-policy-value" style="padding:12px 0;' . $border . 'font-size:14px;line-height:1.7;font-weight:700;color:#0f172a;">' . esc_html((string) $row['value']) . '</td>';
            $html .= '</tr>';
        }
        $html .= '</table>';

        return $html;
    }

    protected static function buildHighlights(array $daily, array $totals = []): array
    {
        $peakDay = null;
        $peakBlocked = -1;
        $peakLoginDay = null;
        $peakLogins = -1;
        $activeDays = 0;
        $formsBlocked = (int) ($totals['forms_blocked'] ?? 0);
        $commentSpamHeld = (int) ($totals['comment_spam_held'] ?? 0);
        $commentPendingReview = (int) ($totals['comment_pending_review'] ?? 0);
        $commentStops = (int) ($totals['comment_spam_blocked'] ?? 0) + (int) ($totals['comment_rate_limited'] ?? 0);

        foreach ($daily as $day) {
            $counts = is_array($day['counts'] ?? null) ? $day['counts'] : [];
            $blocked = (int) ($counts['blocked'] ?? 0);
            $failedLogins = (int) ($counts['login_failed'] ?? 0);

            if ($blocked > 0) {
                $activeDays++;
            }

            if ($blocked > $peakBlocked) {
                $peakBlocked = $blocked;
                $peakDay = $day;
            }

            if ($failedLogins > $peakLogins) {
                $peakLogins = $failedLogins;
                $peakLoginDay = $day;
            }
        }

        $highlights = [
            [
                'title' => __('Peak Pressure', 'vulntitan'),
                'body' => $peakDay && $peakBlocked > 0
                    ? sprintf(
                        __('%1$s recorded the highest blocked activity with %2$s blocked events.', 'vulntitan'),
                        (string) ($peakDay['label'] ?? ''),
                        self::formatNumber($peakBlocked)
                    )
                    : __('No blocked activity was recorded during this reporting period.', 'vulntitan'),
            ],
            [
                'title' => __('Login Risk', 'vulntitan'),
                'body' => $peakLoginDay && $peakLogins > 0
                    ? sprintf(
                        __('%1$s saw the heaviest failed-login pressure with %2$s rejected attempts.', 'vulntitan'),
                        (string) ($peakLoginDay['label'] ?? ''),
                        self::formatNumber($peakLogins)
                    )
                    : __('No failed-login spikes were recorded in the last 7 complete days.', 'vulntitan'),
            ],
            [
                'title' => __('Persistence', 'vulntitan'),
                'body' => sprintf(
                    __('Threat activity was visible on %1$s of %2$s days in this report.', 'vulntitan'),
                    self::formatNumber($activeDays),
                    self::formatNumber(count($daily))
                ),
            ],
            [
                'title' => __('Abuse Filters', 'vulntitan'),
                'body' => ($formsBlocked + $commentStops + $commentSpamHeld + $commentPendingReview) > 0
                    ? sprintf(
                        __('Form Shield blocked %1$s submissions, comment filtering stopped %2$s comments, and %3$s comments were held or queued for review.', 'vulntitan'),
                        self::formatNumber($formsBlocked),
                        self::formatNumber($commentStops),
                        self::formatNumber($commentSpamHeld + $commentPendingReview)
                    )
                    : __('No form spam or suspicious comment activity required intervention during this reporting period.', 'vulntitan'),
            ],
        ];

        return $highlights;
    }

    protected static function renderEmailStyles(): string
    {
        return '<style type="text/css">'
            . 'body{margin:0;padding:0;background-color:#edf2f7;}'
            . 'table{border-collapse:separate;}'
            . '@media only screen and (max-width:620px){'
            . '.vt-shell{padding:16px 0 !important;}'
            . '.vt-container{width:100% !important;}'
            . '.vt-section-pad{padding-left:12px !important;padding-right:12px !important;}'
            . '.vt-card-pad{padding-left:18px !important;padding-right:18px !important;}'
            . '.vt-brand-right{display:block !important;width:100% !important;text-align:left !important;padding:12px 0 0 0 !important;}'
            . '.vt-hero-left,.vt-hero-right,.vt-two-col-left,.vt-two-col-right,.vt-metric-cell,.vt-policy-label,.vt-policy-value,.vt-daily-label,.vt-daily-data{display:block !important;width:100% !important;}'
            . '.vt-hero-left{padding-right:0 !important;padding-bottom:16px !important;}'
            . '.vt-hero-right{padding-left:0 !important;text-align:left !important;}'
            . '.vt-two-col-left{padding:0 0 16px 0 !important;}'
            . '.vt-two-col-right{padding:0 !important;}'
            . '.vt-metric-row{display:block !important;}'
            . '.vt-metric-cell{padding:0 0 12px 0 !important;}'
            . '.vt-metric-cell:last-child{padding-bottom:0 !important;}'
            . '.vt-blocked-card{width:100% !important;}'
            . '.vt-hero-title{font-size:24px !important;}'
            . '.vt-blocked-value,.vt-metric-value{font-size:30px !important;}'
            . '.vt-inline-chip{display:block !important;margin:0 0 8px 0 !important;text-align:center !important;}'
            . '.vt-daily-label{padding-bottom:8px !important;}'
            . '.vt-daily-data{padding-right:0 !important;}'
            . '.vt-policy-label{padding-bottom:2px !important;border-bottom:none !important;}'
            . '.vt-policy-value{padding-top:0 !important;padding-bottom:12px !important;}'
            . '}'
            . '</style>';
    }

    protected static function buildTwoFactorSummary(array $settings): string
    {
        if (empty($settings['two_factor_enabled'])) {
            return __('Disabled', 'vulntitan');
        }

        $roles = is_array($settings['two_factor_roles'] ?? null) ? $settings['two_factor_roles'] : [];
        $roleLabel = $roles ? self::implodeHumanList(array_map([__CLASS__, 'humanizeIdentifier'], $roles)) : __('selected roles', 'vulntitan');
        $trustedDays = max(0, (int) ($settings['trusted_device_days'] ?? 0));

        return sprintf(
            __('Enabled for %1$s with %2$s-day trusted devices', 'vulntitan'),
            $roleLabel,
            self::formatNumber($trustedDays)
        );
    }

    protected static function buildCaptchaSummary(array $settings): string
    {
        $provider = (string) ($settings['captcha_provider'] ?? 'none');
        if ($provider === '' || $provider === 'none') {
            return __('Disabled', 'vulntitan');
        }

        $surfaces = [];
        if (!empty($settings['captcha_login_enabled'])) {
            $surfaces[] = __('login', 'vulntitan');
        }
        if (!empty($settings['captcha_register_enabled'])) {
            $surfaces[] = __('registration', 'vulntitan');
        }
        if (!empty($settings['captcha_lostpassword_enabled'])) {
            $surfaces[] = __('password reset', 'vulntitan');
        }
        if (!empty($settings['captcha_comment_enabled'])) {
            $surfaces[] = __('comments', 'vulntitan');
        }

        $providerLabel = self::humanizeCaptchaProvider($provider);
        if (!$surfaces) {
            return sprintf(
                __('%s configured but not assigned to a protected flow', 'vulntitan'),
                $providerLabel
            );
        }

        return sprintf(
            __('%1$s on %2$s', 'vulntitan'),
            $providerLabel,
            self::implodeHumanList($surfaces)
        );
    }

    protected static function buildXmlrpcSummary(array $settings): string
    {
        $policy = (string) ($settings['xmlrpc_policy'] ?? 'allow');

        if ($policy === 'rate_limit') {
            return sprintf(
                __('Rate limited at %1$s attempts / %2$s minutes', 'vulntitan'),
                self::formatNumber((int) ($settings['xmlrpc_rate_limit_attempts'] ?? 0)),
                self::formatNumber((int) ($settings['xmlrpc_rate_limit_window_minutes'] ?? 0))
            );
        }

        if ($policy === 'block') {
            return __('Blocked except allowlist', 'vulntitan');
        }

        return __('Allowed', 'vulntitan');
    }

    protected static function buildLearningModeSummary(array $settings): string
    {
        if (empty($settings['learning_mode_enabled'])) {
            return __('Disabled', 'vulntitan');
        }

        return sprintf(
            __('Enabled at %1$s hits within %2$s days', 'vulntitan'),
            self::formatNumber((int) ($settings['learning_suggestion_threshold'] ?? 0)),
            self::formatNumber((int) ($settings['learning_suggestion_window_days'] ?? 0))
        );
    }

    protected static function buildProxyTrustSummary(array $settings): string
    {
        $parts = [];
        $trustedProxies = is_array($settings['trusted_proxies'] ?? null) ? $settings['trusted_proxies'] : [];

        if (!empty($settings['trust_cloudflare'])) {
            $parts[] = __('Cloudflare headers trusted', 'vulntitan');
        }

        if ($trustedProxies) {
            $parts[] = sprintf(
                __('%s trusted proxy IPs', 'vulntitan'),
                self::formatNumber(count($trustedProxies))
            );
        }

        if (!$parts) {
            return __('Direct REMOTE_ADDR only', 'vulntitan');
        }

        return implode(' • ', $parts);
    }

    protected static function buildFormProvidersSummary(array $settings): string
    {
        if (empty($settings['form_shield_enabled'])) {
            return __('Disabled', 'vulntitan');
        }

        $providers = [];
        if (!empty($settings['form_provider_cf7_enabled'])) {
            $providers[] = __('Contact Form 7', 'vulntitan');
        }
        if (!empty($settings['form_provider_fluentforms_enabled'])) {
            $providers[] = __('Fluent Forms', 'vulntitan');
        }

        if (!$providers) {
            return __('Form Shield enabled with no active provider selected', 'vulntitan');
        }

        return self::implodeHumanList($providers);
    }

    protected static function humanizeCaptchaProvider(string $provider): string
    {
        switch ($provider) {
            case 'turnstile':
                return __('Cloudflare Turnstile', 'vulntitan');
            case 'hcaptcha':
                return __('hCaptcha', 'vulntitan');
            default:
                return ucfirst($provider);
        }
    }

    protected static function humanizeIdentifier(string $value): string
    {
        return ucwords(str_replace(['_', '-'], ' ', trim($value)));
    }

    protected static function implodeHumanList(array $items): string
    {
        $items = array_values(array_filter(array_map(static function ($item): string {
            return is_scalar($item) ? trim((string) $item) : '';
        }, $items)));

        if (!$items) {
            return '';
        }

        if (count($items) === 1) {
            return $items[0];
        }

        if (count($items) === 2) {
            return $items[0] . ' ' . __('and', 'vulntitan') . ' ' . $items[1];
        }

        $last = array_pop($items);

        return implode(', ', $items) . ', ' . __('and', 'vulntitan') . ' ' . $last;
    }

    protected static function getPostureSummary(array $totals): array
    {
        $blocked = (int) ($totals['blocked'] ?? 0);
        $failedLogins = (int) ($totals['login_failed'] ?? 0);
        $criticalWaf = (int) ($totals['sqli'] ?? 0) + (int) ($totals['command_injection'] ?? 0);

        if ($criticalWaf >= 10 || $blocked >= 100 || $failedLogins >= 80) {
            return [
                'label' => __('Elevated', 'vulntitan'),
                'summary' => __('Elevated pressure: sustained hostile traffic required repeated firewall intervention.', 'vulntitan'),
            ];
        }

        if ($criticalWaf >= 1 || $blocked >= 15 || $failedLogins >= 20) {
            return [
                'label' => __('Guarded', 'vulntitan'),
                'summary' => __('Guarded posture: the site absorbed active probing and login abuse without exposure.', 'vulntitan'),
            ];
        }

        return [
            'label' => __('Stable', 'vulntitan'),
            'summary' => __('Stable posture: no meaningful attack pressure was recorded in the previous week.', 'vulntitan'),
        ];
    }

    protected static function humanizeRuleContext(string $ruleGroup, string $ruleId): string
    {
        $parts = [];

        if ($ruleGroup !== '') {
            $parts[] = ucwords(str_replace('_', ' ', $ruleGroup));
        }

        if ($ruleId !== '') {
            $parts[] = str_replace('_', ' ', $ruleId);
        }

        return implode(' / ', $parts);
    }

    protected static function formatNumber(int $value): string
    {
        if (function_exists('number_format_i18n')) {
            return number_format_i18n($value);
        }

        return number_format($value);
    }

    protected static function formatLocalTimestamp(int $timestamp, string $format): string
    {
        if (function_exists('wp_date')) {
            return wp_date($format, $timestamp, self::getWpTimezone());
        }

        return date_i18n($format, $timestamp, false);
    }

    protected static function getWpTimezone(): \DateTimeZone
    {
        if (function_exists('wp_timezone')) {
            return wp_timezone();
        }

        $timezoneString = (string) get_option('timezone_string', 'UTC');
        if ($timezoneString !== '') {
            try {
                return new \DateTimeZone($timezoneString);
            } catch (\Exception $exception) {
                // Fall through to UTC.
            }
        }

        return new \DateTimeZone('UTC');
    }
}
