<?php
/**
 * SwapAds Client — BacklinksShortcode (F236 refactor).
 *
 * `[swapads_backlinks]` shortcode that renders a list of approved
 * (received) backlinks on the operator's site. Operators can drop it
 * into any post or page to show their partners.
 *
 * Attributes:
 *   - count     : int   Number of links to show (1-50, default 5)
 *   - mode      : string Display mode: "list" | "card" | "text" (default "list")
 *   - audience  : string Filter by audience code (default: all)
 *   - category  : string Filter by host substring (default: all)
 *   - random    : bool  Randomize order (default false; ordered by date desc)
 *
 * F236 (2026-07-31): refactored to delegate to the shared
 * BacklinksRenderer so the shortcode + Gutenberg block stay in lockstep.
 * F236 also removed the deprecated `swapads_server_url` option check
 * (F201 removed it from the operator UI; `RestClient::fromOption()` is
 * the canonical server-URL source now).
 *
 * @since 1.4.0
 * @since 1.5.3 F236 — delegate to BacklinksRenderer; drop server_url option
 */

declare(strict_types=1);

namespace SwapAds\Client\Shortcodes;

use SwapAds\Client\Backlinks\BacklinksRenderer;

/**
 * Class BacklinksShortcode.
 *
 * @since 1.4.0
 */
final class BacklinksShortcode
{
    public const SHORTCODE = 'swapads_backlinks';

    /**
     * Register the shortcode.
     */
    public static function register(): void
    {
        if (!shortcode_exists(self::SHORTCODE)) {
            add_shortcode(self::SHORTCODE, [self::class, 'render']);
        }
    }

    /**
     * Shortcode callback.
     *
     * Accepts the same attributes as the Gutenberg block (F236).
     * Returns the rendered HTML from BacklinksRenderer so the two
     * surfaces (shortcode + block) stay byte-identical.
     *
     * @param array<string, string> $atts
     * @param string|null          $content
     *
     * @return string Rendered HTML, empty when nothing to show.
     */
    public static function render($atts, $content = null): string
    {
        $atts = shortcode_atts([
            'count'    => (string) BacklinksRenderer::DEFAULT_COUNT,
            'mode'     => BacklinksRenderer::MODE_LIST,
            'audience' => '',
            'category' => '',
            'random'   => 'false',
        ], $atts, self::SHORTCODE);

        $html = BacklinksRenderer::render([
            'count'    => (int) $atts['count'],
            'mode'     => (string) $atts['mode'],
            'audience' => (string) $atts['audience'],
            'category' => (string) $atts['category'],
            'random'   => filter_var($atts['random'], FILTER_VALIDATE_BOOLEAN),
        ]);

        if ($html === '' && $content !== null) {
            // Shortcode nested content (e.g. `[swapads_backlinks]fallback html[/swapads_backlinks]`)
            // renders only when there's no data — lets the operator show
            // a manual block when their account is empty.
            return do_shortcode($content);
        }
        return $html;
    }
}
