/**
 * Encypher Block-Level Rights Inspector Panel
 *
 * Adds an "Encypher Rights" panel to the block inspector for supported block
 * types. Each block can override the document-level license with a per-block
 * license template and custom fields.
 *
 * Rights data is stored as a block attribute (encypherRights) which gets
 * serialized into the block comment delimiter. The PHP backend reads these
 * attributes on save and maps them to the API's segment_rights (for text
 * blocks) or per-media rights (for media blocks).
 */
(function () {
    'use strict';

    var el = wp.element.createElement;
    var Fragment = wp.element.Fragment;
    var useState = wp.element.useState;
    var useEffect = wp.element.useEffect;
    var createHigherOrderComponent = wp.compose.createHigherOrderComponent;
    var addFilter = wp.hooks.addFilter;
    var InspectorControls = wp.blockEditor.InspectorControls;
    var BlockControls = wp.blockEditor.BlockControls;
    var PanelBody = wp.components.PanelBody;
    var SelectControl = wp.components.SelectControl;
    var ComboboxControl = wp.components.ComboboxControl;
    var ToolbarGroup = wp.components.ToolbarGroup;
    var ToolbarButton = wp.components.ToolbarButton;
    var Button = wp.components.Button;
    var select = wp.data.select;
    var dispatch = wp.data.dispatch;

    var catalog = window.EncypherLicenseCatalog;
    var brandConfig = window.EncypherProvenanceConfig || {};


    // Block types that support per-block rights.
    var SUPPORTED_BLOCKS = [
        'core/paragraph',
        'core/heading',
        'core/list',
        'core/quote',
        'core/image',
        'core/audio',
        'core/video',
        'core/gallery',
        'core/cover',
        'core/media-text',
    ];

    // ----- 1. Register the encypherRights attribute on supported blocks -----

    function addRightsAttribute(settings, name) {
        if (SUPPORTED_BLOCKS.indexOf(name) === -1) {
            return settings;
        }
        if (!settings.attributes) {
            settings.attributes = {};
        }
        settings.attributes.encypherRights = {
            type: 'object',
            default: undefined,
        };
        return settings;
    }

    addFilter(
        'blocks.registerBlockType',
        'encypher-provenance/block-rights-attribute',
        addRightsAttribute
    );

    // ----- 1b. WS0.2: Register a PERSISTED per-block UUID on every block -----
    //
    // Gutenberg's clientId is ephemeral (regenerated each editor load and on
    // duplicate), so it cannot key per-block provenance/history. encypherBlockId
    // is a persisted attribute that survives reorder, save/reload, and (via the
    // duplicate guard below) is regenerated on block duplication so two blocks
    // never share an id. WS2 (edit history), WS4 (per-block rights + VS256-RS
    // markers), and per-domain analytics all key off this id.

    function generateBlockId() {
        // RFC4122-ish v4; crypto.randomUUID when available, fallback otherwise.
        if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {
            return 'enb_' + crypto.randomUUID();
        }
        return 'enb_' + 'xxxxxxxxxxxx4xxxyxxxxxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
            var r = (Math.random() * 16) | 0;
            var v = c === 'x' ? r : (r & 0x3) | 0x8;
            return v.toString(16);
        });
    }

    function addBlockIdAttribute(settings) {
        if (!settings.attributes) {
            settings.attributes = {};
        }
        if (!settings.attributes.encypherBlockId) {
            settings.attributes.encypherBlockId = {
                type: 'string',
                default: '',
            };
        }
        return settings;
    }

    addFilter(
        'blocks.registerBlockType',
        'encypher-provenance/block-id-attribute',
        addBlockIdAttribute
    );

    // Assign an id the first time a block renders without one, and detect
    // duplicates (same id on two live blocks) so copies get a fresh id.
    var withBlockId = createHigherOrderComponent(function (BlockEdit) {
        return function (props) {
            if (props.attributes && typeof props.attributes.encypherBlockId !== 'undefined') {
                var existing = props.attributes.encypherBlockId;
                if (!existing) {
                    // First render of a new block.
                    props.setAttributes({ encypherBlockId: generateBlockId() });
                } else {
                    // Duplicate guard: if another live block already owns this id,
                    // this is a duplicated/pasted block — reassign.
                    try {
                        var blocks = select('core/block-editor').getBlocks();
                        var owners = 0;
                        (function countOwners(list) {
                            list.forEach(function (b) {
                                if (b.attributes && b.attributes.encypherBlockId === existing) {
                                    owners += 1;
                                }
                                if (b.innerBlocks && b.innerBlocks.length) {
                                    countOwners(b.innerBlocks);
                                }
                            });
                        })(blocks);
                        if (owners > 1) {
                            props.setAttributes({ encypherBlockId: generateBlockId() });
                        }
                    } catch (e) {
                        // select() unavailable in some contexts; id stays as-is.
                    }
                }
            }
            return el(BlockEdit, props);
        };
    }, 'withEncypherBlockId');

    addFilter('editor.BlockEdit', 'encypher-provenance/with-block-id', withBlockId);
    // ----- 2. Add inspector controls to each supported block -----

    var withRightsInspector = createHigherOrderComponent(function (BlockEdit) {
        return function (props) {
            if (SUPPORTED_BLOCKS.indexOf(props.name) === -1) {
                return el(BlockEdit, props);
            }

            var rights = props.attributes.encypherRights || {};
            var templateKey = rights.template || '';
            var isCustom = templateKey === 'custom';
            var panelState = useState(!!templateKey);
            var panelOpen = panelState[0];
            var setPanelOpen = panelState[1];

            // Load the server license catalog once; the setter forces a re-render
            // when it arrives so getEntry()/comboboxOptions() have data.
            var setCatalogState = useState(catalog ? catalog.state() : null)[1];
            useEffect(function () {
                if (catalog) {
                    catalog.load().then(setCatalogState);
                }
            }, []);


            function onTemplateChange(value) {
                value = value || '';
                if (!value) {
                    // Reset to inherit the document default.
                    props.setAttributes({ encypherRights: undefined });
                    return;
                }
                // Store only dashboard template ids. The legacy `custom` value
                // is shown read-only when already saved and must retain its
                // existing serialized fields until the user replaces it.
                if (value === 'custom' && templateKey === 'custom') {
                    return;
                }
                props.setAttributes({ encypherRights: { template: value } });
            }

            var isMediaBlock = ['core/image', 'core/audio', 'core/video', 'core/gallery', 'core/cover', 'core/media-text'].indexOf(props.name) !== -1;
            var blockLabel = isMediaBlock ? 'media asset' : 'text block';

            var panelChildren = [
                el(ComboboxControl, {
                    key: 'template-select',
                    label: 'License',
                    value: templateKey,
                    options: catalog ? catalog.comboboxOptions(true, templateKey) : [{ value: '', label: 'Inherit document default' }].concat(templateKey === 'custom' ? [{ value: 'custom', label: 'Saved custom terms (read-only)', disabled: true }] : (templateKey ? [{ value: templateKey, label: templateKey + ' (saved, read-only)', disabled: true }] : [])),
                    onChange: onTemplateChange,
                    help: templateKey ? null : 'Inherits document-level license when unset.',
                }),
            ];

            // Show a read-only summary for dashboard-owned templates.
            if (templateKey && !isCustom) {
                var tplEntry = catalog ? catalog.getEntry(templateKey) : null;
                var tplFields = tplEntry ? tplEntry.fields : null;
                if (tplFields) {
                    panelChildren.push(
                        el('div', { key: 'tpl-summary', className: 'encypher-rights-summary' },
                            el('p', { className: 'encypher-rights-summary-type' }, tplFields.type),
                            tplFields.url ? el('a', {
                                href: tplFields.url,
                                target: '_blank',
                                rel: 'noopener noreferrer',
                                className: 'encypher-rights-summary-url',
                            }, 'View license') : null,
                            el('p', { className: 'encypher-rights-summary-terms' }, tplFields.usage_terms)
                        )
                    );
                }
            }

            if (isCustom) {
                panelChildren.push(
                    el('p', {
                        key: 'saved-custom',
                        className: 'description encypher-rights-saved-selection',
                    }, 'Previously saved terms remain in effect. Choose a dashboard template to replace them.')
                );
            }

            panelChildren.push(
                el('p', { key: 'dashboard-link', className: 'encypher-rights-dashboard-link' },
                    el('a', {
                        href: 'https://dashboard.encypher.com/rights',
                        target: '_blank',
                        rel: 'noopener noreferrer',
                    }, 'Manage license templates in your Encypher dashboard')
                )
            );

            // Indicator for which block type this applies to.
            if (templateKey) {
                panelChildren.push(
                    el('p', {
                        key: 'block-note',
                        className: 'encypher-rights-block-note',
                    }, 'This license applies to this ' + blockLabel + ' only. Other blocks inherit the document default.')
                );
            }

            // "Apply to all [type]" button.
            if (templateKey) {
                var blockType = props.name;
                var typeLabel = blockType.replace('core/', '');
                var plural = typeLabel;
                if (typeLabel === 'gallery') { plural = 'galleries'; }
                else if (typeLabel === 'media-text') { plural = 'media-text blocks'; }
                else { plural = typeLabel + 's'; }

                panelChildren.push(
                    el(Button, {
                        key: 'apply-similar',
                        variant: 'secondary',
                        isSmall: true,
                        style: { marginTop: '8px', width: '100%' },
                        onClick: function () {
                            var allBlocks = select('core/block-editor').getBlocks();
                            var currentRights = Object.assign({}, rights);
                            allBlocks.forEach(function (block) {
                                if (block.name === blockType && block.clientId !== props.clientId) {
                                    dispatch('core/block-editor').updateBlockAttributes(
                                        block.clientId,
                                        { encypherRights: currentRights }
                                    );
                                }
                            });
                        },
                    }, 'Apply to all ' + plural)
                );
            }

            var hasOverride = !!(rights && rights.template);

            return el(
                Fragment,
                null,
                el(BlockEdit, props),
                el(BlockControls, { group: 'other' },
                    el(ToolbarGroup, null,
                        el(ToolbarButton, {
                            icon: el('img', {
                                src: brandConfig.markUrl || '',
                                alt: '',
                                'aria-hidden': 'true',
                                width: 20,
                                height: 20,
                            }),
                            label: hasOverride ? 'Custom rights applied' : 'Encypher Rights (inheriting document default)',
                            className: hasOverride ? 'encypher-toolbar-badge encypher-toolbar-badge--active' : 'encypher-toolbar-badge',
                            onClick: function () {
                                setPanelOpen(true);
                                var openPanel = dispatch('core/edit-post');
                                if (openPanel && openPanel.openGeneralSidebar) {
                                    openPanel.openGeneralSidebar('edit-post/block');
                                }
                            },
                        })
                    )
                ),
                el(
                    InspectorControls,
                    null,
                    el(
                        PanelBody,
                        {
                            title: 'Encypher Rights',
                            opened: panelOpen,
                            onToggle: function () { setPanelOpen(!panelOpen); },
                            className: 'encypher-block-rights-panel',
                        },
                        panelChildren
                    )
                )
            );
        };
    }, 'withEncypherRightsInspector');

    addFilter(
        'editor.BlockEdit',
        'encypher-provenance/block-rights-inspector',
        withRightsInspector
    );

    // ----- 3. Canvas indicator for blocks with rights overrides -----

    var withRightsIndicator = createHigherOrderComponent(function (BlockListBlock) {
        return function (props) {
            if (SUPPORTED_BLOCKS.indexOf(props.name) === -1) {
                return el(BlockListBlock, props);
            }
            var rights = props.attributes && props.attributes.encypherRights;
            if (rights && rights.template) {
                var newProps = Object.assign({}, props, {
                    className: ((props.className || '') + ' has-encypher-rights-override').trim(),
                });
                return el(BlockListBlock, newProps);
            }
            return el(BlockListBlock, props);
        };
    }, 'withEncypherRightsIndicator');

    addFilter(
        'editor.BlockListBlock',
        'encypher-provenance/block-rights-indicator',
        withRightsIndicator
    );
})();
