<?php
/**
 * SwapAds Client — BacklinkStatsWidget (F238).
 *
 * WP-admin dashboard widget that shows per-partner backlink statistics.
 * Operator sees: "12 partners viewed your backlink this week, 47 humans
 * clicked, 8 search-engine bots crawled".
 *
 * Data source: server endpoint /v1/backlinks/statistics/summary (HMAC-signed).
 * Cached 5-min transient to avoid server spam from dashboard auto-refresh.
 *
 * Naming-convention-locked (avoid tracker/ad/beacon trigger words).
 *
 * @since 1.5.3
 */

declare(strict_types=1);

namespace SwapAds\Client\Admin;

use SwapAds\Client\Api\RestClient;
use SwapAds\Client\License\LicenseManager;


if (!defined('ABSPATH')) { /* test mode: skip WordPress bootstrap guard */ }

final class BacklinkStatsWidget
{
    /** Transient key for caching server response. */
    public const CACHE_KEY_PREFIX = 'swapads_stats_summary_';
    public const CACHE_TTL = 300;  // 5 minutes

    /**
     * Register the wp_add_dashboard_widget hook.
     */
    public static function register(): void
    {
        add_action('wp_dashboard_setup', [self::class, 'registerWidget']);
    }

    public static function registerWidget(): void
    {
        // Only show to users who can manage options + operators with licensed sites.
        if (!current_user_can('manage_options')) {
            return;
        }
        if (!LicenseManager::isLicensed()) {
            return;
        }
        wp_add_dashboard_widget(
            'swapads_backlink_statistics',
            __('Backlink statistics', 'swapads'),
            [self::class, 'render'],
            null,
            [],
            'normal',
            'high'  // show near top of dashboard
        );
    }

    /**
     * Render the widget.
     */
    public static function render(): void
    {
        $summary = self::fetchSummary(30);
        if ($summary === null) {
            // Server unreachable or no data yet.
            echo '<div class="swapads-stats-empty">';
            echo \SwapAds\Client\Admin\Renderer::noticeAccessible(
                __('No backlink statistics yet. Your backlinks haven\'t received any views or clicks in the last 30 days.', 'swapads'),
                'info'
            );
            echo '</div>';
            return;
        }

        $total = $summary['summary'] ?? [];
        $partners = $summary['partners'] ?? [];
        $days = (int) ($summary['days'] ?? 30);

        $humanViews = (int) ($total['human_views'] ?? 0);
        $botViews = (int) ($total['bot_views'] ?? 0);
        $humanClicks = (int) ($total['human_clicks'] ?? 0);
        $botClicks = (int) ($total['bot_clicks'] ?? 0);
        $ctr = isset($total['ctr']) ? (float) $total['ctr'] : 0.0;
        $ctrPct = number_format($ctr * 100, 1);

        echo '<div class="swapads-stats-widget">';

        // Top-line totals.
        echo '<div class="swapads-stats-totals">';
        echo '<span class="swapads-stats-totals-views">';
        echo '<strong>' . esc_html(number_format($humanViews)) . '</strong> ';
        echo esc_html__('human views', 'swapads');
        echo '</span>';

        echo '<span class="swapads-stats-totals-clicks">';
        echo '<strong>' . esc_html(number_format($humanClicks)) . '</strong> ';
        echo esc_html__('human clicks', 'swapads');
        echo '</span>';

        echo '<span class="swapads-stats-totals-ctr">';
        echo '<strong>' . esc_html($ctrPct) . '%</strong> ';
        echo esc_html__('CTR', 'swapads');
        echo '</span>';
        echo '</div>';

        // Bot breakdown (collapsed but visible).
        echo '<p class="swapads-stats-bot-line">';
        echo esc_html(
            sprintf(
                /* translators: 1: bot views, 2: bot clicks */
                _n(
                    'Bots: %1$s view, %2$s click (last %3$d days)',
                    'Bots: %1$s views, %2$s clicks (last %3$d days)',
                    max(1, $botViews),
                    'swapads'
                ),
                number_format($botViews),
                number_format($botClicks),
                $days
            )
        );
        echo '</p>';

        // Per-partner table (top 10).
        if (!empty($partners)) {
            echo '<h4>' . esc_html__('Top partners', 'swapads') . '</h4>';
            echo '<table class="widefat swapads-stats-partners">';
            echo '<thead><tr>';
            echo '<th>' . esc_html__('Partner', 'swapads') . '</th>';
            echo '<th>' . esc_html__('Views', 'swapads') . '</th>';
            echo '<th>' . esc_html__('Clicks', 'swapads') . '</th>';
            echo '<th>' . esc_html__('CTR', 'swapads') . '</th>';
            echo '</tr></thead>';
            echo '<tbody>';
            $shown = 0;
            foreach ($partners as $p) {
                if ($shown >= 10) {
                    break;
                }
                $domain = (string) ($p['partner_domain'] ?? '');
                if ($domain === '') {
                    continue;
                }
                echo '<tr>';
                echo '<td>' . esc_html($domain) . '</td>';
                echo '<td>' . esc_html(number_format((int) ($p['total_views'] ?? 0))) . '</td>';
                echo '<td>' . esc_html(number_format((int) ($p['total_clicks'] ?? 0))) . '</td>';
                echo '<td>' . esc_html(number_format(((float) ($p['ctr'] ?? 0)) * 100, 1)) . '%</td>';
                echo '</tr>';
                $shown++;
            }
            echo '</tbody></table>';
            if (count($partners) > 10) {
                echo '<p class="swapads-stats-more">';
                echo esc_html(sprintf(
                    /* translators: %d: number of additional partners */
                    _n(
                        '...and %d more partner.',
                        '...and %d more partners.',
                        count($partners) - 10,
                        'swapads'
                    ),
                    count($partners) - 10
                ));
                echo '</p>';
            }
        }

        // Link to full stats (in case there's a deeper page later).
        echo '<p class="swapads-stats-link">';
        echo '<a href="' . esc_url(admin_url('admin.php?page=swapads-client-hub&tab=setup')) . '">';
        echo esc_html__('Manage backlink setup', 'swapads');
        echo '</a>';
        echo '</p>';

        echo '</div>';

        // Inline CSS for the widget (kept lightweight).
        echo '<style>
            .swapads-stats-totals { display: flex; gap: 1.5em; margin-bottom: 0.75em; }
            .swapads-stats-totals > span { display: flex; flex-direction: column; }
            .swapads-stats-totals strong { font-size: 1.4em; color: #2271b1; }
            .swapads-stats-bot-line { color: #50575e; font-size: 0.85em; margin: 0.5em 0; }
            .swapads-stats-partners { margin-top: 0.75em; }
            .swapads-stats-more { color: #50575e; font-style: italic; font-size: 0.85em; }
            .swapads-stats-link { margin-top: 0.75em; }
        </style>';
    }

    /**
     * Fetch summary from server (with caching).
     *
     * @param int $days 1..365
     * @return array|null Server response (decoded), or null on error.
     */
    private static function fetchSummary(int $days): ?array
    {
        $key = self::CACHE_KEY_PREFIX . $days;
        $cached = get_transient($key);
        if (is_array($cached)) {
            return $cached;
        }

        $client = RestClient::fromOption();
        $response = $client->get('/backlinks/statistics/summary', ['days' => $days]);
        if (!is_array($response)) {
            return null;
        }
        if (($response['success'] ?? false) !== true) {
            return null;
        }
        $payload = [
            'summary'  => $response['summary'] ?? [],
            'partners' => $response['partners'] ?? [],
            'days'     => $response['days'] ?? $days,
        ];
        set_transient($key, $payload, self::CACHE_TTL);
        return $payload;
    }
}
