/**
 * SwapAds Backlinks Block — Editor Sidebar + Live Preview
 *
 * F236 (2026-07-31): inspector controls + live preview for the
 * `swapads/backlinks` Gutenberg block.
 *
 * No build step. Loaded via wp_register_script() in BacklinksBlock::register().
 * Uses wp.element + wp.blockEditor + wp.components (already provided by WP).
 *
 * Inspector controls:
 *   - count    : number, clamped 1-50 server-side, validated client-side
 *   - mode     : select (list|card|text)
 *   - audience : text (filter by audience code)
 *   - category : text (filter by host substring)
 *   - random   : toggle (shuffle vs newest-first)
 *   - align    : WP core alignment (wide|full|center|right|left|'')
 *
 * @since 1.5.3
 */
( function ( wp ) {
    'use strict';

    if ( ! wp || ! wp.element || ! wp.blocks || ! wp.blockEditor || ! wp.components ) {
        // WP < 5.0 or missing dependency — bail silently. The block
        // still renders server-side via BacklinksBlock::render().
        return;
    }

    var el = wp.element.createElement;
    var Fragment = wp.element.Fragment;
    var __ = wp.i18n ? wp.i18n.__ : function ( s ) { return s; };

    var PanelBody = wp.components.PanelBody;
    var SelectControl = wp.components.SelectControl;
    var TextControl = wp.components.TextControl;
    var ToggleControl = wp.components.ToggleControl;
    var RangeControl = wp.components.RangeControl;

    var InspectorControls = wp.blockEditor.InspectorControls;
    var useBlockProps = wp.blockEditor ? wp.blockEditor.useBlockProps : null;

    // F236: display modes — kept in sync with BacklinksRenderer::ALLOWED_MODES.
    var MODE_OPTIONS = [
        { label: 'List (one per row)', value: 'list' },
        { label: 'Card (with host)',   value: 'card' },
        { label: 'Text (inline)',      value: 'text' },
    ];

    // F236: alignment options — same set as BannerBlock for consistency.
    var ALIGN_OPTIONS = [
        { label: 'Default (none)', value: '' },
        { label: 'Wide',          value: 'wide' },
        { label: 'Full',          value: 'full' },
        { label: 'Left',          value: 'left' },
        { label: 'Right',         value: 'right' },
        { label: 'Center',        value: 'center' },
    ];

    // F236: live preview — we can't render the exact server output without
    // an authenticated REST call (which the editor context can't sign), so
    // we show a faithful placeholder that mirrors the modes + attributes.
    // Operators see what they'll get after they hit "Update".
    function PreviewBox( props ) {
        var mode  = props.mode || 'list';
        var count = props.count || 5;
        var random = props.random ? ' (random)' : ' (newest first)';
        var align = props.align || '';
        var alignClass = align !== '' ? ' align' + align : '';

        var items = [];
        for ( var i = 0; i < Math.min( count, 3 ); i++ ) {
            items.push(
                el( 'div', { key: i, className: 'swapads-block-preview__item' },
                    el( 'span', { className: 'swapads-block-preview__anchor' }, 'Partner ' + ( i + 1 ) ),
                    el( 'span', { className: 'swapads-block-preview__host'  }, 'partner.example.com' )
                )
            );
        }
        if ( count > 3 ) {
            items.push(
                el( 'div', { key: 'more', className: 'swapads-block-preview__item swapads-block-preview__more' },
                    '+ ' + ( count - 3 ) + ' more'
                )
            );
        }
        if ( mode === 'text' ) {
            items = items.map( function ( item, idx ) {
                return el( 'span', { key: idx, className: 'swapads-block-preview__inline' }, 'Partner' );
            } );
        }

        return el(
            'div',
            { className: 'swapads-block-preview swapads-block-preview--' + mode + alignClass },
            el( 'div', { className: 'swapads-block-preview__label' },
                __( 'SwapAds Backlinks Preview' ) + ' — ' + mode + ', ' + count + random
            ),
            el( 'div', { className: 'swapads-block-preview__list' }, items )
        );
    }

    var Edit = function ( props ) {
        var attributes = props.attributes || {};
        var setAttributes = props.setAttributes;

        // F236: clamp count to [1, 50] in the editor so it can't be
        // persisted with invalid values.
        var rawCount = typeof attributes.count === 'number' ? attributes.count : 5;
        if ( rawCount < 1 ) { rawCount = 1; }
        if ( rawCount > 50 ) { rawCount = 50; }

        var blockProps = useBlockProps ? useBlockProps( { className: 'swapads-block swapads-block--backlinks' } ) : { className: 'swapads-block swapads-block--backlinks' };

        return el(
            Fragment,
            null,
            el(
                InspectorControls,
                null,
                el(
                    PanelBody,
                    { title: __( 'SwapAds Backlinks' ), initialOpen: true },
                    el( RangeControl, {
                        label: __( 'Number of backlinks' ),
                        value: rawCount,
                        min: 1,
                        max: 50,
                        onChange: function ( value ) {
                            setAttributes( { count: parseInt( value, 10 ) || 1 } );
                        },
                        help: __( 'How many approved backlinks to display (1-50).' )
                    } ),
                    el( SelectControl, {
                        label: __( 'Display mode' ),
                        value: attributes.mode || 'list',
                        options: MODE_OPTIONS,
                        onChange: function ( value ) {
                            setAttributes( { mode: value } );
                        },
                        help: __( 'list: one per row. card: with host. text: inline anchors.' )
                    } ),
                    el( TextControl, {
                        label: __( 'Filter by audience code' ),
                        value: attributes.audience || '',
                        onChange: function ( value ) {
                            setAttributes( { audience: value } );
                        },
                        placeholder: __( 'e.g. cam_sites' ),
                        help: __( 'Optional. Restrict to backlinks in a specific audience.' )
                    } ),
                    el( TextControl, {
                        label: __( 'Filter by category/host' ),
                        value: attributes.category || '',
                        onChange: function ( value ) {
                            setAttributes( { category: value } );
                        },
                        placeholder: __( 'e.g. cam-site.com' ),
                        help: __( 'Optional. Substring match against backlink source URL host.' )
                    } ),
                    el( ToggleControl, {
                        label: __( 'Random order' ),
                        checked: !! attributes.random,
                        onChange: function ( value ) {
                            setAttributes( { random: !! value } );
                        },
                        help: __( 'Off = newest first (default). On = shuffle.' )
                    } ),
                    el( SelectControl, {
                        label: __( 'Alignment' ),
                        value: attributes.align || '',
                        options: ALIGN_OPTIONS,
                        onChange: function ( value ) {
                            setAttributes( { align: value } );
                        }
                    } )
                )
            ),
            el(
                'div',
                blockProps,
                el( PreviewBox, {
                    mode: attributes.mode || 'list',
                    count: rawCount,
                    random: !! attributes.random,
                    align: attributes.align || ''
                } )
            )
        );
    };

    // Register the block (overrides the BacklinksBlock::register PHP version
    // since wp.blocks.registerBlockType is the canonical client API).
    // The PHP side keeps the server render_callback so saved posts still
    // produce correct HTML even if the JS bundle is missing.
    if ( wp.blocks && typeof wp.blocks.registerBlockType === 'function' ) {
        wp.blocks.registerBlockType( 'swapads/backlinks', {
            edit: Edit,
            // 'save' returns null so WP uses server-side render via PHP
            // (api_version: 2 + render_callback in PHP).
            save: function () { return null; }
        } );
    }
}( window.wp ) );
