(function() {
    'use strict';

    // --- КОНФИГУРАЦИЯ ---
    var SCRIPT_NAME = 'SidebarWidgets';
    var BTN_CLASS = SCRIPT_NAME + '-btn';
    var PANEL_CLASS = SCRIPT_NAME + '-panel';
    var TARGET_COLUMNS = ['Полезная информация [Remake]', 'колонка 2'];
    // Виджеты вставляются перед последним child внутри панели (кнопка «Свернуть панель»)
    var LAYOUT_NAME = 'Оформление Remake';
    var DATA_FILE_NAME = 'widgets-data';

    // --- КАТАЛОГ ВИДЖЕТОВ ---
    var WIDGETS = [];

    // --- ДОПРОДАЖИ ---
    var UPSELLS = [
        {
            label: 'Календарь',
            icon: 'fa fa-calendar-check-o',
            url: 'https://remake.space/calendar'
        },
        {
            label: 'Прогресс-бар',
            icon: 'fa fa-tasks',
            url: 'https://remake.space/shop/tproduct/661011665-499397848812-progress-bar'
        },
        {
            label: 'Избранные уроки',
            icon: 'fa fa-bookmark',
            url: 'https://remake.space/shop/tproduct/661011665-419288270592-izbrannie-uroki'
        },
        {
            label: 'Рейтинг участников',
            icon: 'fa fa-trophy',
            url: 'https://remake.space/shop/tproduct/661011665-842662157792-reiting-uchenikov'
        },
        {
            label: 'Допродажа курсов',
            icon: 'fa fa-shopping-cart',
            url: 'https://remake.space/shop/tproduct/661011665-999418985822-doprodazha-kursov'
        },
    ];

    // --- ПЕРСИСТЕНЦИЯ ПАНЕЛИ (localStorage) ---
    // GC editor теряет данные панели при повторной сериализации.
    // Сохраняем blockData панели и реинъецируем при потере.

    function getPanelStorageKey() {
        return SCRIPT_NAME + '_panel_' + window.location.pathname;
    }

    function isPanelWidget(blockData) {
        if (!blockData || !blockData.params) return false;
        return blockData.params.elementTitle === TARGET_COLUMNS[0];
    }

    function savePanelBlockData(blockData) {
        try {
            localStorage.setItem(getPanelStorageKey(), JSON.stringify(blockData));
            console.log('[SidebarWidgets] panel blockData saved to localStorage');
        } catch (e) {
            console.warn('[SidebarWidgets] failed to save panel data:', e);
        }
    }

    function loadPanelBlockData() {
        try {
            var json = localStorage.getItem(getPanelStorageKey());
            if (!json) return null;
            var data = JSON.parse(json);
            // Генерируем свежие xdgetId для каждой реинъекции
            data.xdgetId = generateXdgetId();
            ensureXdgetIds(data);
            return data;
        } catch (e) {
            console.warn('[SidebarWidgets] failed to load panel data:', e);
            return null;
        }
    }

    function clearPanelBlockData() {
        try {
            localStorage.removeItem(getPanelStorageKey());
        } catch (e) { /* ignore */ }
    }

    function hasPanelInPost(params) {
        var found = false;
        params.forEach(function(v) {
            if (v === TARGET_COLUMNS[0]) found = true;
        });
        return found;
    }

    // --- УТИЛИТЫ ---

    function isEditMode() {
        return window.location.search.indexOf('editMode=1') !== -1;
    }

    function getEditModeUrl() {
        var url = window.location.href;
        if (url.indexOf('editMode=1') !== -1) return url;
        var sep = url.indexOf('?') !== -1 ? '&' : '?';
        return url + sep + 'editMode=1';
    }

    function generateXdgetId() {
        return 'r' + Math.random().toString(36).slice(2, 6);
    }

    // --- УДАЛЁННОЕ ХРАНИЛИЩЕ ВИДЖЕТОВ (GetCourse theme file) ---

    var _cachedLayoutId = null;
    var _cachedFileKey = null;

    async function findLayoutId() {
        if (_cachedLayoutId) return _cachedLayoutId;
        var resp = await fetch('/pl/cms/layout/index');
        var html = await resp.text();
        var $link = $(html).find('table.kv-grid-table td a').filter(function() {
            return $(this).text().trim() === LAYOUT_NAME;
        });
        if (!$link.length) return null;
        var url = $link.attr('href');
        _cachedLayoutId = url.split('id=')[1];
        return _cachedLayoutId;
    }

    async function findFileKey(layoutId) {
        if (_cachedFileKey) return _cachedFileKey;
        var resp = await fetch('/pl/cms/layout/update?id=' + layoutId);
        var html = await resp.text();
        var $rows = $(html).find('.layout-add-content-files__row');
        var fileKey = null;
        $rows.each(function() {
            var name = $(this).find('.layout-add-content-files__filename a').text().trim();
            if (name === DATA_FILE_NAME) {
                fileKey = $(this).find('input[name="fileIndex[]"]').val();
                return false;
            }
        });
        _cachedFileKey = fileKey;
        return _cachedFileKey;
    }

    async function findLayoutAndFile() {
        var layoutId = await findLayoutId();
        if (!layoutId) {
            console.error(SCRIPT_NAME + ': layout "' + LAYOUT_NAME + '" не найден');
            return null;
        }
        var fileKey = await findFileKey(layoutId);
        if (!fileKey) {
            console.error(SCRIPT_NAME + ': файл "' + DATA_FILE_NAME + '" не найден в layout');
            return null;
        }
        return { layoutId: layoutId, fileKey: fileKey };
    }

    async function loadRemoteWidgets() {
        try {
            var info = await findLayoutAndFile();
            if (!info) return [];
            var resp = await fetch('/pl/cms/layout/edit-layout-file?id=' + info.layoutId + '&fileKey=' + info.fileKey);
            var html = await resp.text();
            var $page = $(html);
            var content = $page.find('textarea').first().val() || '[]';
            return JSON.parse(content);
        } catch (e) {
            console.error(SCRIPT_NAME + ': ошибка загрузки виджетов', e);
            return [];
        }
    }

    async function saveRemoteWidgets(widgets) {
        var info = await findLayoutAndFile();
        if (!info) {
            alert('Не удалось найти файл данных виджетов.');
            return false;
        }
        var resp = await fetch('/pl/cms/layout/edit-layout-file?id=' + info.layoutId + '&fileKey=' + info.fileKey);
        var html = await resp.text();
        var $page = $(html);
        var $form = $page.find('form').first();
        var action = $form.attr('action') || ('/pl/cms/layout/edit-layout-file?id=' + info.layoutId + '&fileKey=' + info.fileKey);

        var params = new URLSearchParams();
        $form.find('input[type="hidden"]').each(function() {
            params.append($(this).attr('name'), $(this).val());
        });
        params.append('content', JSON.stringify(widgets, null, 2));

        await fetch(action, {
            method: 'POST',
            headers: { 'content-type': 'application/x-www-form-urlencoded' },
            body: params.toString()
        });
        return true;
    }

    async function addCustomWidget(name, jsonStr) {
        var block;
        try {
            block = JSON.parse(jsonStr);
        } catch (e) {
            alert('Невалидный JSON. Проверьте формат.');
            return false;
        }
        if (!block.type) {
            alert('JSON должен содержать поле "type".');
            return false;
        }
        var customs = await loadRemoteWidgets();
        customs.push({
            label: name || block.type,
            icon: 'fa fa-cube',
            description: block.type,
            block: block
        });
        return await saveRemoteWidgets(customs);
    }

    async function removeCustomWidget(index) {
        var customs = await loadRemoteWidgets();
        customs.splice(index, 1);
        await saveRemoteWidgets(customs);
    }

    // --- СТИЛИ ---

    function injectStyles() {
        if (document.getElementById(SCRIPT_NAME + '-styles')) return;

        var css = [
            '@keyframes sw-panel-in {',
            '  from { opacity: 0; transform: translateY(10px) scale(0.97); }',
            '  to { opacity: 1; transform: translateY(0) scale(1); }',
            '}',
            '@keyframes sw-panel-out {',
            '  from { opacity: 1; transform: translateY(0) scale(1); }',
            '  to { opacity: 0; transform: translateY(10px) scale(0.97); }',
            '}',
            '',
            '.' + BTN_CLASS + ' {',
            '  position: fixed; bottom: 124px; right: 20px; z-index: 100000;',
            '  width: 54px; height: 54px; border-radius: 16px; border: none;',
            '  background: #fff; color: #1a1a2e;',
            '  font-size: 20px; cursor: pointer;',
            '  box-shadow: 0 1px 3px rgba(0,0,0,0.08), 0 8px 24px rgba(0,0,0,0.1);',
            '  transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);',
            '  display: flex; align-items: center; justify-content: center;',
            '}',
            '.' + BTN_CLASS + ':hover {',
            '  transform: translateY(-2px);',
            '  box-shadow: 0 2px 6px rgba(0,0,0,0.08), 0 12px 32px rgba(0,0,0,0.14);',
            '}',
            '.' + BTN_CLASS + '.sw-active {',
            '  background: #f0f0f5; border-radius: 16px 16px 4px 16px;',
            '}',
            '',
            '.' + PANEL_CLASS + ' {',
            '  position: fixed; bottom: 188px; right: 20px; z-index: 100001;',
            '  width: 300px; max-height: 520px; overflow-y: auto;',
            '  background: #fff;',
            '  border: 1px solid rgba(0,0,0,0.06);',
            '  border-radius: 18px;',
            '  box-shadow: 0 1px 3px rgba(0,0,0,0.04), 0 16px 48px rgba(0,0,0,0.12);',
            '  animation: sw-panel-in 0.22s cubic-bezier(0.16, 1, 0.3, 1) forwards;',
            '  transform-origin: bottom right;',
            '  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;',
            '}',
            '.' + PANEL_CLASS + '.sw-closing {',
            '  animation: sw-panel-out 0.15s cubic-bezier(0.4, 0, 1, 1) forwards;',
            '}',
            '',
            '.sw-section-label {',
            '  font-size: 11px; font-weight: 600; letter-spacing: 0.06em;',
            '  text-transform: uppercase; color: #a0a0b0; margin: 0;',
            '  padding: 16px 18px 8px;',
            '}',
            '.sw-divider {',
            '  height: 1px; background: #f0f0f4; margin: 4px 0;',
            '}',
            '.sw-panel-list { padding: 4px 8px 8px; }',
            '',
            '.sw-item {',
            '  display: flex; align-items: center; gap: 12px;',
            '  padding: 8px 10px; margin: 1px 0; border-radius: 10px;',
            '  cursor: pointer; transition: all 0.15s ease;',
            '  text-decoration: none !important; color: inherit;',
            '}',
            '.sw-item:hover {',
            '  background: #f5f5fa;',
            '}',
            '.sw-item:active {',
            '  transform: scale(0.98);',
            '  background: #ededf4;',
            '}',
            '.sw-item-icon {',
            '  width: 34px; height: 34px; border-radius: 8px;',
            '  background: #f5f5fa;',
            '  display: flex; align-items: center; justify-content: center;',
            '  font-size: 16px; color: #8888a0; flex-shrink: 0;',
            '  transition: all 0.15s ease;',
            '}',
            '.sw-item:hover .sw-item-icon {',
            '  background: #e8e8f4; color: #5c6bc0;',
            '}',
            '.sw-item-text { min-width: 0; }',
            '.sw-item-label {',
            '  font-size: 14px; font-weight: 500; color: #1a1a2e !important;',
            '  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;',
            '  text-decoration: none !important;',
            '}',
            '.sw-item-desc {',
            '  font-size: 12px; color: #a0a0b0; margin-top: 2px;',
            '  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;',
            '}',
            '',
            '.sw-upsell-icon {',
            '  width: 28px; height: 28px; border-radius: 7px; font-size: 13px;',
            '  background: linear-gradient(135deg, #fff8ef, #fff3e0) !important;',
            '  color: #e6a23c !important;',
            '}',
            '.sw-upsell { padding: 6px 10px; gap: 10px; }',
            '.sw-upsell .sw-item-label { font-size: 13px; }',
            '.sw-item:hover .sw-upsell-icon {',
            '  background: linear-gradient(135deg, #fff3e0, #ffe8c8) !important;',
            '  color: #d48806 !important;',
            '}',
            '.sw-upsell-arrow {',
            '  margin-left: auto; font-size: 13px; color: #c8c8d4;',
            '  transition: all 0.15s ease; flex-shrink: 0;',
            '}',
            '.sw-item:hover .sw-upsell-arrow { color: #e6a23c; transform: translateX(2px); }',
            '',
            '.sw-section-header {',
            '  display: flex; align-items: center; justify-content: space-between;',
            '  padding-right: 14px;',
            '}',
            '.sw-section-header .sw-section-label { flex: 1; }',
            '.sw-add-btn {',
            '  width: 26px; height: 26px; border-radius: 8px; border: 1px solid #e8e8f0;',
            '  background: #fafafa; color: #8888a0; font-size: 12px; cursor: pointer;',
            '  display: flex; align-items: center; justify-content: center;',
            '  transition: all 0.15s ease;',
            '}',
            '.sw-add-btn:hover { background: #f0f0f8; color: #5c6bc0; border-color: #d0d0e0; }',
            '',
            '.sw-add-form {',
            '  padding: 8px 14px 12px; border-bottom: 1px solid #f0f0f4;',
            '}',
            '.sw-add-name, .sw-add-json {',
            '  width: 100%; box-sizing: border-box; border: 1px solid #e0e0ea;',
            '  border-radius: 8px; padding: 8px 10px; font-size: 13px;',
            '  font-family: inherit; resize: vertical; outline: none;',
            '  transition: border-color 0.15s ease;',
            '}',
            '.sw-add-name:focus, .sw-add-json:focus { border-color: #5c6bc0; }',
            '.sw-add-name { margin-bottom: 8px; }',
            '.sw-add-json { min-height: 70px; font-family: monospace; font-size: 12px; }',
            '.sw-add-actions { display: flex; gap: 8px; margin-top: 8px; }',
            '.sw-add-save, .sw-add-cancel {',
            '  flex: 1; padding: 6px 0; border-radius: 8px; border: none;',
            '  font-size: 13px; font-weight: 500; cursor: pointer;',
            '  transition: all 0.15s ease;',
            '}',
            '.sw-add-save {',
            '  background: #5c6bc0; color: #fff;',
            '}',
            '.sw-add-save:hover { background: #4a5ab0; }',
            '.sw-add-cancel {',
            '  background: #f0f0f5; color: #666;',
            '}',
            '.sw-add-cancel:hover { background: #e4e4ee; }',
            '',
            '.sw-delete-btn {',
            '  background: none; border: none; color: #c8c8d4; cursor: pointer;',
            '  padding: 4px 6px; border-radius: 6px; font-size: 13px;',
            '  margin-left: auto; flex-shrink: 0;',
            '  transition: all 0.15s ease;',
            '}',
            '.sw-delete-btn:hover { color: #e55; background: #fff0f0; }',
            '',
            '@keyframes sw-loader-spin {',
            '  to { transform: rotate(360deg); }',
            '}',
            '.sw-panel-loader {',
            '  display: flex; align-items: center; justify-content: center;',
            '  padding: 40px 0;',
            '}',
            '.sw-panel-loader-spinner {',
            '  width: 28px; height: 28px; border-radius: 50%;',
            '  border: 2.5px solid #e8e8f0; border-top-color: #5c6bc0;',
            '  animation: sw-loader-spin 0.7s linear infinite;',
            '}',
            '',
            '.sw-shops { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; padding: 8px 12px 14px; }',
            '.sw-shop-btn {',
            '  display: flex; align-items: center; gap: 8px;',
            '  padding: 8px 10px; border-radius: 10px; border: 1px solid #eeeef4;',
            '  background: #fafafe; text-decoration: none !important;',
            '  transition: all 0.15s ease; cursor: pointer;',
            '}',
            '.sw-shop-btn:hover { background: #f0f0f8; border-color: #dddde8; }',
            '.sw-shop-btn:active { transform: scale(0.97); }',
            '.sw-shop-logo {',
            '  width: 22px; height: 22px; border-radius: 6px; flex-shrink: 0;',
            '  display: flex; align-items: center; justify-content: center;',
            '  font-size: 11px; font-weight: 700; color: #fff;',
            '}',
            '.sw-shop-logo-remake { background: #6366f1; }',
            '.sw-shop-logo-getscript { background: #4a9d6e; }',
            '.sw-shop-name {',
            '  font-size: 12px; font-weight: 500; color: #555 !important;',
            '  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;',
            '}',
        ].join('\n');

        var style = document.createElement('style');
        style.id = SCRIPT_NAME + '-styles';
        style.textContent = css;
        document.head.appendChild(style);
    }

    // --- ПЛАВАЮЩАЯ КНОПКА ---

    var panelOpen = false;

    function renderFloatingButton() {
        if ($('.' + BTN_CLASS).length) return;

        var $btn = $('<button class="' + BTN_CLASS + '" title="Каталог виджетов">' +
            '<i class="fa fa-puzzle-piece"></i>' +
            '</button>');

        $btn.on('click', function(e) {
            e.preventDefault();
            e.stopPropagation();
            if (panelOpen) {
                closePanel();
            } else {
                openPanel();
            }
        });

        $('body').append($btn);
    }

    // --- ПАНЕЛЬ-ПОПОВЕР ---

    async function openPanel() {
        if ($('.' + PANEL_CLASS).length) return;
        panelOpen = true;
        $('.' + BTN_CLASS).addClass('sw-active');

        // Сразу показываем панель с лоадером
        var $panel = $('<div class="' + PANEL_CLASS + '">' +
            '<div class="sw-panel-loader"><div class="sw-panel-loader-spinner"></div></div>' +
            '</div>');
        $('body').append($panel);

        var customWidgets = await loadRemoteWidgets();
        var allWidgets = WIDGETS.concat(customWidgets);

        // Если панель закрыли пока грузилось — не рендерим
        if (!panelOpen) return;

        var html = '';

        // Секция: виджеты
        html += '<div class="sw-section-header">' +
            '<p class="sw-section-label">Ваши виджеты</p>' +
            '<button class="sw-add-btn" title="Добавить виджет"><i class="fa fa-plus"></i></button>' +
            '</div>';

        // Форма добавления (скрыта по умолчанию)
        html += '<div class="sw-add-form" style="display:none;">' +
            '<input class="sw-add-name" type="text" placeholder="Название виджета" />' +
            '<textarea class="sw-add-json" placeholder="Вставьте JSON экспорта виджета..." rows="4">' + '</' + 'textarea>' +
            '<div class="sw-add-actions">' +
            '<button class="sw-add-save">Добавить</button>' +
            '<button class="sw-add-cancel">Отмена</button>' +
            '</div></div>';

        html += '<div class="sw-panel-list">';
        for (var i = 0; i < allWidgets.length; i++) {
            var w = allWidgets[i];
            var isCustom = i >= WIDGETS.length;
            html += '<div class="sw-item" data-index="' + i + '">' +
                '<div class="sw-item-icon"><i class="' + w.icon + '"></i></div>' +
                '<div class="sw-item-text">' +
                '<div class="sw-item-label">' + w.label + '</div>' +
                '<div class="sw-item-desc">' + (w.description || w.block.type) + '</div>' +
                '</div>';
            if (isCustom) {
                html += '<button class="sw-delete-btn" data-custom-index="' + (i - WIDGETS.length) + '" title="Удалить">' +
                    '<i class="fa fa-trash-o"></i></button>';
            }
            html += '</div>';
        }
        html += '</div>';

        // Разделитель + секция: допродажи
        html += '<div class="sw-divider"></div>' +
            '<p class="sw-section-label">Ещё вы можете купить</p>' +
            '<div class="sw-panel-list">';
        for (var j = 0; j < UPSELLS.length; j++) {
            var u = UPSELLS[j];
            html += '<a class="sw-item sw-upsell" href="' + u.url + '" target="_blank">' +
                '<div class="sw-item-icon sw-upsell-icon"><i class="' + u.icon + '"></i></div>' +
                '<div class="sw-item-text">' +
                '<div class="sw-item-label">' + u.label + '</div>' +
                '</div>' +
                '<span class="sw-upsell-arrow"><i class="fa fa-chevron-right"></i></span>' +
                '</a>';
        }
        html += '</div>';

        // Секция: магазины
        html += '<div class="sw-divider"></div>' +
            '<p class="sw-section-label">Каталоги скриптов</p>' +
            '<div class="sw-shops">' +
            '<a class="sw-shop-btn" href="https://remake.space/shop" target="_blank">' +
            '<div class="sw-shop-logo sw-shop-logo-remake">R</div>' +
            '<span class="sw-shop-name">Remake</span>' +
            '</a>' +
            '<a class="sw-shop-btn" href="https://getscript.ru" target="_blank">' +
            '<div class="sw-shop-logo sw-shop-logo-getscript">G</div>' +
            '<span class="sw-shop-name">GetScript</span>' +
            '</a>' +
            '</div>';

        // Заменяем лоадер на контент
        $panel.html(html);

        // Клик по виджету — импорт
        $panel.find('.sw-item[data-index]').on('click', function(e) {
            if ($(e.target).closest('.sw-delete-btn').length) return;
            var index = parseInt($(this).attr('data-index'), 10);
            closePanel();
            onWidgetSelected(allWidgets[index]);
        });

        // Удаление кастомного виджета
        $panel.find('.sw-delete-btn').on('click', async function(e) {
            e.stopPropagation();
            var ci = parseInt($(this).attr('data-custom-index'), 10);
            var $btn = $(this);
            $btn.find('i').removeClass('fa-trash-o').addClass('fa-spinner fa-spin');
            await removeCustomWidget(ci);
            closePanel();
            setTimeout(openPanel, 200);
        });

        // Кнопка «+» — показать/скрыть форму
        $panel.find('.sw-add-btn').on('click', function(e) {
            e.stopPropagation();
            $panel.find('.sw-add-form').slideToggle(150);
        });

        // Сохранение нового виджета
        $panel.find('.sw-add-save').on('click', async function(e) {
            e.stopPropagation();
            var name = $panel.find('.sw-add-name').val().trim();
            var json = $panel.find('.sw-add-json').val().trim();
            if (!json) { alert('Вставьте JSON виджета.'); return; }
            var $btn = $(this);
            $btn.text('Сохраняю...').prop('disabled', true);
            var ok = await addCustomWidget(name, json);
            if (ok) {
                closePanel();
                setTimeout(openPanel, 200);
            } else {
                $btn.text('Добавить').prop('disabled', false);
            }
        });

        // Отмена
        $panel.find('.sw-add-cancel').on('click', function(e) {
            e.stopPropagation();
            $panel.find('.sw-add-form').slideUp(150);
        });

        // Закрытие по клику вне
        setTimeout(function() {
            $(document).on('click.sw-panel', function(e) {
                if (!$(e.target).closest('.' + PANEL_CLASS + ', .' + BTN_CLASS).length) {
                    closePanel();
                }
            });
        }, 10);
    }

    function closePanel() {
        var $panel = $('.' + PANEL_CLASS);
        if (!$panel.length) { panelOpen = false; return; }

        $panel.addClass('sw-closing');
        $('.' + BTN_CLASS).removeClass('sw-active');
        $(document).off('click.sw-panel');

        setTimeout(function() {
            $panel.remove();
            panelOpen = false;
        }, 150);
    }

    // --- ОБРАБОТКА ВЫБОРА ВИДЖЕТА ---

    function onWidgetSelected(widget) {
        importWidget(widget.block);
    }

    // --- ВСПОМОГАТЕЛЬНЫЕ ФУНКЦИИ ИМПОРТА ---

    var STANDARD_PARAM_KEYS = ['elClass', 'elId', 'visibleTo', 'fixedClass', 'elementTitle', 'invisibleTo', 'attributesStr', 'clickLink'];

    function ensureXdgetIds(block) {
        if (!block.xdgetId) {
            block.xdgetId = generateXdgetId();
        }
        if (block.params && Array.isArray(block.params.children)) {
            for (var i = 0; i < block.params.children.length; i++) {
                ensureXdgetIds(block.params.children[i]);
            }
        }
    }

    function ensureStandardParams(block) {
        if (!block.params) block.params = {};
        for (var i = 0; i < STANDARD_PARAM_KEYS.length; i++) {
            var key = STANDARD_PARAM_KEYS[i];
            if (!(key in block.params)) {
                block.params[key] = '';
            }
        }
        if (block.params.children && Array.isArray(block.params.children)) {
            for (var j = 0; j < block.params.children.length; j++) {
                ensureStandardParams(block.params.children[j]);
            }
        }
    }

    function flattenObject(params, prefix, obj) {
        if (obj === null || obj === undefined) {
            params.append(prefix, '');
            return;
        }
        if (typeof obj === 'boolean') {
            params.append(prefix, obj.toString());
            return;
        }
        if (typeof obj !== 'object') {
            params.append(prefix, String(obj));
            return;
        }
        if (Array.isArray(obj)) {
            for (var i = 0; i < obj.length; i++) {
                flattenObject(params, prefix + '[' + i + ']', obj[i]);
            }
            return;
        }
        var keys = Object.keys(obj);
        for (var k = 0; k < keys.length; k++) {
            flattenObject(params, prefix + '[' + keys[k] + ']', obj[keys[k]]);
        }
    }

    /**
     * Сдвигает children[fromIdx..toIdx] на +1 в URLSearchParams.
     * Собирает все записи, переименовывает индексы, пересоздаёт params.
     */
    function shiftChildrenFrom(params, childrenPrefix, fromIdx, toIdx) {
        // Собрать все записи: неизменные + переименованные
        var entries = [];
        params.forEach(function(value, key) {
            if (key.indexOf(childrenPrefix + '[') === 0) {
                var rest = key.substring(childrenPrefix.length);
                var match = rest.match(/^\[(\d+)\]/);
                if (match) {
                    var idx = parseInt(match[1], 10);
                    if (idx >= fromIdx && idx <= toIdx) {
                        // Сдвигаем индекс на +1
                        var newKey = childrenPrefix + '[' + (idx + 1) + ']' + rest.substring(match[0].length);
                        entries.push({ key: newKey, value: value });
                        return; // не добавляем старый ключ
                    }
                }
            }
            entries.push({ key: key, value: value });
        });

        // Пересоздать params из entries
        // Удалить всё и заполнить заново
        var allKeys = [];
        params.forEach(function(v, k) { allKeys.push(k); });
        for (var i = 0; i < allKeys.length; i++) params.delete(allKeys[i]);
        for (var j = 0; j < entries.length; j++) params.append(entries[j].key, entries[j].value);
    }

    /**
     * Находит точку вставки виджета внутри панели «Полезная информация [Remake]».
     * Логика: находим контейнер по elementTitle → заходим в children[0] (внутренний контейнер)
     * → вставляем перед последним child (кнопка «Свернуть панель» — всегда последний).
     * Возвращает { childrenPrefix, index } или null.
     */
    function findPanelInsertPoint(params) {
        var panelPrefix = null;
        params.forEach(function(value, key) {
            if (panelPrefix) return;
            if (key.endsWith('[params][elementTitle]') && value === TARGET_COLUMNS[0]) {
                panelPrefix = key.replace(/\[params\]\[elementTitle\]$/, '');
            }
        });
        if (!panelPrefix) return null;

        // Внутренний контейнер — children[0]
        var childrenPrefix = panelPrefix + '[params][children][0][params][children]';

        // Находим максимальный индекс child
        var maxIndex = -1;
        params.forEach(function(value, key) {
            if (key.indexOf(childrenPrefix + '[') === 0) {
                var rest = key.substring(childrenPrefix.length);
                var match = rest.match(/^\[(\d+)\]/);
                if (match) {
                    var idx = parseInt(match[1], 10);
                    if (idx > maxIndex) maxIndex = idx;
                }
            }
        });

        if (maxIndex < 0) return null;

        // Вставляем перед последним child (сдвигаем его на +1)
        return { childrenPrefix: childrenPrefix, index: maxIndex };
    }

    /**
     * Вставить виджет перед последним child (сдвигая его на +1).
     * Безопасная реализация: создаёт НОВЫЙ URLSearchParams вместо
     * мутации через delete-all (которая теряла данные на больших POST body).
     */
    function insertBeforeSibling(params, beforeBlock, blockData) {
        var childrenPrefix = beforeBlock.childrenPrefix;
        var insertAt = beforeBlock.index;

        // Prefix ключей последнего child (который сдвигаем на +1)
        var lastChildKeyPrefix = childrenPrefix + '[' + insertAt + ']';
        var shiftedPrefix = childrenPrefix + '[' + (insertAt + 1) + ']';

        // Один проход: разделяем на «остальное» и «последний child со сдвинутым индексом»
        var lastChildEntries = [];
        var newParams = new URLSearchParams();

        params.forEach(function(value, key) {
            if (key.indexOf(lastChildKeyPrefix) === 0) {
                // Ключ последнего child → сохраняем с новым индексом
                var suffix = key.substring(lastChildKeyPrefix.length);
                lastChildEntries.push({ key: shiftedPrefix + suffix, value: value });
            } else {
                // Все остальные ключи → копируем как есть
                newParams.append(key, value);
            }
        });

        // Вставляем виджет на освободившуюся позицию
        flattenObject(newParams, lastChildKeyPrefix, blockData);

        // Добавляем сдвинутый последний child после виджета
        for (var i = 0; i < lastChildEntries.length; i++) {
            newParams.append(lastChildEntries[i].key, lastChildEntries[i].value);
        }

        return newParams.toString();
    }

    /** Добавить виджет в конец контейнера (по xdgetId) */
    function appendToContainer(params, containerXdgetId, blockData) {
        var containerPrefix = null;
        params.forEach(function(value, key) {
            if (key.endsWith('[xdgetId]') && value === containerXdgetId) {
                containerPrefix = key.replace(/\[xdgetId\]$/, '');
            }
        });
        if (!containerPrefix) {
            throw new Error('Контейнер xdgetId=' + containerXdgetId + ' не найден');
        }

        var childrenPrefix = containerPrefix + '[params][children]';
        var maxIndex = -1;
        params.forEach(function(value, key) {
            if (key.indexOf(childrenPrefix + '[') === 0) {
                var rest = key.substring(childrenPrefix.length);
                var match = rest.match(/^\[(\d+)\]/);
                if (match) {
                    var idx = parseInt(match[1], 10);
                    if (idx > maxIndex) maxIndex = idx;
                }
            }
        });

        flattenObject(params, childrenPrefix + '[' + (maxIndex + 1) + ']', blockData);
        return params.toString();
    }

    // --- СОЗДАНИЕ КОЛОНКИ 2 ---

    var COLUMN_NAME = 'колонка 2';
    var COLUMN_WIDTH = 'm4';
    var MAIN_COLUMN_WIDTH = 'm8';

    function injectColumnIntoBody(body) {
        var params = new URLSearchParams(body);

        // Стратегия 1: Найти существующий row — добавить container внутрь
        var rowPrefix = null;
        params.forEach(function(value, key) {
            if (!rowPrefix && key.endsWith('[type]') && value === 'row') {
                rowPrefix = key.replace(/\[type\]$/, '');
            }
        });

        if (rowPrefix) {
            return injectColumnIntoRow(params, rowPrefix);
        }

        // Стратегия 2: row нет — найти главный container/area, создать row внутри него
        var containerPrefix = null;
        var containerTypes = ['area', 'container'];
        for (var t = 0; t < containerTypes.length; t++) {
            var searchType = containerTypes[t];
            params.forEach(function(value, key) {
                if (!containerPrefix && key.endsWith('[type]') && value === searchType) {
                    containerPrefix = key.replace(/\[type\]$/, '');
                }
            });
            if (containerPrefix) break;
        }

        if (!containerPrefix) {
            throw new Error('Ни row, ни container/area не найдены в данных страницы');
        }

        return injectRowWithColumns(params, containerPrefix);
    }

    // Добавить container (колонку 2) в существующий row
    function injectColumnIntoRow(params, rowPrefix) {
        var rowChildrenPrefix = rowPrefix + '[params][children]';
        var maxContainerIndex = -1;
        var firstContainerMdWidthKey = null;

        params.forEach(function(value, key) {
            if (key.indexOf(rowChildrenPrefix + '[') !== 0) return;
            var rest = key.substring(rowChildrenPrefix.length);
            var match = rest.match(/^\[(\d+)\]/);
            if (!match) return;

            var idx = parseInt(match[1], 10);
            if (idx > maxContainerIndex) maxContainerIndex = idx;

            if (idx === 0 && key.endsWith('[params][mdWidth]')) {
                firstContainerMdWidthKey = key;
            }
        });

        if (firstContainerMdWidthKey) {
            params.set(firstContainerMdWidthKey, MAIN_COLUMN_WIDTH);
        }

        var newColumnId = generateXdgetId();
        var newPrefix = rowChildrenPrefix + '[' + (maxContainerIndex + 1) + ']';
        flattenObject(params, newPrefix, makeColumnBlock(newColumnId));

        return { body: params.toString(), columnId: newColumnId };
    }

    // Создать row с двумя колонками, переместив существующие children внутрь колонки 1
    function injectRowWithColumns(params, containerPrefix) {
        var childrenPrefix = containerPrefix + '[params][children]';

        // 1. Собрать все существующие children area/container
        var existingEntries = [];
        var keysToDelete = [];
        params.forEach(function(value, key) {
            if (key.indexOf(childrenPrefix + '[') === 0) {
                existingEntries.push({ key: key, value: value });
                keysToDelete.push(key);
            }
        });

        // 2. Удалить старые ключи
        for (var d = 0; d < keysToDelete.length; d++) {
            params.delete(keysToDelete[d]);
        }

        // 3. Пересоздать с новым путём: old children → row > column1 > children
        var col1ChildrenPrefix = childrenPrefix + '[0][params][children][0][params][children]';
        for (var e = 0; e < existingEntries.length; e++) {
            var newKey = existingEntries[e].key.replace(childrenPrefix, col1ChildrenPrefix);
            params.append(newKey, existingEntries[e].value);
        }

        // 4. Добавить метаданные row
        var rowPrefix = childrenPrefix + '[0]';
        params.append(rowPrefix + '[type]', 'row');
        params.append(rowPrefix + '[xdgetId]', generateXdgetId());
        var rowStdKeys = ['elClass', 'elId', 'visibleTo', 'fixedClass', 'elementTitle', 'invisibleTo', 'attributesStr', 'clickLink'];
        for (var r = 0; r < rowStdKeys.length; r++) {
            params.append(rowPrefix + '[params][' + rowStdKeys[r] + ']', '');
        }

        // 5. Добавить метаданные column 1 (children уже перемещены на шаге 3)
        var col1Prefix = rowPrefix + '[params][children][0]';
        params.append(col1Prefix + '[type]', 'container');
        params.append(col1Prefix + '[xdgetId]', generateXdgetId());
        params.append(col1Prefix + '[params][mdWidth]', MAIN_COLUMN_WIDTH);
        var colStdKeys = ['elClass', 'elId', 'visibleTo', 'fixedClass', 'invisibleTo', 'attributesStr', 'clickLink'];
        for (var c = 0; c < colStdKeys.length; c++) {
            params.append(col1Prefix + '[params][' + colStdKeys[c] + ']', '');
        }
        params.append(col1Prefix + '[params][elementTitle]', 'колонка 1');

        // 6. Добавить column 2
        var column2Id = generateXdgetId();
        var col2Prefix = rowPrefix + '[params][children][1]';
        flattenObject(params, col2Prefix, makeColumnBlock(column2Id));

        return { body: params.toString(), columnId: column2Id };
    }

    function makeColumnBlock(columnId) {
        return {
            type: 'container',
            xdgetId: columnId,
            params: {
                mdWidth: COLUMN_WIDTH,
                elClass: '',
                elId: '',
                visibleTo: '',
                fixedClass: '',
                elementTitle: COLUMN_NAME,
                invisibleTo: '',
                attributesStr: '',
                clickLink: '',
                children: []
            }
        };
    }

    // --- РАБОТА С ДЕРЕВОМ rootXdget ---

    /** Рекурсивный поиск узла по xdgetId в дереве */
    function findNodeByXdgetId(node, xdgetId) {
        if (!node) return null;
        if (node.xdgetId === xdgetId) return node;
        var children = node.children || (node.params && node.params.children) || [];
        for (var i = 0; i < children.length; i++) {
            var found = findNodeByXdgetId(children[i], xdgetId);
            if (found) return found;
        }
        return null;
    }

    /** Рекурсивный поиск узла по type в дереве */
    function findNodeByType(node, type) {
        var children = node.children || (node.params && node.params.children) || [];
        for (var i = 0; i < children.length; i++) {
            if (children[i].type === type) return children[i];
            var found = findNodeByType(children[i], type);
            if (found) return found;
        }
        return null;
    }

    /** Добавить виджет в дерево rootXdget по стратегии */
    function addWidgetToTree(tree, targets, blockData) {
        // Стратегия 1: панель существует → вставить перед последним child (кнопка «Свернуть»)
        if (targets.primary) {
            var panel = findNodeByXdgetId(tree, targets.primary);
            if (panel && panel.params && Array.isArray(panel.params.children) && panel.params.children.length > 0) {
                var inner = panel.params.children[0];
                if (inner && inner.params && Array.isArray(inner.params.children) && inner.params.children.length > 0) {
                    inner.params.children.splice(inner.params.children.length - 1, 0, blockData);
                    return;
                }
            }
        }

        // Стратегия 2: колонка существует → append в конец
        if (targets.column) {
            var column = findNodeByXdgetId(tree, targets.column);
            if (column) {
                if (!column.params) column.params = {};
                if (!Array.isArray(column.params.children)) column.params.children = [];
                column.params.children.push(blockData);
                return;
            }
        }

        // Стратегия 3: колонки нет → создать row + columns → append виджет
        var col2Id = injectColumnIntoTree(tree);
        var col2 = findNodeByXdgetId(tree, col2Id);
        if (col2) {
            if (!col2.params) col2.params = {};
            if (!Array.isArray(col2.params.children)) col2.params.children = [];
            col2.params.children.push(blockData);
        }
    }

    /** Создать структуру row + 2 колонки в дереве. Возвращает xdgetId колонки 2. */
    function injectColumnIntoTree(tree) {
        // Если row уже есть → просто добавить col2
        var row = findNodeByType(tree, 'row');
        if (row && row.params && Array.isArray(row.params.children)) {
            if (row.params.children[0] && row.params.children[0].params) {
                row.params.children[0].params.mdWidth = MAIN_COLUMN_WIDTH;
            }
            var col2 = makeColumnBlock(generateXdgetId());
            ensureStandardParams(col2);
            row.params.children.push(col2);
            return col2.xdgetId;
        }

        // Row нет → найти area/container, обернуть его children в row
        var container = null;
        var children = tree.children || [];
        for (var i = 0; i < children.length; i++) {
            if (children[i].type === 'area' || children[i].type === 'container') {
                container = children[i];
                break;
            }
        }
        if (!container) throw new Error('Ни row, ни container/area не найдены');

        var existingChildren = (container.params && container.params.children) || [];

        var col1 = {
            type: 'container',
            xdgetId: generateXdgetId(),
            params: {
                mdWidth: MAIN_COLUMN_WIDTH,
                elClass: '', elId: '', visibleTo: '', fixedClass: '',
                elementTitle: 'колонка 1', invisibleTo: '', attributesStr: '', clickLink: '',
                children: existingChildren
            }
        };
        ensureStandardParams(col1);

        var col2 = makeColumnBlock(generateXdgetId());
        ensureStandardParams(col2);

        var rowNode = {
            type: 'row',
            xdgetId: generateXdgetId(),
            params: {
                elClass: '', elId: '', visibleTo: '', fixedClass: '',
                elementTitle: '', invisibleTo: '', attributesStr: '', clickLink: '',
                children: [col1, col2]
            }
        };
        ensureStandardParams(rowNode);

        container.params.children = [rowNode];
        return col2.xdgetId;
    }

    // --- ИМПОРТ ВИДЖЕТА В КОЛОНКУ ---

    function isSaveRequest(url, data) {
        if (typeof url === 'string' && url.indexOf('saveChanges') !== -1) return true;
        if (typeof data === 'string' && data.indexOf('action=saveXdget') !== -1) return true;
        return false;
    }

    // Лоадер — показываем пользователю что идёт установка
    function showImportLoader() {
        var $overlay = $('<div id="sw-import-loader" style="' +
            'position:fixed;inset:0;z-index:999999;' +
            'background:rgba(255,255,255,0.85);backdrop-filter:blur(4px);' +
            'display:flex;align-items:center;justify-content:center;' +
            'font-family:-apple-system,BlinkMacSystemFont,sans-serif;' +
            '">' +
            '<div style="text-align:center;">' +
            '<div style="width:40px;height:40px;border:3px solid #e0e0ea;border-top-color:#5c6bc0;border-radius:50%;margin:0 auto 16px;' +
            'animation:sw-spin 0.8s linear infinite;"></div>' +
            '<div style="font-size:15px;font-weight:500;color:#1a1a2e;">Устанавливаю виджет...</div>' +
            '<div style="font-size:12px;color:#a0a0b0;margin-top:6px;">Не закрывайте страницу</div>' +
            '</div></div>');

        if (!document.getElementById('sw-spin-style')) {
            var spin = document.createElement('style');
            spin.id = 'sw-spin-style';
            spin.textContent = '@keyframes sw-spin { to { transform: rotate(360deg); } }';
            document.head.appendChild(spin);
        }

        $('body').append($overlay);
        return $overlay;
    }

    function hideImportLoader() {
        $('#sw-import-loader').remove();
    }

    async function importWidget(block) {
        var blockData = JSON.parse(JSON.stringify(block));
        blockData.xdgetId = generateXdgetId();
        ensureXdgetIds(blockData);
        ensureStandardParams(blockData);

        if (isEditMode()) {
            importWidgetDirect(blockData);
        } else {
            importWidgetViaIframe(blockData);
        }
    }

    // Прямой импорт — когда уже в editMode
    function importWidgetDirect(blockData) {
        var targets = findTargetColumns($);

        hookAjaxAndSave($, targets, blockData, function() {
            var cleanUrl = window.location.href
                .replace(/\/editMode\/1/, '')
                .replace(/[?&]editMode=1/, '')
                .replace(/\?$/, '');
            window.location.href = cleanUrl;
        });
    }

    // Невидимый импорт — через скрытый iframe с editMode
    function importWidgetViaIframe(blockData) {
        var $loader = showImportLoader();

        var iframe = document.createElement('iframe');
        iframe.style.cssText = 'position:fixed;left:-9999px;top:-9999px;width:1px;height:1px;opacity:0;pointer-events:none;';
        iframe.src = getEditModeUrl();

        var iframeTimeout = setTimeout(function() {
            hideImportLoader();
            if (iframe.parentNode) iframe.parentNode.removeChild(iframe);
            alert(SCRIPT_NAME + ': не удалось загрузить редактор. Попробуйте ещё раз.');
        }, 30000);

        iframe.onload = function() {
            try {
                var iframeWindow = iframe.contentWindow;
                var iframe$ = iframeWindow.jQuery || iframeWindow.$;

                if (!iframe$) {
                    clearTimeout(iframeTimeout);
                    hideImportLoader();
                    iframe.parentNode.removeChild(iframe);
                    alert(SCRIPT_NAME + ': jQuery не найден в редакторе.');
                    return;
                }

                // Подождать инициализации редактора (editor select должен появиться)
                var checkInterval = setInterval(function() {
                    var $select = iframe$('.global-xdget-editor .element-panel select');
                    if (!$select.length) return;

                    clearInterval(checkInterval);
                    clearTimeout(iframeTimeout);

                    var targets = findTargetColumns(iframe$);

                    hookAjaxAndSave(iframe$, targets, blockData, function() {
                        hideImportLoader();
                        iframe.parentNode.removeChild(iframe);
                        window.location.reload();
                    });
                }, 300);

                // Таймаут ожидания редактора внутри iframe
                setTimeout(function() {
                    clearInterval(checkInterval);
                }, 25000);

            } catch (e) {
                clearTimeout(iframeTimeout);
                hideImportLoader();
                if (iframe.parentNode) iframe.parentNode.removeChild(iframe);
                console.error(SCRIPT_NAME + ': ошибка доступа к iframe', e);
                alert(SCRIPT_NAME + ': ошибка доступа к редактору.');
            }
        };

        document.body.appendChild(iframe);
    }

    // Найти целевые контейнеры в <select> редактора
    // Возвращает { primary: value|null, column: value|null }
    //   primary — «Полезная информация [Remake]» (виджет пойдёт перед «Свернуть панель»)
    //   column  — «колонка 2» (фоллбэк — append в конец)
    function findTargetColumns(jq) {
        var $select = jq('.global-xdget-editor .element-panel select');
        var result = { primary: null, column: null };

        $select.find('option').each(function() {
            var text = jq(this).text().trim();
            if (!result.primary && text === TARGET_COLUMNS[0]) {
                result.primary = jq(this).val();
            }
            if (!result.column && text === TARGET_COLUMNS[1]) {
                result.column = jq(this).val();
            }
        });

        return result;
    }

    // Зацепить ajaxPrefilter и нажать Save
    // targets = { primary, column } из findTargetColumns
    //
    // КЛЮЧЕВОЙ ФИКС: GC editor делает ДВА save-запроса при клике на Save
    // (xdget-editor-*.js:197 → main.js:169 ajaxCall). Раньше мы модифицировали
    // только первый (intercepted=true), а второй шёл с оригинальными данными
    // и ПЕРЕЗАПИСЫВАЛ наши изменения на сервере.
    // Теперь сохраняем модифицированный POST body и подменяем его во ВСЕХ save-запросах.
    function hookAjaxAndSave(jq, targets, blockData, onSuccess) {
        var modifiedData = null; // хранит модифицированный POST body для повторных запросов
        var saveCount = 0;

        var prefilterTimeout = setTimeout(function() {
            modifiedData = 'TIMEOUT';
            hideImportLoader();
            alert(SCRIPT_NAME + ': сохранение не сработало за 15 сек. Попробуйте ещё раз.');
        }, 15000);

        jq.ajaxPrefilter(function(options) {
            if (!isSaveRequest(options.url, options.data)) return;
            if (modifiedData === 'TIMEOUT') return;

            saveCount++;

            // Повторный save-запрос — подменяем data на наш модифицированный
            if (modifiedData !== null) {
                console.log('[SidebarWidgets] save #' + saveCount +
                    ': replaying modified data (size=' + modifiedData.length +
                    ', original=' + (options.data ? options.data.length : 0) + ')');
                options.data = modifiedData;
                return;
            }

            // Первый save-запрос — модифицируем POST body
            clearTimeout(prefilterTimeout);

            try {
                var params = new URLSearchParams(options.data);

                var origKeyCount = 0;
                params.forEach(function() { origKeyCount++; });
                console.log('[SidebarWidgets] original POST: keys=' + origKeyCount + ', size=' + options.data.length);

                var targetId = targets.column;
                var strategy = 'none';
                var usedColumnId = null; // ID колонки для возможной реинъекции панели

                if (targets.primary) {
                    var panelPoint = findPanelInsertPoint(params);
                    if (panelPoint) {
                        targetId = null;
                        strategy = 'panel-insert';
                        console.log('[SidebarWidgets] panel found in POST at index=' + panelPoint.index);
                    } else {
                        console.log('[SidebarWidgets] panel NOT in POST body, falling to column');
                    }
                }

                if (targetId && strategy === 'none') {
                    var colFound = false;
                    params.forEach(function(v, k) {
                        if (k.endsWith('[xdgetId]') && v === targetId) colFound = true;
                    });

                    if (colFound) {
                        appendToContainer(params, targetId, blockData);
                        strategy = 'column-append';
                        usedColumnId = targetId;
                        console.log('[SidebarWidgets] appended to column xdgetId=' + targetId);
                    } else {
                        console.log('[SidebarWidgets] column ' + targetId + ' NOT in POST body');
                    }
                }

                if (strategy === 'none') {
                    var result = injectColumnIntoBody(options.data);
                    params = new URLSearchParams(result.body);
                    appendToContainer(params, result.columnId, blockData);
                    strategy = 'create-column';
                    usedColumnId = result.columnId;
                    console.log('[SidebarWidgets] created column, id=' + result.columnId);
                }

                if (strategy === 'panel-insert') {
                    params = new URLSearchParams(options.data);
                    var panelPrefix2 = null;
                    params.forEach(function(value, key) {
                        if (panelPrefix2) return;
                        if (key.endsWith('[params][elementTitle]') && value === TARGET_COLUMNS[0]) {
                            panelPrefix2 = key.replace(/\[params\]\[elementTitle\]$/, '');
                        }
                    });
                    if (panelPrefix2) {
                        var innerXdgetIdKey = panelPrefix2 + '[params][children][0][xdgetId]';
                        var innerXdgetId = params.get(innerXdgetIdKey);
                        if (innerXdgetId) {
                            appendToContainer(params, innerXdgetId, blockData);
                            console.log('[SidebarWidgets] appended to panel inner container xdgetId=' + innerXdgetId);
                        } else {
                            var panelXdgetIdKey = panelPrefix2 + '[xdgetId]';
                            var panelXdgetId = params.get(panelXdgetIdKey);
                            if (panelXdgetId) {
                                appendToContainer(params, panelXdgetId, blockData);
                                console.log('[SidebarWidgets] appended to panel xdgetId=' + panelXdgetId);
                            }
                        }
                    }
                }

                // --- ПЕРСИСТЕНЦИЯ ПАНЕЛИ ---
                // Сохранить blockData панели при её установке
                if (isPanelWidget(blockData)) {
                    savePanelBlockData(blockData);
                    console.log('[SidebarWidgets] panel widget detected, saving to localStorage');
                }

                // Реинъекция: если панель отсутствует в POST, но была ранее установлена
                if (!isPanelWidget(blockData) && usedColumnId && !hasPanelInPost(params)) {
                    var savedPanel = loadPanelBlockData();
                    if (savedPanel) {
                        appendToContainer(params, usedColumnId, savedPanel);
                        console.log('[SidebarWidgets] re-injected saved panel into column ' + usedColumnId);
                    }
                }

                options.data = params.toString();
                modifiedData = options.data; // сохраняем для повторных save-запросов

                // Диагностика: итоговый POST body
                var finalParams = new URLSearchParams(options.data);
                var finalKeyCount = 0;
                var finalHasPanel = false;
                finalParams.forEach(function(v) {
                    finalKeyCount++;
                    if (v === 'Полезная информация [Remake]') finalHasPanel = true;
                });
                console.log('[SidebarWidgets] strategy=' + strategy +
                    ' | FINAL POST: keys=' + finalKeyCount +
                    ', size=' + options.data.length + ', hasPanel=' + finalHasPanel);
            } catch (e) {
                console.error(SCRIPT_NAME + ': ошибка при добавлении виджета', e);
            }

            var origSuccess = options.success;
            var origError = options.error;

            options.success = function(data, textStatus, jqXHR) {
                console.log('[SidebarWidgets] Save response:', jqXHR ? jqXHR.status : '?',
                    typeof data === 'string' ? data.substring(0, 200) : JSON.stringify(data).substring(0, 200));
                if (origSuccess) origSuccess.apply(this, arguments);
                if (onSuccess) onSuccess();
            };

            options.error = function(jqXHR, textStatus, errorThrown) {
                console.error('[SidebarWidgets] Save FAILED:', textStatus, errorThrown,
                    jqXHR ? jqXHR.responseText && jqXHR.responseText.substring(0, 300) : '');
                if (origError) origError.apply(this, arguments);
            };
        });

        // Нажать Save
        var $saveBtn = jq('.global-xdget-editor .root-element-panel .btn-save');
        if (!$saveBtn.length) {
            $saveBtn = jq('.global-xdget-editor .btn-save').first();
        }

        if (!$saveBtn.length) {
            clearTimeout(prefilterTimeout);
            modifiedData = 'NO_BTN';
            hideImportLoader();
            alert('Кнопка "Сохранить" не найдена.');
            return;
        }

        $saveBtn.trigger('click');
    }

    // --- ИНИЦИАЛИЗАЦИЯ ---

    $(function() {
        if (!window.userInfo || !window.userInfo.isAdmin) return;
        injectStyles();
        renderFloatingButton();
    });

})();
