/**
 * Audace — Custom icons (open + close) for the core/navigation block.
 *
 * Per-icon attributes (CSS-length strings, e.g. "24px", "1.5em", "5%"):
 *   audaceIconId       audaceCloseIconId       (SVG attachment IDs)
 *   audaceOpenSize     audaceCloseSize         (icon size)
 *   audaceOpenPadY     audaceClosePadY         (vertical padding)
 *   audaceOpenPadX     audaceClosePadX         (lateral padding)
 *
 * Editor preview is injected via a scoped <style> tag using mask-image so the
 * SVG inherits currentColor. The same CSS is rendered server-side in
 * inc/nav-icon.php for the front-end output.
 */
(function (wp) {
    'use strict';
    if (!wp || !wp.hooks) return;

    var addFilter        = wp.hooks.addFilter;
    var __               = (wp.i18n && wp.i18n.__) ? wp.i18n.__ : function (s) { return s; };
    var createHigherOrderComponent = wp.compose.createHigherOrderComponent;
    var Fragment         = wp.element.Fragment;
    var createElement    = wp.element.createElement;
    var useEffect        = wp.element.useEffect;
    var useState         = wp.element.useState;
    var useSelect        = wp.data && wp.data.useSelect;
    var InspectorControls = wp.blockEditor.InspectorControls;
    var MediaUpload      = wp.blockEditor.MediaUpload;
    var MediaUploadCheck = wp.blockEditor.MediaUploadCheck;
    var PanelBody        = wp.components.PanelBody;
    var Button           = wp.components.Button;
    var ToggleControl    = wp.components.ToggleControl;
    var UnitControl      = wp.components.__experimentalUnitControl || wp.components.UnitControl;

    var DEFAULTS = {
        openSize:  '24px', openPadY:  '8px', openPadX:  '8px',
        closeSize: '24px', closePadY: '8px', closePadX: '8px'
    };

    var UNITS = [
        { value: 'px',  label: 'px',  default: 24 },
        { value: 'em',  label: 'em',  default: 1.5 },
        { value: 'rem', label: 'rem', default: 1.5 },
        { value: '%',   label: '%',   default: 50 },
        { value: 'vh',  label: 'vh',  default: 4 },
        { value: 'vw',  label: 'vw',  default: 4 }
    ];

    addFilter('blocks.registerBlockType', 'audace/nav-icon/attributes', function (settings, name) {
        if (name !== 'core/navigation') return settings;
        if (!settings.attributes) settings.attributes = {};
        var a = settings.attributes;
        a.audaceIconId       = a.audaceIconId       || { type: 'number', default: 0 };
        a.audaceIconUrl      = a.audaceIconUrl      || { type: 'string', default: '' };
        a.audaceCloseIconId  = a.audaceCloseIconId  || { type: 'number', default: 0 };
        a.audaceCloseIconUrl = a.audaceCloseIconUrl || { type: 'string', default: '' };
        a.audaceOpenSize    = a.audaceOpenSize    || { type: 'string', default: DEFAULTS.openSize };
        a.audaceOpenPadY    = a.audaceOpenPadY    || { type: 'string', default: DEFAULTS.openPadY };
        a.audaceOpenPadX    = a.audaceOpenPadX    || { type: 'string', default: DEFAULTS.openPadX };
        a.audaceCloseSize   = a.audaceCloseSize   || { type: 'string', default: DEFAULTS.closeSize };
        a.audaceClosePadY   = a.audaceClosePadY   || { type: 'string', default: DEFAULTS.closePadY };
        a.audaceClosePadX   = a.audaceClosePadX   || { type: 'string', default: DEFAULTS.closePadX };
        a.audaceSticky      = a.audaceSticky      || { type: 'boolean', default: false };
        a.audaceStickyOffset= a.audaceStickyOffset|| { type: 'string',  default: '0px' };
        return settings;
    });

    /**
     * Coerce any legacy numeric value to a CSS length string.
     */
    function asLength(v, def) {
        if (v == null || v === '') return def;
        if (typeof v === 'number') return v + 'px';
        return String(v);
    }

    function iconPicker(label, currentId, currentUrl, onSelect, onClear) {
        var preview = currentUrl
            ? createElement('div', {
                style: {
                    width: '36px', height: '36px',
                    border: '1px solid #ddd', borderRadius: '2px',
                    background: '#f6f7f7 url(' + JSON.stringify(currentUrl) + ') center/65% no-repeat',
                    flexShrink: 0
                },
                'aria-label': __('Aperçu', 'audace')
            })
            : null;

        return createElement(
            'div',
            { style: { marginBottom: '12px' } },
            createElement('p', { style: { margin: '0 0 6px', fontWeight: 600 } }, label),
            createElement(
                'div',
                { style: { display: 'flex', gap: '8px', alignItems: 'center', flexWrap: 'wrap' } },
                preview,
                createElement(
                    MediaUploadCheck,
                    null,
                    createElement(MediaUpload, {
                        allowedTypes: ['image/svg+xml', 'image'],
                        value: currentId,
                        onSelect: onSelect,
                        render: function (obj) {
                            return createElement(
                                'div',
                                { style: { display: 'flex', gap: '8px', flexWrap: 'wrap' } },
                                createElement(Button, {
                                    variant: 'secondary',
                                    onClick: obj.open
                                }, currentId ? __('Changer', 'audace') : __('Téléverser', 'audace')),
                                currentId ? createElement(Button, {
                                    variant: 'tertiary',
                                    isDestructive: true,
                                    onClick: onClear
                                }, __('Retirer', 'audace')) : null
                            );
                        }
                    })
                )
            )
        );
    }

    function lengthControl(label, value, onChange) {
        if (UnitControl) {
            return createElement(UnitControl, {
                label: label,
                value: value,
                units: UNITS,
                onChange: function (v) { onChange(v); },
                style: { marginBottom: '8px' }
            });
        }
        // Fallback: plain text input.
        return createElement('label', { style: { display: 'block', marginBottom: '8px' } },
            createElement('span', { style: { display: 'block', marginBottom: '4px', fontSize: '11px', textTransform: 'uppercase', fontWeight: 500 } }, label),
            createElement('input', {
                type: 'text',
                value: value,
                onChange: function (e) { onChange(e.target.value); },
                style: { width: '100%' }
            })
        );
    }

    var ratioCache = {};
    function getAspectRatio(url, onReady) {
        if (!url) return null;
        if (ratioCache[url] !== undefined) return ratioCache[url];
        ratioCache[url] = null;
        var img = new Image();
        img.onload = function () {
            if (img.naturalWidth > 0 && img.naturalHeight > 0) {
                ratioCache[url] = img.naturalWidth / img.naturalHeight;
                if (onReady) onReady();
            }
        };
        img.src = url;
        return null;
    }

    function buildPreviewStyle(clientId, cfg, onRatioReady) {
        if (!clientId) return '';
        var sel = '[data-block="' + clientId + '"]';
        var css = '';

        function paint(role, url, size) {
            if (!url) return '';
            var btn = role === 'open'
                ? '.wp-block-navigation__responsive-container-open'
                : '.wp-block-navigation__responsive-container-close';
            var ratio = getAspectRatio(url, onRatioReady);
            var ar = ratio ? 'aspect-ratio:' + ratio + ';' : '';
            return sel + ' ' + btn + ' > svg{display:none!important;}'
                + sel + ' ' + btn + '::before{'
                + 'content:"";display:inline-block;'
                + 'width:' + size + ';height:auto;' + ar
                + 'background:url(' + JSON.stringify(url) + ') center/contain no-repeat;'
                + '}';
        }

        css += paint('open',  cfg.openUrl,  cfg.openSize);
        css += paint('close', cfg.closeUrl, cfg.closeSize);
        css += sel + ' .wp-block-navigation__responsive-container-open{padding:'
            + cfg.openPadY + ' ' + cfg.openPadX + '!important;}';
        css += sel + ' .wp-block-navigation__responsive-container-close{padding:'
            + cfg.closePadY + ' ' + cfg.closePadX + '!important;}';

        if (cfg.sticky) {
            var top = 'calc(' + cfg.stickyOffset + ' + var(--wp-admin--admin-bar--height, 0px))';
            css += sel + '{position:sticky!important;top:' + top + '!important;z-index:50;}';
            css += 'header:has(' + sel + '){position:sticky!important;top:' + top + '!important;z-index:50;}';
        }

        return css;
    }

    var withIconControls = createHigherOrderComponent(function (BlockEdit) {
        return function (props) {
            if (props.name !== 'core/navigation') {
                return createElement(BlockEdit, props);
            }
            var a = props.attributes || {};
            var iconId  = a.audaceIconId      || 0;
            var closeId = a.audaceCloseIconId || 0;

            // Subscribe to attachment records so the URL is filled in on resolve.
            var openMedia = useSelect(function (select) {
                return iconId ? select('core').getEntityRecord('postType', 'attachment', iconId) : null;
            }, [iconId]);
            var closeMedia = useSelect(function (select) {
                return closeId ? select('core').getEntityRecord('postType', 'attachment', closeId) : null;
            }, [closeId]);

            var cfg = {
                openUrl:    a.audaceIconUrl      || (openMedia  && openMedia.source_url)  || '',
                closeUrl:   a.audaceCloseIconUrl || (closeMedia && closeMedia.source_url) || '',
                openSize:   asLength(a.audaceOpenSize,  DEFAULTS.openSize),
                openPadY:   asLength(a.audaceOpenPadY,  DEFAULTS.openPadY),
                openPadX:   asLength(a.audaceOpenPadX,  DEFAULTS.openPadX),
                closeSize:  asLength(a.audaceCloseSize, DEFAULTS.closeSize),
                closePadY:  asLength(a.audaceClosePadY, DEFAULTS.closePadY),
                closePadX:  asLength(a.audaceClosePadX, DEFAULTS.closePadX),
                sticky:       !!a.audaceSticky,
                stickyOffset: asLength(a.audaceStickyOffset, '0px')
            };

            // Backfill URL attribute for blocks saved before this attribute existed.
            useEffect(function () {
                if (iconId && !a.audaceIconUrl && openMedia && openMedia.source_url) {
                    props.setAttributes({ audaceIconUrl: openMedia.source_url });
                }
                if (closeId && !a.audaceCloseIconUrl && closeMedia && closeMedia.source_url) {
                    props.setAttributes({ audaceCloseIconUrl: closeMedia.source_url });
                }
            }, [iconId, closeId, openMedia && openMedia.source_url, closeMedia && closeMedia.source_url]);

            var ratioTick = useState(0);
            var bumpRatio = function () { ratioTick[1](function (n) { return n + 1; }); };
            var styleCss = buildPreviewStyle(props.clientId, cfg, bumpRatio);

            // The block lives inside the canvas iframe (Site Editor / Post Editor).
            // Upsert a <style> element into every document where it might be rendered
            // so size/padding/icon changes are visible live.
            useEffect(function () {
                var styleId = 'audace-nav-style-' + props.clientId;

                function collectDocs() {
                    var docs = [document];
                    function walk(root) {
                        try {
                            var frames = root.querySelectorAll('iframe');
                            for (var i = 0; i < frames.length; i++) {
                                var d = frames[i].contentDocument;
                                if (d) {
                                    docs.push(d);
                                    walk(d);
                                }
                            }
                        } catch (e) {}
                    }
                    walk(document);
                    return docs;
                }

                function apply() {
                    collectDocs().forEach(function (doc) {
                        if (!doc || !doc.head) return;
                        var node = doc.getElementById(styleId);
                        if (styleCss) {
                            if (!node) {
                                node = doc.createElement('style');
                                node.id = styleId;
                                doc.head.appendChild(node);
                            }
                            if (node.textContent !== styleCss) node.textContent = styleCss;
                        } else if (node) {
                            node.remove();
                        }
                    });
                }

                function applyHeaderClass() {
                    collectDocs().forEach(function (doc) {
                        if (!doc) return;
                        var nav = doc.querySelector('[data-block="' + props.clientId + '"]');
                        if (!nav) return;
                        var header = nav.closest('header');
                        if (!header) return;
                        if (cfg.sticky) header.classList.add('audace-sticky-header');
                        else header.classList.remove('audace-sticky-header');
                    });
                }

                apply();
                applyHeaderClass();
                // Retry shortly after in case the canvas iframe was still loading.
                var t1 = setTimeout(function () { apply(); applyHeaderClass(); }, 150);
                var t2 = setTimeout(function () { apply(); applyHeaderClass(); }, 600);

                return function () {
                    clearTimeout(t1); clearTimeout(t2);
                    collectDocs().forEach(function (doc) {
                        if (!doc) return;
                        var n = doc.getElementById(styleId);
                        if (n) n.remove();
                    });
                };
            }, [styleCss, props.clientId]);

            var setStr = function (key) {
                return function (v) {
                    var u = {};
                    u[key] = (v == null || v === '') ? DEFAULTS[key.replace('audace', '').replace(/^./, function (c) { return c.toLowerCase(); })] : String(v);
                    props.setAttributes(u);
                };
            };

            return createElement(
                Fragment,
                null,
                styleCss ? createElement('style', null, styleCss) : null,
                createElement(BlockEdit, props),
                createElement(
                    InspectorControls,
                    null,
                    createElement(
                        PanelBody,
                        { title: __('Audace — Icône d\'ouverture', 'audace'), initialOpen: true },
                        iconPicker(
                            __('Image (SVG)', 'audace'),
                            iconId,
                            cfg.openUrl,
                            function (m) { props.setAttributes({ audaceIconId: m.id, audaceIconUrl: m.url || m.source_url || '' }); },
                            function () { props.setAttributes({ audaceIconId: 0, audaceIconUrl: '' }); }
                        ),
                        lengthControl(__('Taille', 'audace'),            cfg.openSize, setStr('audaceOpenSize')),
                        lengthControl(__('Marge verticale', 'audace'),   cfg.openPadY, setStr('audaceOpenPadY')),
                        lengthControl(__('Marge latérale', 'audace'),    cfg.openPadX, setStr('audaceOpenPadX'))
                    ),
                    createElement(
                        PanelBody,
                        { title: __('Audace — Icône de fermeture', 'audace'), initialOpen: false },
                        iconPicker(
                            __('Image (SVG)', 'audace'),
                            closeId,
                            cfg.closeUrl,
                            function (m) { props.setAttributes({ audaceCloseIconId: m.id, audaceCloseIconUrl: m.url || m.source_url || '' }); },
                            function () { props.setAttributes({ audaceCloseIconId: 0, audaceCloseIconUrl: '' }); }
                        ),
                        lengthControl(__('Taille', 'audace'),            cfg.closeSize, setStr('audaceCloseSize')),
                        lengthControl(__('Marge verticale', 'audace'),   cfg.closePadY, setStr('audaceClosePadY')),
                        lengthControl(__('Marge latérale', 'audace'),    cfg.closePadX, setStr('audaceClosePadX'))
                    ),
                    createElement(
                        PanelBody,
                        { title: __('Audace — Position', 'audace'), initialOpen: false },
                        createElement(ToggleControl, {
                            label: __('Menu sticky', 'audace'),
                            help: __('Le menu reste collé en haut de la fenêtre lors du défilement.', 'audace'),
                            checked: cfg.sticky,
                            onChange: function (v) { props.setAttributes({ audaceSticky: !!v }); }
                        }),
                        cfg.sticky ? lengthControl(
                            __('Décalage du haut', 'audace'),
                            cfg.stickyOffset,
                            setStr('audaceStickyOffset')
                        ) : null
                    )
                )
            );
        };
    }, 'withAudaceNavIcons');
    addFilter('editor.BlockEdit', 'audace/nav-icon/control', withIconControls);

})(window.wp);
