<?php
namespace EasyChat\View;

class NotificationHealthFragments {

    public function pulse(array $health, array $chip, string $action_message = '', string $action_state = ''): string {
        $state = (string)($health['state'] ?? 'gateway_unavailable');
        $mode = (string)($health['mode'] ?? '');
        $limit = is_array($health['limit'] ?? null) ? $health['limit'] : [];
        $usage = is_array($health['usage'] ?? null) ? $health['usage'] : [];
        $channels = is_array($health['channels'] ?? null) ? $health['channels'] : [];
        $operator = is_array($channels['operator'] ?? null) ? $channels['operator'] : [];
        $customer = is_array($channels['customer'] ?? null) ? $channels['customer'] : [];
        $operator_webpush = is_array($operator['webpush'] ?? null) ? $operator['webpush'] : [];
        $customer_webpush = is_array($customer['webpush'] ?? null) ? $customer['webpush'] : [];
        $local_android = is_array($health['local_android'] ?? null) ? $health['local_android'] : [];
        $purchase_url = (string)($health['purchase_url'] ?? 'https://easychat24.ru/pricing/');
        $is_licensed = $mode === 'licensed' || $state === 'licensed';
        $android_total = (int)($local_android['total'] ?? 0);
        $copy = $this->stateCopy($state);
        $action_state = in_array($action_state, ['success', 'error'], true) ? $action_state : '';

        $html = '<div id="notification-health-pulse"'
            . ' class="notification-health-pulse ' . self::e(HtmxFragmentRenderer::motionClass('notification-health-pulse')) . '"'
            . ' data-notification-health-state="' . self::e($state) . '">';

        $html .= '<div class="notification-health-pulse-toolbar" role="toolbar" aria-label="Действия центра уведомлений">'
            . '<div class="notification-health-pulse-toolbar-copy">'
            . '<span class="notification-health-pulse-dot" aria-hidden="true"></span>'
            . '<span>Пульс системы обновляется без перезагрузки страницы</span>'
            . '</div>'
            . '<button type="button" class="btn btn-light notification-health-refresh"'
            . ' hx-get="index.php?route=notification_health/pulse"'
            . ' hx-target="#notification-health-pulse"'
            . ' hx-swap="' . self::e(HtmxFragmentRenderer::notificationHealthPulseSwap()) . '"'
            . ' hx-sync="#notification-health-pulse:replace"'
            . ' hx-indicator="#notification-health-pulse-indicator">'
            . '<i class="fa fa-refresh me-1" aria-hidden="true"></i>Обновить'
            . '</button>'
            . '<span id="notification-health-pulse-indicator" class="htmx-indicator notification-health-refresh-indicator" aria-hidden="true">'
            . '<span class="spinner-border spinner-border-sm"></span>'
            . '</span>'
            . '</div>';

        $html .= '<div class="notification-health-hero notification-health-state-' . self::e($state) . ($is_licensed ? ' notification-health-hero-licensed' : '') . '">'
            . '<div>'
            . '<div class="notification-health-kicker"><i class="fa fa-bell-o me-2"></i> Центр уведомлений EasyChat</div>'
            . '<h2>' . self::e($copy[0]) . '</h2>'
            . '<p>' . self::e($copy[1]) . '</p>';
        if ($mode !== 'licensed' && $state !== 'gateway_unavailable') {
            $html .= '<div class="notification-health-actions">'
                . '<a class="btn btn-primary" href="' . self::e($purchase_url) . '" target="_blank" rel="noopener noreferrer">'
                . '<i class="fa fa-unlock-alt me-2"></i>Снять лимит'
                . '</a>'
                . '</div>';
        } elseif ($is_licensed) {
            $html .= '<div class="notification-health-actions">'
                . '<button class="btn btn-primary" type="button" data-notification-health-open-cabinet>'
                . '<i class="fa fa-user-circle-o me-2" aria-hidden="true"></i>Открыть личный кабинет'
                . '</button><button class="btn btn-outline-primary" type="button" data-notification-health-open-cabinet data-cabinet-action="recovercabinet" data-cabinet-recovery="1">'
                . '<i class="fa fa-life-ring me-2" aria-hidden="true"></i>Восстановить доступ</button>'
                . '</div>';
        }
        $html .= '</div>';
        if (!$is_licensed) {
            $html .= '<div class="notification-health-meter" aria-label="Остаток push">'
                . '<span>' . self::e($chip['label'] ?? '—') . '</span>'
                . '<small>push осталось</small>'
                . '</div>';
        }
        $html .= '</div>';

        $html .= '<div class="row g-4 mt-1">';
        if (!$is_licensed) {
            $used_percent = max(0, min(100, 100 - (float)($limit['remaining_percent'] ?? 0)));
            $html .= '<div class="col-12 col-xl-4">'
                . '<section class="notification-health-panel">'
                . '<div class="notification-health-panel-title"><i class="fa fa-tachometer text-primary"></i> Остаток бесплатных push</div>'
                . '<div class="notification-health-big-number">' . self::int($limit['used'] ?? 0) . ' / ' . self::int($limit['limit'] ?? 300) . '</div>'
                . '<div class="progress notification-health-progress" role="progressbar" aria-label="Использовано push">'
                . '<div class="progress-bar" style="width: ' . self::e($used_percent) . '%;"></div>'
                . '</div>'
                . '<div class="notification-health-muted mt-3">'
                . 'Осталось: <b>' . self::int($limit['remaining'] ?? 0) . '</b>';
            if (!empty($usage['forecast_days'])) {
                $html .= '<br>Прогноз: примерно ' . self::e($usage['forecast_days']) . ' дн.';
                if (!empty($usage['forecast_date'])) {
                    $html .= ' до ' . self::e($usage['forecast_date']);
                }
            } else {
                $html .= '<br>Прогноз появится после накопления свежих доставок.';
            }
            $html .= '</div></section></div>';
        }

        $html .= '<div class="col-12 ' . ($is_licensed ? '' : 'col-xl-8') . '">'
            . '<section class="notification-health-panel">'
            . '<div class="notification-health-panel-title"><i class="fa fa-wifi text-success"></i> Каналы доставки</div>'
            . '<div class="notification-health-channel-grid">'
            . $this->androidChannel($android_total)
            . $this->webChannel('Операторы Web', 'Браузеры операторов', (int)($operator_webpush['active'] ?? 0), false)
            . $this->webChannel('Посетители Web', 'Браузеры посетителей', (int)($customer_webpush['active'] ?? 0), true)
            . '</div>'
            . '<div class="notification-health-inline-status mt-3" data-notification-health-action-status data-state="' . self::e($action_state) . '" aria-live="polite">' . self::e($action_message) . '</div>'
            . '</section>'
            . '</div>'
            . '</div>';

        $html .= '<div class="row g-4 mt-1">'
            . '<div class="col-12 col-xl-7">'
            . '<section class="notification-health-panel">'
            . '<div class="notification-health-panel-title"><i class="fa fa-clock-o text-warning"></i> Последняя активность уведомлений</div>'
            . '<dl class="notification-health-events notification-health-events-readable">'
            . $this->eventRow('Новый push-адресат', self::datetime($channels['last_registered_at'] ?? ''), 'Последняя регистрация Android, WebPush оператора или WebPush посетителя.')
            . $this->eventRow('Оператор получил push', self::datetime($usage['last_push_at'] ?? ''), 'Последняя доставка оператору через Android или браузер за период статистики.')
            . $this->eventRow('Любой канал доставил push', self::datetime($channels['last_success_at'] ?? ''), 'Общая последняя успешная доставка, включая посетительские WebPush.');
        if (!empty($channels['last_error_code'])) {
            $html .= '<div>'
                . '<dt>Последняя проблема доставки</dt>'
                . '<dd title="' . self::e($channels['last_error_code'] ?? '') . '">'
                . self::e(self::gatewayErrorLabel($channels['last_error_code'] ?? ''))
                . '<small>' . (!empty($channels['last_error_at']) ? self::e($channels['last_error_at']) : 'Показываем только если gateway недавно вернул ошибку.') . '</small>'
                . '</dd>'
                . '</div>';
        }
        $html .= '</dl></section></div>'
            . '<div class="col-12 col-xl-5">'
            . '<section class="notification-health-panel notification-health-value-panel">'
            . '<div class="notification-health-panel-title"><i class="fa fa-diamond text-primary"></i> Почему это важно</div>'
            . '<p>Когда первый посетитель пишет в чат, оператор должен узнать об этом сразу, даже если вкладка свернута. Android и WebPush сокращают время реакции и помогают не терять горячие обращения.</p>'
            . '<p class="mb-0">Разовая покупка снимает ограничение текущего бесплатного лимита. Переписка остается на сервере клиента и не передается в центральный gateway.</p>'
            . '</section>'
            . '</div>'
            . '</div>';

        return $html . '</div>';
    }

    private function androidChannel(int $android_total): string {
        return '<div class="notification-health-channel notification-health-channel-primary">'
            . '<div class="notification-health-channel-top">'
            . '<span class="notification-health-channel-icon" aria-hidden="true">'
            . '<svg viewBox="0 0 24 24" focusable="false"><path d="M8 2h8a2 2 0 0 1 2 2v16a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2Zm0 4v12h8V6H8Zm3 13.5a1 1 0 1 0 2 0 1 1 0 0 0-2 0Z"/></svg>'
            . '</span>'
            . '<span class="notification-health-channel-status">Приложение оператора</span>'
            . '</div>'
            . '<strong>Android-приложение</strong>'
            . '<span class="notification-health-channel-metric"><b data-notification-health-android-count>' . $android_total . '</b> подключено</span>'
            . '<button type="button" class="notification-health-channel-action notification-health-logout-android" data-notification-health-logout-android'
            . ' hx-post="index.php?route=notification_health/logoutAndroidPulse"'
            . ' hx-target="#notification-health-pulse"'
            . ' hx-swap="' . self::e(HtmxFragmentRenderer::notificationHealthPulseSwap()) . '"'
            . ' hx-sync="#notification-health-pulse:replace"'
            . ' hx-include="#notification-health-csrf"'
            . ' hx-indicator="#notification-health-pulse-indicator"'
            . ($android_total > 0 ? '' : ' disabled') . '>'
            . '<i class="fa fa-sign-out me-1"></i>Выйти со всех устройств'
            . '</button>'
            . '</div>';
    }

    private function webChannel(string $title, string $status, int $active, bool $visitors): string {
        $icon = $visitors
            ? '<path d="M9 11a4 4 0 1 1 0-8 4 4 0 0 1 0 8Zm8-1a3 3 0 1 1 0-6 3 3 0 0 1 0 6ZM2 20a7 7 0 0 1 14 0 1 1 0 0 1-1 1H3a1 1 0 0 1-1-1Zm14.7-6.9A5.5 5.5 0 0 1 22 18.6a1 1 0 0 1-1 1h-3.1a9 9 0 0 0-1.2-6.5Z"/>'
            : '<path d="M4 4h16a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2h-6v2h3a1 1 0 1 1 0 2H7a1 1 0 1 1 0-2h3v-2H4a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2Zm0 2v9h16V6H4Z"/>';
        return '<div class="notification-health-channel">'
            . '<div class="notification-health-channel-top">'
            . '<span class="notification-health-channel-icon" aria-hidden="true"><svg viewBox="0 0 24 24" focusable="false">' . $icon . '</svg></span>'
            . '<span class="notification-health-channel-status">' . self::e($status) . '</span>'
            . '</div>'
            . '<strong>' . self::e($title) . '</strong>'
            . '<span class="notification-health-channel-metric"><b>' . $active . '</b> активных</span>'
            . '</div>';
    }

    private function eventRow(string $title, string $value, string $hint): string {
        return '<div><dt>' . self::e($title) . '</dt><dd>' . self::e($value) . '<small>' . self::e($hint) . '</small></dd></div>';
    }

    private function stateCopy(string $state): array {
        $copy = [
            'licensed' => ['Уведомления подключены', 'Android и WebPush помогают операторам быстро увидеть новое обращение, даже если вкладка админки свернута.'],
            'normal' => ['Уведомления работают', 'Android и браузерные уведомления готовы помогать оператору быстрее отвечать на новые обращения.'],
            'attention' => ['Следим за остатком', 'Лимит еще есть, но расход уже стоит держать на виду.'],
            'warning' => ['Лимит скоро закончится', 'Если не снять лимит заранее, внешние push операторов могут остановиться в самый неудобный момент.'],
            'critical' => ['Осталось очень мало push', 'Команда уже близко к блокировке Android/WebPush-сигналов для новых сообщений.'],
            'blocked' => ['Push-лимит исчерпан', 'Новые сообщения сохраняются в EasyChat, но операторские Android/WebPush-сигналы остановлены до снятия лимита.'],
            'gateway_unavailable' => ['Данные временно недоступны', 'Не удалось получить свежую диагностику от central gateway. Уже подключенные локальные функции EasyChat продолжают работать.'],
        ];
        return $copy[$state] ?? $copy['gateway_unavailable'];
    }

    private static function gatewayErrorLabel($value): string {
        $code = strtoupper(trim((string)$value));
        if ($code === '') return '—';
        $labels = [
            'NOT_FOUND' => 'Адресат не найден',
            'UNREGISTERED' => 'Подписка устарела',
            'INVALID_ARGUMENT' => 'Некорректный push-токен',
            'QUOTA_EXCEEDED' => 'Превышена квота gateway',
            'SENDER_ID_MISMATCH' => 'Неверный Firebase sender',
            'THIRD_PARTY_AUTH_ERROR' => 'Ошибка авторизации Firebase',
            'GATEWAY_UNAVAILABLE' => 'Gateway временно недоступен',
        ];
        return $labels[$code] ?? 'Ошибка доставки';
    }

    private static function datetime($value): string {
        $value = trim((string)$value);
        return $value !== '' ? $value : '—';
    }

    private static function int($value): int {
        return (int)$value;
    }

    public static function e($value): string {
        return htmlspecialchars((string)$value, ENT_QUOTES, 'UTF-8');
    }
}
