<?php
/**
 * SwapAds Client — Backlinks Gutenberg Block (F236).
 *
 * Registers `swapads/backlinks` Gutenberg block for drag-and-drop
 * placement in post + page editors. Renders the same output as
 * `[swapads_backlinks]` shortcode via the shared BacklinksRenderer.
 *
 * Block attributes mirror the shortcode attributes:
 *   - count     : int    1-50 (default 5)
 *   - mode      : string list|card|text (default list)
 *   - audience  : string filter by audience code (optional)
 *   - category  : string filter by host substring (optional)
 *   - random    : bool   random order (default false)
 *   - align     : string wide|full|center|right|left|''  (WP align attr)
 *
 * @since 1.5.3
 */

declare(strict_types=1);

namespace SwapAds\Client\Blocks;

use SwapAds\Client\Backlinks\BacklinksRenderer;

/**
 * Class BacklinksBlock.
 *
 * @since 1.5.3
 */
final class BacklinksBlock
{
    public const BLOCK_NAME = 'swapads/backlinks';
    public const SCRIPT_HANDLE = 'swapads-backlinks-block-editor';

    /**
     * Register the block + editor script.
     */
    public static function register(): void
    {
        if (!function_exists('register_block_type')) {
            return;
        }

        // F236: editor script defines the inspector controls + live
        // preview. Front-end posts use the server-side render_callback
        // below — no JS needed on the visitor side.
        if (function_exists('wp_register_script')) {
            wp_register_script(
                self::SCRIPT_HANDLE,
                plugin_dir_url(__FILE__) . '../../assets/js/backlinks-block-editor.js',
                ['wp-blocks', 'wp-element', 'wp-block-editor', 'wp-components', 'wp-i18n'],
                '1.5.7',
                true
            );
        }

        register_block_type(self::BLOCK_NAME, [
            'api_version'     => 2,
            'title'           => __('SwapAds Backlinks', 'swapads'),
            'description'     => __('Display approved backlinks from your SwapAds partners. Configurable count, display mode, audience + category filters.', 'swapads'),
            'category'        => 'swapads',
            'icon'            => 'admin-links',
            'keywords'        => ['backlinks', 'swapads', 'partners', 'barter'],
            'supports'        => [
                'align'  => ['wide', 'full'],
                'html'   => false,
                'reusable' => false,
            ],
            'attributes'      => [
                'count'    => [
                    'type'    => 'number',
                    'default' => BacklinksRenderer::DEFAULT_COUNT,
                ],
                'mode'     => [
                    'type'    => 'string',
                    'default' => BacklinksRenderer::MODE_LIST,
                ],
                'audience' => [
                    'type'    => 'string',
                    'default' => '',
                ],
                'category' => [
                    'type'    => 'string',
                    'default' => '',
                ],
                'random'   => [
                    'type'    => 'boolean',
                    'default' => false,
                ],
                'align'    => [
                    'type'    => 'string',
                    'default' => '',
                ],
            ],
            'editor_script'   => self::SCRIPT_HANDLE,
            'render_callback' => [self::class, 'render'],
        ]);
    }

    /**
     * Server-side render callback for the block.
     *
     * @param array<string, mixed> $attributes
     *
     * @return string Rendered HTML, empty string when nothing to show.
     */
    public static function render(array $attributes): string
    {
        $html = BacklinksRenderer::render([
            'count'    => (int) ($attributes['count'] ?? BacklinksRenderer::DEFAULT_COUNT),
            'mode'     => (string) ($attributes['mode'] ?? BacklinksRenderer::MODE_LIST),
            'audience' => (string) ($attributes['audience'] ?? ''),
            'category' => (string) ($attributes['category'] ?? ''),
            'random'   => (bool) ($attributes['random'] ?? false),
            // F236: block editor previews should NOT cache. Operators see
            // the latest state of their approvals as they tweak controls.
            'cache'    => false,
        ]);
        if ($html === '') {
            // Empty placeholder so the block doesn't disappear in the editor.
            $count = (int) ($attributes['count'] ?? BacklinksRenderer::DEFAULT_COUNT);
            $mode  = (string) ($attributes['mode'] ?? BacklinksRenderer::MODE_LIST);
            $html  = '<div class="swapads-backlinks swapads-backlinks-placeholder swapads-backlinks-' . esc_attr($mode) . '" data-count="' . esc_attr((string) $count) . '"></div>';
        }

        $align = (string) ($attributes['align'] ?? '');
        if ($align !== '') {
            $html = '<div class="wp-block-swapads-backlinks align' . esc_attr($align) . '">' . $html . '</div>';
        }
        return $html;
    }
}
