/*
 * Amazon Template Mapping interactions – extracted from inline script.
 * This is a near-verbatim move; PHP-echoed strings/nonces are replaced by values
 * injected via wp_localize_script("momcsAmazonTemplateMapping", …).
 *
 * @package MOMCS_Sync
 */

/* global jQuery, ajaxurl */
(function ($) {
    'use strict';

    // Guard: script may be enqueued on pages that do not localize momcsAmazonTemplateMapping (e.g. Sync settings).
    if (typeof window.momcsAmazonTemplateMapping === 'undefined') {
        console.log('[MOMCS] Amazon Template Mapping JS: config not localized on this page, skipping init.');
        return;
    }

    console.log("Amazon Template Mapping JS Loaded - Hierarchical field mapping active");

    const cfg = window.momcsAmazonTemplateMapping || {};

    // -------------------------------------------------------------------------
    // Shimmer helpers – overlay SearchableSelect wrappers with skeleton bars
    // -------------------------------------------------------------------------

    // Shimmer for the Template dropdown (premium) until templates list is fetched
    function showTemplateDropdownSkeleton() {
        const $wrapper = $('#momcs-template-dropdown-container .momcs-searchable-wrapper');
        if (!$wrapper.length) return;
        $wrapper.addClass('momcs-searchable-loading');
        if (!$wrapper.find('.momcs-skeleton-select').length) {
            $wrapper.append('<div class="momcs-skeleton-select" aria-hidden="true"></div>');
        }
    }

    function hideTemplateDropdownSkeleton() {
        const $container = $('#momcs-template-dropdown-container');
        $container.find('.momcs-skeleton-select').remove();
        $container.find('.momcs-searchable-wrapper').removeClass('momcs-searchable-loading');
    }

    // Shimmer for WC & Amazon category SearchableSelect wrappers
    function showTemplateMappingSkeleton() {
        const $row = $('#momcs-template-mapping-rows .momcs-template-mapping-row').first();
        if (!$row.length) return;

        $row.find('.momcs-searchable-wrapper').each(function () {
            const $wrapper = $(this);
            $wrapper.addClass('momcs-searchable-loading');
            if (!$wrapper.find('.momcs-skeleton-select').length) {
                $wrapper.append('<div class="momcs-skeleton-select" aria-hidden="true"></div>');
            }
        });

        $row.attr('aria-busy', 'true');
    }

    function hideTemplateMappingSkeleton() {
        const $row = $('#momcs-template-mapping-rows .momcs-template-mapping-row').first();
        if (!$row.length) return;
        $row.removeAttr('aria-busy');
        $row.find('.momcs-skeleton-select').remove();
        $row.find('.momcs-searchable-wrapper').removeClass('momcs-searchable-loading');
    }

    // Meta fields that should not appear in the mapping UI
    const HIDDEN_META_FIELDS = ['language_tag', 'marketplace_id'];
    
    // Special fields that are handled automatically by backend build_ functions
    const SPECIAL_BACKEND_FIELDS = [
        'externally_assigned_product_identifier',
        'condition_type',
        'bullet_point',
    ];

    const { ajaxUrl, nonces, tmNonces = {}, marketplaceId, channelUuid, strings, wcAttributes = {}, amazonCategoryNames = {}, wcCategoryNames = {}, wcCategoryHierarchy = {}, defaultMeta = {}, limits = {} } = cfg;

    // -------------------------------------------------------------------------
    // Utility helpers
    // -------------------------------------------------------------------------
    var _searchableSelectId = 0;

    function escapeAttr(str) {
        if (!str) return '';
        return String(str).replace(/&/g, '&amp;').replace(/"/g, '&quot;')
                          .replace(/</g, '&lt;').replace(/>/g, '&gt;');
    }

    function escapeHtml(str) {
        if (!str) return '';
        return String(str).replace(/&/g, '&amp;').replace(/</g, '&lt;')
                          .replace(/>/g, '&gt;').replace(/"/g, '&quot;');
    }

    // Logo markup for category chips — reuses existing CSS background-image classes
    var WC_LOGO_HTML = '<span class="momcs-schedule-card-logo momcs-schedule-card-logo--wc momcs-category-chip-icon" title="WooCommerce"></span>';
    var AMZ_LOGO_HTML = '<span class="momcs-schedule-card-logo momcs-schedule-card-logo--amazon momcs-category-chip-icon" title="Amazon"></span>';

    var TOOLTIP_INFO_SVG = '<svg class="momcs-tooltip-icon" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"></circle><path d="M12 16v-4"></path><path d="M12 8h.01"></path></svg>';

    // -------------------------------------------------------------------------
    // SearchableSelect – Reusable searchable dropdown component
    // Modeled on RegionDropdown from amazon-authorization.js
    // -------------------------------------------------------------------------
    function SearchableSelect(selectElement, options) {
        this.$select = $(selectElement);
        if (!this.$select.length || this.$select.data('searchableSelect')) return;
        this._id = ++_searchableSelectId;
        this.cfg = $.extend({
            placeholder: '-- Select --',
            noResultsText: 'No matching options',
            pinnedItems: [],
            width: '100%',
            renderItem: null,
            renderSelected: null,
        }, options || {});
        this.items = [];
        this.pinnedValues = {};
        this.selectedIndex = -1;
        this.isOpen = false;
        this.$wrapper = null;
        this.$input = null;
        this.$dropdown = null;
        this.$selectedDisplay = null;
        this._outsideClickBound = null;
        this.init();
    }

    SearchableSelect.prototype.init = function () {
        var self = this;

        // Build pinned value lookup
        this.cfg.pinnedItems.forEach(function (p) {
            self.pinnedValues[p.value] = p;
        });

        // Parse options from original <select>
        this.parseOptions();

        // Hide original select
        this.$select.hide();

        // Build custom UI
        this.$wrapper = $(
            '<div class="momcs-searchable-wrapper" style="width:' + this.cfg.width + '">' +
                '<svg class="momcs-searchable-search-icon" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">' +
                    '<circle cx="11" cy="11" r="8"></circle>' +
                    '<path d="m21 21-4.35-4.35"></path>' +
                '</svg>' +
                '<input type="text" class="momcs-searchable-input" placeholder="' + escapeAttr(this.cfg.placeholder) + '" autocomplete="off">' +
                '<div class="momcs-searchable-selected-display" style="display:none;"></div>' +
                '<svg class="momcs-searchable-chevron" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">' +
                    '<polyline points="6 9 12 15 18 9"></polyline>' +
                '</svg>' +
                '<div class="momcs-searchable-dropdown"></div>' +
            '</div>'
        );
        this.$select.after(this.$wrapper);
        this.$input = this.$wrapper.find('.momcs-searchable-input');
        this.$dropdown = this.$wrapper.find('.momcs-searchable-dropdown');
        this.$selectedDisplay = this.$wrapper.find('.momcs-searchable-selected-display');

        // If the select already has a value, show it
        var currentVal = this.$select.val();
        if (currentVal) {
            var match = this.findItem(currentVal);
            if (match) {
                this.showSelected(match.value, match.label);
            }
        }

        // Handle disabled state
        if (this.$select.prop('disabled')) {
            this.$wrapper.addClass('momcs-searchable-disabled');
        }

        // Store reference
        this.$select.data('searchableSelect', this);

        this.bindEvents();
    };

    SearchableSelect.prototype.parseOptions = function () {
        var self = this;
        this.items = [];

        this.$select.children().each(function () {
            var $el = $(this);
            if ($el.is('optgroup')) {
                var group = $el.attr('label') || '';
                $el.children('option').each(function () {
                    var $opt = $(this);
                    var val = $opt.val();
                    if (!val && val !== 0) return; // skip empty placeholder
                    self.items.push({
                        value: val,
                        label: $opt.text(),
                        group: group,
                        isPinned: !!self.pinnedValues[val],
                    });
                });
            } else if ($el.is('option')) {
                var val = $el.val();
                if (!val && val !== 0) return; // skip empty placeholder
                self.items.push({
                    value: val,
                    label: $el.text(),
                    group: '',
                    isPinned: !!self.pinnedValues[val],
                });
            }
        });
    };

    SearchableSelect.prototype.findItem = function (value) {
        for (var i = 0; i < this.items.length; i++) {
            if (this.items[i].value === value) return this.items[i];
        }
        return null;
    };

    SearchableSelect.prototype.bindEvents = function () {
        var self = this;

        this.$input.on('input', function () {
            self.filter($(this).val());
            self.showDropdown();
        });

        this.$input.on('focus', function () {
            self.filter($(this).val());
            self.showDropdown();
        });

        this.$input.on('keydown', function (e) {
            self.handleKeydown(e);
        });

        // Click on selected display to switch to search mode
        this.$selectedDisplay.on('click', function () {
            self.$selectedDisplay.hide();
            self.$input.show().val('').focus();
        });

        // Wrapper click focuses input
        this.$wrapper.on('click', function (e) {
            if (!$(e.target).closest('.momcs-searchable-dropdown').length &&
                !$(e.target).is('.momcs-searchable-input') &&
                !$(e.target).closest('.momcs-searchable-selected-display').length) {
                if (self.$selectedDisplay.is(':visible')) {
                    self.$selectedDisplay.hide();
                    self.$input.show().val('').focus();
                } else {
                    self.$input.focus();
                }
            }
        });

        // Click outside to close
        this._outsideClickBound = function (e) {
            if (!$(e.target).closest(self.$wrapper).length) {
                self.hideDropdown();
                // Restore selected display if a value is set
                var val = self.$select.val();
                if (val) {
                    var match = self.findItem(val);
                    if (match) {
                        self.showSelected(match.value, match.label);
                    }
                }
            }
        };
        $(document).on('click.searchableSelect' + this._id, this._outsideClickBound);

        // Item click
        this.$dropdown.on('click', '.momcs-searchable-result-item', function () {
            self.selectItem($(this).data('value'), $(this).data('label'));
        });
    };

    SearchableSelect.prototype.filter = function (query) {
        var q = (query || '').toLowerCase();
        var html = '';
        var count = 0;
        var lastGroup = null;
        var self = this;

        // Render pinned items first
        var hasPinned = false;
        this.items.forEach(function (item) {
            if (!item.isPinned) return;
            var pinCfg = self.pinnedValues[item.value] || {};
            var itemHtml = '';
            if (pinCfg.icon) {
                itemHtml += '<span class="momcs-searchable-pinned-icon">' + escapeHtml(pinCfg.icon) + '</span>';
            }
            itemHtml += escapeHtml(pinCfg.label || item.label);
            var cssClass = pinCfg.cssClass ? ' ' + pinCfg.cssClass : '';
            html += '<div class="momcs-searchable-result-item' + cssClass + (count === 0 ? ' is-focused' : '') + '" data-value="' + escapeAttr(item.value) + '" data-label="' + escapeAttr(pinCfg.label || item.label) + '" data-index="' + count + '">' + itemHtml + '</div>';
            count++;
            hasPinned = true;
        });

        if (hasPinned) {
            html += '<div class="momcs-searchable-divider"></div>';
        }

        // Render regular items grouped by optgroup
        this.items.forEach(function (item) {
            if (item.isPinned) return;
            if (q && item.label.toLowerCase().indexOf(q) === -1) return;

            if (item.group && item.group !== lastGroup) {
                html += '<div class="momcs-searchable-group-header">' + escapeHtml(item.group) + '</div>';
                lastGroup = item.group;
            } else if (!item.group && lastGroup !== '') {
                lastGroup = '';
            }

            var displayHtml = '';
            if (self.cfg.renderItem) {
                displayHtml = self.cfg.renderItem(item.value, item.label);
            } else {
                displayHtml = escapeHtml(item.label);
            }

            html += '<div class="momcs-searchable-result-item' + (count === 0 ? ' is-focused' : '') + '" data-value="' + escapeAttr(item.value) + '" data-label="' + escapeAttr(item.label) + '" data-index="' + count + '">' + displayHtml + '</div>';
            count++;
        });

        if (!count) {
            html = '<div class="momcs-searchable-no-results">' + escapeHtml(this.cfg.noResultsText) + '</div>';
        }

        this.$dropdown.html(html);
        this.selectedIndex = count > 0 ? 0 : -1;
    };

    SearchableSelect.prototype.selectItem = function (value, label) {
        this.$select.val(String(value)).trigger('change');
        this.showSelected(value, label);
        this.hideDropdown();
        this.clearError();
    };

    SearchableSelect.prototype.showSelected = function (value, label) {
        if (this.cfg.renderSelected) {
            this.$selectedDisplay.html(this.cfg.renderSelected(value, label)).show();
            this.$input.hide();
        } else {
            this.$input.val(label).show();
            this.$selectedDisplay.hide();
        }
    };

    SearchableSelect.prototype.showDropdown = function () {
        // Close all other open searchable dropdowns first
        $('.momcs-searchable-dropdown.is-open').not(this.$dropdown).removeClass('is-open');
        this.$dropdown.addClass('is-open');
        this.isOpen = true;
    };

    SearchableSelect.prototype.hideDropdown = function () {
        this.$dropdown.removeClass('is-open');
        this.isOpen = false;
        this.selectedIndex = -1;
    };

    SearchableSelect.prototype.handleKeydown = function (e) {
        var $items = this.$dropdown.find('.momcs-searchable-result-item');
        if (!$items.length) return;

        if (e.key === 'ArrowDown') {
            e.preventDefault();
            this.selectedIndex = Math.min(this.selectedIndex + 1, $items.length - 1);
            this.highlightItem($items);
        } else if (e.key === 'ArrowUp') {
            e.preventDefault();
            this.selectedIndex = Math.max(this.selectedIndex - 1, 0);
            this.highlightItem($items);
        } else if (e.key === 'Enter') {
            e.preventDefault();
            if (this.selectedIndex >= 0 && this.isOpen) {
                var $item = $items.eq(this.selectedIndex);
                this.selectItem($item.data('value'), $item.data('label'));
            }
        } else if (e.key === 'Escape') {
            this.hideDropdown();
            var val = this.$select.val();
            if (val) {
                var match = this.findItem(val);
                if (match) this.showSelected(match.value, match.label);
            }
        }
    };

    SearchableSelect.prototype.highlightItem = function ($items) {
        $items.removeClass('is-focused');
        var $current = $items.eq(this.selectedIndex).addClass('is-focused');
        if ($current.length) {
            $current[0].scrollIntoView({ block: 'nearest' });
        }
    };

    SearchableSelect.prototype.showError = function () {
        this.$wrapper.addClass('momcs-searchable-error');
    };

    SearchableSelect.prototype.clearError = function () {
        this.$wrapper.removeClass('momcs-searchable-error');
    };

    SearchableSelect.prototype.refresh = function () {
        var val = this.$select.val();
        this.parseOptions();
        if (val) {
            var match = this.findItem(val);
            if (match) {
                this.showSelected(match.value, match.label);
            } else {
                this.$input.val('').show();
                this.$selectedDisplay.hide();
            }
        }
    };

    SearchableSelect.prototype.destroy = function () {
        if (this.$wrapper) {
            this.$wrapper.remove();
        }
        this.$select.show().removeData('searchableSelect');
        if (this._outsideClickBound) {
            $(document).off('click.searchableSelect' + this._id, this._outsideClickBound);
        }
    };

    // -------------------------------------------------------------------------
    // Category chip helper
    // -------------------------------------------------------------------------
    function buildCategoryChipsHtml(wcName, amzName) {
        var html = '';
        if (wcName) {
            html += '<span class="momcs-category-chip momcs-category-chip-wc">' + WC_LOGO_HTML + ' ' + escapeHtml(wcName) + '</span>';
        }
        if (wcName && amzName) {
            html += '<span class="momcs-category-chip-arrow">&rArr;</span>';
        }
        if (amzName) {
            html += '<span class="momcs-category-chip momcs-category-chip-amazon">' + AMZ_LOGO_HTML + ' ' + escapeHtml(amzName) + '</span>';
        }
        return html;
    }

    // -------------------------------------------------------------------------
    // Initialize SearchableSelect on dynamically created field mapping rows
    // -------------------------------------------------------------------------
    function initFieldMappingSearchables() {
        // Destroy any existing instances
        $('#momcs-field-mapping-rows select').each(function () {
            var inst = $(this).data('searchableSelect');
            if (inst) inst.destroy();
        });

        // WC field mapping selects (with pinned "Add New Attribute")
        $('#momcs-field-mapping-rows .momcs-field-mapping-row-wc-field').each(function () {
            new SearchableSelect(this, {
                placeholder: strings.selectFieldPlaceholder || '-- Select Field --',
                noResultsText: 'No matching fields',
                pinnedItems: [{
                    value: 'ADD_NEW_ATTRIBUTE',
                    label: 'Add New Attribute',
                    icon: '+',
                    cssClass: 'momcs-searchable-pinned-add-new',
                }],
            });
        });

        // Enum selects
        $('#momcs-field-mapping-rows .momcs-enum-select').each(function () {
            if ($(this).data('searchableSelect')) return;
            new SearchableSelect(this, {
                placeholder: '-- Select Fixed Value --',
                noResultsText: 'No matching values',
            });
        });
    }

    // Store reference for template searchable
    var templateSearchable = null;

    // -------------------------------------------------------------------------
    // Multi-template toolbar state and helpers (plan-aware)
    // -------------------------------------------------------------------------
    const tmState = {
        templates: [],            // [{ uuid, label, updated_at }]
        selectedUuid: '',
        maxTemplates: parseInt(limits.max_templates || 1, 10),
        /** Free plan: true when get_unified_mapping returned saved category data (tm_list may be unavailable). */
        hasPrefillMapping: false,
        /** True after at least one successful unified save (keeps Add-template reset visible after UI clear). */
        mappingSaveCompletedOnce: false,
    };

    const isFreePlan = tmState.maxTemplates === 1;

    /**
     * Hide the initial loading placeholder shown before template list is fetched.
     */
    function hideTemplateMappingInitLoading() {
        const $el = $('#momcs-template-mapping-init-loading');
        if ($el.length) {
            $el.hide().attr('aria-hidden', 'true');
        }
    }

    /**
     * Show empty state (no templates); hide the mapping editor.
     */
    function showTemplateMappingEmptyStateUi() {
        $('#momcs-template-mapping-empty-state').show().removeAttr('hidden');
        $('#momcs-template-mapping-editor').hide().attr('hidden', 'hidden');
        $('.momcs-template-mapping-rows-toolbar').hide();
        $('#momcs-add-template-mapping-reset').hide();
    }

    /**
     * Show the mapping editor; hide empty state.
     */
    function showTemplateMappingEditorUi() {
        $('#momcs-template-mapping-empty-state').hide().attr('hidden', 'hidden');
        $('#momcs-template-mapping-editor').show().removeAttr('hidden');
    }

    /**
     * Premium: show template dropdown only when at least one template exists.
     */
    function updatePremiumTemplateDropdownVisibility() {
        if (isFreePlan) {
            $('#momcs-template-dropdown-container').hide();
            return;
        }
        const show = tmState.templates.length > 0;
        $('#momcs-template-dropdown-container').toggle(show);
        if (!show) {
            hideTemplateDropdownSkeleton();
        }
    }

    /**
     * Show "Add template" reset control after at least one template exists and editor is visible.
     */
    function updateAddTemplateResetVisibility() {
        const editorVisible = $('#momcs-template-mapping-editor').is(':visible');
        const show = editorVisible && (
            tmState.templates.length > 0 ||
            tmState.hasPrefillMapping ||
            tmState.mappingSaveCompletedOnce
        );
        $('.momcs-template-mapping-rows-toolbar').toggle(show);
        $('#momcs-add-template-mapping-reset').toggle(show);
    }

    /**
     * Find a template by WC + Amazon category ids (for post-save selection).
     *
     * @param {string} wcCat
     * @param {string} amzCat
     * @returns {object|undefined}
     */
    function findTemplateByCategoryPair(wcCat, amzCat) {
        const wc = String(wcCat || '');
        const amz = String(amzCat || '');
        if (!wc || !amz) {
            return undefined;
        }
        return tmState.templates.find(function (t) {
            const tw = t.category_mappings && t.category_mappings.wc_category ? String(t.category_mappings.wc_category) : '';
            const ta = t.selected_category || (t.category_mappings && t.category_mappings.amazon_category) || '';
            return tw === wc && String(ta) === amz;
        });
    }

    function tooltipIfDisabled($el) {
        if ($el.is(':disabled')) {
            $el.attr('title', strings.upgradeTooltip || 'Available in Premium');
            $el.attr('aria-disabled', 'true');
        } else {
            $el.removeAttr('title');
            $el.removeAttr('aria-disabled');
        }
    }

    function applyPlanGating() {
        const count = tmState.templates.length;
        const atLimit = count >= tmState.maxTemplates;

        const $add = $('#momcs-tm-add');
        const $saveAs = $('#momcs-tm-save-as');
        const $clone = $('#momcs-tm-clone');
        const $deleteBtn = $('#momcs-tm-delete');
        const $save = $('#momcs-tm-save');

        if (isFreePlan) {
            // Free: one template only – hide Add/Create template; disable other premium controls.
            $add.prop('disabled', true).hide();
            $saveAs.prop('disabled', true).hide();
            $clone.prop('disabled', true).hide();
            $deleteBtn.prop('disabled', true).hide();
            // Hide toolbar Save in free (saving handled by mapping Save/Next)
            $save.prop('disabled', true).hide();
        } else {
            // Premium: enable unless at limit or no selection
            $add.prop('disabled', atLimit).show();
            $saveAs.prop('disabled', !tmState.selectedUuid || atLimit).show();
            $clone.prop('disabled', !tmState.selectedUuid || atLimit).show();
            $deleteBtn.prop('disabled', !tmState.selectedUuid).show();
            // Premium: remove Save from UI entirely
            $save.prop('disabled', true).hide();
        }

        [$add, $saveAs, $clone, $deleteBtn, $save].forEach(tooltipIfDisabled);
    }

    function buildTemplateOptionLabel(t) {
        const wcId = (t.category_mappings && t.category_mappings.wc_category) ? String(t.category_mappings.wc_category) : '';
        const amzId = t.selected_category || (t.category_mappings && t.category_mappings.amazon_category) || '';
        const wcPretty = wcId && wcCategoryNames[wcId] ? wcCategoryNames[wcId] : (wcId ? ('Category #' + wcId) : (t.label || ''));
        const amzPretty = amzId && amazonCategoryNames[amzId] ? amazonCategoryNames[amzId] : (amzId || '');
        if (wcPretty && amzPretty) return wcPretty + ' => ' + amzPretty;
        if (wcPretty) return wcPretty;
        if (t.label) return t.label;
        return t.uuid || 'Template';
    }

    function populateTemplateSelect() {
        const $sel = $('#momcs-template-select');
        const prev = $sel.val();
        const opts = ['<option value="">' + (strings.placeholders && strings.placeholders.chooseTemplate || '-- Select Template --') + '</option>'];
        // Premium: list saved templates using WC => Amazon label
        tmState.templates.forEach(t => {
            const pretty = buildTemplateOptionLabel(t);
            const sel = (t.uuid === tmState.selectedUuid) ? ' selected' : '';
            opts.push('<option value="' + t.uuid + '"' + sel + '>' + pretty + '</option>');
        });
        $sel.html(opts.join(''));
        if (prev && !$sel.val()) { $sel.val(prev); }
        // Refresh SearchableSelect if initialized
        if (templateSearchable) {
            templateSearchable.refresh();
        }
        applyPlanGating();
        updatePremiumTemplateDropdownVisibility();
        updateAddTemplateResetVisibility();
    }

    /**
     * Fetch template list for the channel.
     *
     * @param {Object} [opts]
     * @param {function():void} [opts.beforePopulate] Run after tmState.templates is set, before populateTemplateSelect (e.g. set tmState.selectedUuid).
     * @return {JQuery.jqXHR}
     */
    function fetchTemplatesList(opts) {
        opts = opts || {};
        return $.post(ajaxUrl, {
            action: 'momcs_tm_list',
            channel_id: channelUuid,
            nonce: tmNonces.main
        }).done(function(resp){
            if (resp && resp.success && resp.data && Array.isArray(resp.data.templates)) {
                tmState.templates = resp.data.templates;
            } else {
                tmState.templates = [];
            }
            if (typeof opts.beforePopulate === 'function') {
                opts.beforePopulate();
            }
            populateTemplateSelect();
            hideTemplateDropdownSkeleton();
        }).fail(function(){
            // Graceful fallback if backend not ready yet
            tmState.templates = tmState.templates || [];
            if (typeof opts.beforePopulate === 'function') {
                opts.beforePopulate();
            }
            populateTemplateSelect();
            hideTemplateDropdownSkeleton();
        });
    }

    function currentTemplate() {
        return tmState.templates.find(t => t.uuid === tmState.selectedUuid) || null;
    }

    function getConfigFromUI() {
        // Collect mapping and categories from existing UI
        const wcCat = $('.momcs-template-mapping-wc-category').val();
        const amzCat = $('.momcs-template-mapping-amazon-category').val();
        const collected = collectAllFieldMappings();
        return {
            label: ($('#momcs-template-label').val() || '').trim(),
            selected_category: amzCat || '',
            category_mappings: { wc_category: wcCat ? String(wcCat) : '' },
            field_mappings: collected.fieldMappings || {},
            updated_at: new Date().toISOString(),
        };
    }

    function selectTemplate(uuid) {
        tmState.selectedUuid = uuid || '';
        const t = currentTemplate();
        applyPlanGating();

        // In premium, if no template is selected, keep the UI empty/hidden
        if (!isFreePlan && !tmState.selectedUuid) {
            hideTemplateMappingSkeleton();
            // Clear categories and hide mapping area
            $('.momcs-template-mapping-wc-category').val('');
            syncSearchableDisplay($('.momcs-template-mapping-wc-category'));
            $('.momcs-template-mapping-amazon-category').val('');
            syncSearchableDisplay($('.momcs-template-mapping-amazon-category'));
            $('#momcs-required-fields-container').hide();
            $('#momcs-field-mapping-rows').empty();
            $('#momcs-template-mapping-save').hide();
            return;
        }

        // Show shimmer on category dropdowns while loading
        showTemplateMappingSkeleton();

        // Ask backend for mapping for this template (forward-compatible)
        $.post(ajaxUrl, {
            action: 'momcs_sync_get_unified_mapping',
            marketplace: 'amazon',
            channel_id: channelUuid,
            template_uuid: tmState.selectedUuid,
            security: nonces.getMapping,
        }).done(function(resp){
            hideTemplateMappingSkeleton();
            // We rely on existing flow to hydrate category & fields via subsequent schema fetch
            // Trigger change if selected_category is present
            if (resp && resp.success && resp.data && resp.data.selected_category) {
                $('.momcs-template-mapping-amazon-category').val(resp.data.selected_category).trigger('change');
                syncSearchableDisplay($('.momcs-template-mapping-amazon-category'));
            }
            if (resp && resp.success && resp.data && resp.data.category_mappings && resp.data.category_mappings.wc_category) {
                $('.momcs-template-mapping-wc-category').val(resp.data.category_mappings.wc_category);
                syncSearchableDisplay($('.momcs-template-mapping-wc-category'));
            }
            // Reveal container now that we have a template context
            $('#momcs-required-fields-container').show();
        }).fail(function(){
            hideTemplateMappingSkeleton();
        });
    }

    function createTemplate(label, config) {
        return $.post(ajaxUrl, {
            action: 'momcs_tm_create',
            channel_id: channelUuid,
            label: label,
            config: JSON.stringify(config || {}),
            nonce: tmNonces.main
        });
    }

    function updateTemplate(uuid, config) {
        return $.post(ajaxUrl, {
            action: 'momcs_tm_update',
            channel_id: channelUuid,
            template_uuid: uuid,
            config: JSON.stringify(config || {}),
            nonce: tmNonces.main
        });
    }

    function cloneTemplate(uuid, newLabel) {
        return $.post(ajaxUrl, {
            action: 'momcs_tm_clone',
            channel_id: channelUuid,
            template_uuid: uuid,
            label: newLabel,
            nonce: tmNonces.main
        });
    }

    function deleteTemplate(uuid) {
        return $.post(ajaxUrl, {
            action: 'momcs_tm_delete',
            channel_id: channelUuid,
            template_uuid: uuid,
            nonce: tmNonces.main
        });
    }

    /**
     * Check if a field should be hidden from mapping UI
     * @param {string} fieldName Field name to check
     * @returns {boolean} True if field should be hidden
     */
    function isFieldHidden(fieldName) {
        // Check if any hidden meta field appears anywhere in the field name
        const isMetaHidden = HIDDEN_META_FIELDS.some(hiddenField => fieldName.includes(hiddenField));
        
        // Check if it's a special backend field that should be hidden from mapping
        const isSpecialBackendField = SPECIAL_BACKEND_FIELDS.some(specialField => {
            return fieldName === specialField || fieldName.startsWith(specialField + '[');
        });
        
        return isMetaHidden || isSpecialBackendField;
    }

    /**
     * Check if a WooCommerce category has children
     * @param {string|number} categoryId Category ID to check
     * @returns {boolean} True if category has children
     */
    function hasChildCategories(categoryId) {
        return wcCategoryHierarchy && wcCategoryHierarchy[categoryId] && Object.keys(wcCategoryHierarchy[categoryId]).length > 0;
    }

    /**
     * Get child categories for a given parent category
     * @param {string|number} parentId Parent category ID
     * @returns {Array} Array of child category objects
     */
    function getChildCategories(parentId) {
        if (!wcCategoryHierarchy || !wcCategoryHierarchy[parentId]) {
            return [];
        }
        return Object.values(wcCategoryHierarchy[parentId]);
    }

    /**
     * Show parent category warning with child category preview
     * @param {string|number} categoryId Selected parent category ID
     */
    function showParentCategoryWarning(categoryId) {
        const children = getChildCategories(categoryId);
        if (children.length === 0) {
            hideParentCategoryWarning();
            return;
        }

        const categoryName = wcCategoryNames[categoryId] || 'Category #' + categoryId;
        const $warning = $('#momcs-parent-category-warning');
        const $message = $('#momcs-warning-message');
        const $preview = $('#momcs-child-preview');

        // Set basic warning message
        $message.html(`You selected the parent category "<strong>${categoryName}</strong>". This template will apply to all products in this category and its ${children.length} subcategories. Consider mapping individual subcategories for better precision.`);

        // Create basic child category preview
        const previewHtml = children.slice(0, 8).map(child => 
            `<span class="momcs-child-category-tag">${child.name}</span>`
        ).join('');
        
        const moreCount = children.length - 8;
        const moreText = moreCount > 0 ? ` <span class="momcs-more-count">+${moreCount} more</span>` : '';
        
        $preview.html('<strong>Affected subcategories:</strong><br>' + previewHtml + moreText);

        $warning.show();

        // Perform enhanced validation if Amazon category is also selected
        const amzCategory = $('.momcs-template-mapping-amazon-category').val();
        if (amzCategory) {
            validateParentMapping(categoryId, amzCategory);
        }
    }

    /**
     * Validate parent category mapping against Amazon category for conflicts
     * @param {string|number} wcCategoryId WooCommerce category ID
     * @param {string} amazonCategory Amazon category
     */
    function validateParentMapping(wcCategoryId, amazonCategory) {
        $.post(ajaxUrl, {
            action: 'momcs_sync_validate_parent_mapping',
            marketplace: 'amazon',
            channel_id: channelUuid,
            wc_category: wcCategoryId,
            amazon_category: amazonCategory,
            security: nonces.validateParent
        }).done(function(resp) {
            if (resp && resp.success && resp.data) {
                updateParentWarningWithValidation(resp.data);
            }
        }).fail(function() {
            // Validation failed, but keep basic warning
            console.log('Parent mapping validation failed, keeping basic warning');
        });
    }

    /**
     * Update parent warning with detailed validation information
     * @param {Object} validation Validation data from backend
     */
    function updateParentWarningWithValidation(validation) {
        const $warning = $('#momcs-parent-category-warning');
        const $message = $('#momcs-warning-message');
        const $preview = $('#momcs-child-preview');

        // Update warning severity
        const severityClass = validation.severity === 'warning' ? 'notice-warning' : 'notice-info';
        $warning.find('.notice').removeClass('notice-info notice-warning').addClass(severityClass);

        // Add recommendations if any
        if (validation.recommendations && validation.recommendations.length > 0) {
            const recommendationsHtml = validation.recommendations.map(rec => 
                `<div class="momcs-recommendation">• ${rec}</div>`
            ).join('');
            $message.append('<div class="momcs-recommendations" style="margin-top: 10px;"><strong>Recommendations:</strong><br>' + recommendationsHtml + '</div>');
        }

        // Show conflicts if any
        if (validation.conflicts && validation.conflicts.length > 0) {
            const conflictsHtml = validation.conflicts.map(conflict => 
                `<span class="momcs-conflict-tag">${conflict.category_name} → ${conflict.amazon_category}</span>`
            ).join('');
            $preview.append('<br><strong>Existing child templates that will be overridden:</strong><br>' + conflictsHtml);
        }
    }

    /**
     * Hide parent category warning
     */
    function hideParentCategoryWarning() {
        $('#momcs-parent-category-warning').hide();
    }

    /**
     * Handle WooCommerce category change with parent category logic
     */
    function handleWcCategoryChange() {
        const selectedCategoryId = $('.momcs-template-mapping-wc-category').val();
        
        if (!selectedCategoryId) {
            hideParentCategoryWarning();
            return;
        }

        // Check if selected category is a parent category
        if (hasChildCategories(selectedCategoryId)) {
            showParentCategoryWarning(selectedCategoryId);
        } else {
            hideParentCategoryWarning();
        }
    }

    // Channel Defaults (marketplace_id, language_tag) are managed by Default_Meta_Service.
    // No UI injection needed; values are used in AJAX requests via cfg.defaultMeta.

    $(function () {
        // Initialize SearchableSelect on static dropdowns
        new SearchableSelect('.momcs-template-mapping-wc-category', {
            placeholder: '-- Select Category --',
            noResultsText: 'No matching categories',
        });

        new SearchableSelect('.momcs-template-mapping-amazon-category', {
            placeholder: '-- Select Category --',
            noResultsText: 'No matching categories',
        });

        // Template select (premium) – with chip rendering
        templateSearchable = new SearchableSelect('#momcs-template-select', {
            placeholder: strings.placeholders && strings.placeholders.chooseTemplate || '-- Select Template --',
            noResultsText: 'No matching templates',
            renderItem: function (value, label) {
                var t = tmState.templates.find(function (t) { return t.uuid === value; });
                if (!t) return escapeHtml(label);
                var wcId = (t.category_mappings && t.category_mappings.wc_category) ? String(t.category_mappings.wc_category) : '';
                var amzId = t.selected_category || (t.category_mappings && t.category_mappings.amazon_category) || '';
                var wcPretty = wcId && wcCategoryNames[wcId] ? wcCategoryNames[wcId] : '';
                var amzPretty = amzId && amazonCategoryNames[amzId] ? amazonCategoryNames[amzId] : '';
                if (wcPretty || amzPretty) return buildCategoryChipsHtml(wcPretty, amzPretty);
                return escapeHtml(label);
            },
            renderSelected: function (value, label) {
                var t = tmState.templates.find(function (t) { return t.uuid === value; });
                if (!t) return escapeHtml(label);
                var wcId = (t.category_mappings && t.category_mappings.wc_category) ? String(t.category_mappings.wc_category) : '';
                var amzId = t.selected_category || (t.category_mappings && t.category_mappings.amazon_category) || '';
                var wcPretty = wcId && wcCategoryNames[wcId] ? wcCategoryNames[wcId] : '';
                var amzPretty = amzId && amazonCategoryNames[amzId] ? amazonCategoryNames[amzId] : '';
                if (wcPretty || amzPretty) return buildCategoryChipsHtml(wcPretty, amzPretty);
                return escapeHtml(label);
            },
        });

        // Default mapping selects (SKU, Item Name, Brand, Price, Quantity)
        $('.momcs-mapping-select').each(function () {
            new SearchableSelect(this, {
                placeholder: 'Select Field...',
                noResultsText: 'No matching fields',
            });
        });

        /**
         * After template list (and optional free-plan prefill) load, show empty state or editor.
         */
        function completeInitialTemplateMappingLayout() {
            hideTemplateMappingInitLoading();
            hideTemplateMappingSkeleton();
            hideTemplateDropdownSkeleton();
            const hasTemplates = tmState.templates.length > 0;
            const showEmpty = isFreePlan
                ? (!hasTemplates && !tmState.hasPrefillMapping)
                : !hasTemplates;
            if (showEmpty) {
                showTemplateMappingEmptyStateUi();
            } else {
                showTemplateMappingEditorUi();
                updatePremiumTemplateDropdownVisibility();
                updateAddTemplateResetVisibility();
                applyPlanGating();
            }
        }

        if (isFreePlan) {
            showTemplateMappingSkeleton();
            $.when(fetchTemplatesList(), loadExistingWcCategory()).always(function () {
                completeInitialTemplateMappingLayout();
            });
        } else {
            $('#momcs-required-fields-container').hide();
            $('#momcs-field-mapping-rows').empty();
            $('#momcs-template-mapping-save').hide();
            showTemplateDropdownSkeleton();
            fetchTemplatesList().always(function () {
                completeInitialTemplateMappingLayout();
            });
        }
    });

    // Helper: sync SearchableSelect display after programmatic .val() change
    function syncSearchableDisplay($select) {
        var inst = $select.data('searchableSelect');
        if (inst) {
            var val = $select.val();
            if (val) {
                var match = inst.findItem(val);
                if (match) inst.showSelected(match.value, match.label);
            } else {
                inst.$input.val('').show();
                inst.$selectedDisplay.hide();
            }
        }
    }

    /**
     * Clear category selects, field rows, and template selection (premium add-template / reset).
     */
    function resetTemplateMappingForm() {
        tmState.selectedUuid = '';
        tmState.hasPrefillMapping = false;
        $('#momcs-template-select').val('');
        syncSearchableDisplay($('#momcs-template-select'));
        $('.momcs-template-mapping-wc-category').val('');
        syncSearchableDisplay($('.momcs-template-mapping-wc-category'));
        $('.momcs-template-mapping-amazon-category').val('');
        syncSearchableDisplay($('.momcs-template-mapping-amazon-category'));
        $('#momcs-field-mapping-rows').empty();
        $('#momcs-required-fields-container').hide();
        $('#momcs-template-mapping-save').hide();
        hideParentCategoryWarning();
        applyPlanGating();
        updateAddTemplateResetVisibility();
    }

    // Premium template dropdown change handler
    $(document).on('change', '#momcs-template-select', function(){
        const uuid = $(this).val();
        if (!uuid) {
            // Clear and hide mapping area until a template is chosen
            hideTemplateMappingSkeleton();
            $('.momcs-template-mapping-wc-category').val('');
            syncSearchableDisplay($('.momcs-template-mapping-wc-category'));
            $('.momcs-template-mapping-amazon-category').val('');
            syncSearchableDisplay($('.momcs-template-mapping-amazon-category'));
            $('#momcs-required-fields-container').hide();
            $('#momcs-field-mapping-rows').empty();
            $('#momcs-template-mapping-save').hide();
            return;
        }
        // Show shimmer on category dropdowns while loading template mapping
        showTemplateMappingSkeleton();
        // Load mapping for selected template UUID, then hydrate categories -> schema -> fields
        $.post(ajaxUrl, {
            action: 'momcs_sync_get_unified_mapping',
            marketplace: 'amazon',
            channel_id: channelUuid,
            template_uuid: uuid,
            security: nonces.getMapping,
        }).done(function(resp){
            hideTemplateMappingSkeleton();
            if (resp && resp.success && resp.data) {
                const cfg = resp.data;
                if (cfg.category_mappings && cfg.category_mappings.wc_category) {
                    $('.momcs-template-mapping-wc-category').val(cfg.category_mappings.wc_category);
                    syncSearchableDisplay($('.momcs-template-mapping-wc-category'));
                }
                const amzCat = cfg.selected_category || (cfg.category_mappings && cfg.category_mappings.amazon_category) || '';
                if (amzCat) {
                    $('.momcs-template-mapping-amazon-category').val(amzCat).trigger('change');
                    syncSearchableDisplay($('.momcs-template-mapping-amazon-category'));
                } else {
                    // Show container even if category missing; user can select
                    $('#momcs-required-fields-container').show();
                }
            }
        }).fail(function(){
            hideTemplateMappingSkeleton();
        });
    });

    $(document).on('click', '#momcs-tm-add', function(e){
        e.preventDefault();
        if ($(this).is(':disabled')) return;
        // Premium: Add Template just resets UI; no DB write and no label flow
        if (!isFreePlan) {
            resetTemplateMappingForm();
            return;
        }
        // Free (should rarely be visible): no-op or legacy behavior
    });

    $(document).on('click', '#momcs-add-template-mapping-start', function (e) {
        e.preventDefault();
        showTemplateMappingEditorUi();
        updatePremiumTemplateDropdownVisibility();
        updateAddTemplateResetVisibility();
    });

    $(document).on('click', '#momcs-add-template-mapping-reset', function (e) {
        e.preventDefault();
        resetTemplateMappingForm();
    });

    $(document).on('click', '#momcs-tm-save', function(e){
        e.preventDefault();
        // Remove Save functionality in premium; use Save As / existing Save & Next
        if (!isFreePlan) { return; }
        const uuid = tmState.selectedUuid;
        const cfgObj = getConfigFromUI();
        if (!uuid) {
            // If nothing selected, create instead
            $('#momcs-tm-add').trigger('click');
            return;
        }
        updateTemplate(uuid, cfgObj).done(function(resp){
            if (resp && resp.success) {
                fetchTemplatesList();
                // Optionally trigger the existing Save Mapping flow
                $('#momcs-template-mapping-save:visible').trigger('click');
            } else {
                alert((resp && resp.data && resp.data.message) || 'Failed to save template');
            }
        }).fail(function(){ alert('Failed to save template'); });
    });

    $(document).on('click', '#momcs-tm-save-as', function(e){
        e.preventDefault();
        if ($(this).is(':disabled')) return;
        const base = getConfigFromUI();
        const label = base.label ? base.label + ' (Copy)' : 'Template (Copy)';
        createTemplate(label, base).done(function(resp){
            if (resp && resp.success && resp.data && resp.data.uuid) {
                fetchTemplatesList().done(function(){
                    tmState.selectedUuid = resp.data.uuid;
                    populateTemplateSelect();
                    applyPlanGating();
                });
            } else {
                alert((resp && resp.data && resp.data.message) || 'Failed to save as new');
            }
        }).fail(function(){ alert('Failed to save as new'); });
    });

    $(document).on('click', '#momcs-tm-clone', function(e){
        e.preventDefault();
        if ($(this).is(':disabled')) return;
        const uuid = tmState.selectedUuid;
        if (!uuid) return;
        const label = ($('#momcs-template-label').val() || '').trim() || 'Template';
        cloneTemplate(uuid, label + ' (Clone)').done(function(resp){
            if (resp && resp.success && resp.data && resp.data.uuid) {
                fetchTemplatesList().done(function(){
                    tmState.selectedUuid = resp.data.uuid;
                    populateTemplateSelect();
                    applyPlanGating();
                });
            } else {
                alert((resp && resp.data && resp.data.message) || 'Failed to clone');
            }
        }).fail(function(){ alert('Failed to clone'); });
    });

    $(document).on('click', '#momcs-tm-delete', function(e){
        e.preventDefault();
        if ($(this).is(':disabled')) return;
        const uuid = tmState.selectedUuid;
        if (!uuid) return;
        if (!confirm('Delete this template?')) return;
        deleteTemplate(uuid).done(function(resp){
            if (resp && resp.success) {
                // Remove locally to keep UI responsive
                tmState.templates = tmState.templates.filter(t => t.uuid !== uuid);
                tmState.selectedUuid = '';
                populateTemplateSelect();
                applyPlanGating();
                if (tmState.templates.length === 0) {
                    resetTemplateMappingForm();
                    showTemplateMappingEmptyStateUi();
                }
            } else {
                alert((resp && resp.data && resp.data.message) || 'Failed to delete');
            }
        }).fail(function(){ alert('Failed to delete'); });
    });

    /**
     * Load and populate existing WooCommerce category from the database.
     *
     * @return {JQuery.jqXHR}
     */
    function loadExistingWcCategory() {
        return $.post(ajaxUrl, {
            action: 'momcs_sync_get_unified_mapping',
            marketplace: 'amazon',
            channel_id: channelUuid,
            security: nonces.getMapping,
        }).done(function (response) {
            tmState.hasPrefillMapping = false;
            if (response.success && response.data) {
                const data = response.data;
                if (
                    (data.category_mappings && data.category_mappings.wc_category) ||
                    (data.category_mappings && data.category_mappings.amazon_category) ||
                    data.selected_category
                ) {
                    tmState.hasPrefillMapping = true;
                }
                
                // Populate WooCommerce category dropdown
                if (data.category_mappings && data.category_mappings.wc_category) {
                    $('.momcs-template-mapping-wc-category').val(data.category_mappings.wc_category);
                    syncSearchableDisplay($('.momcs-template-mapping-wc-category'));
                    console.log('[MO Debug] Set WC category to:', data.category_mappings.wc_category);
                }
                // Populate Amazon category dropdown if present
                if (data.category_mappings && data.category_mappings.amazon_category) {
                    $('.momcs-template-mapping-amazon-category').val(data.category_mappings.amazon_category);
                    syncSearchableDisplay($('.momcs-template-mapping-amazon-category'));
                    console.log('[MO Debug] Set Amazon category to:', data.category_mappings.amazon_category);
                } else if (data.selected_category) {
                    $('.momcs-template-mapping-amazon-category').val(data.selected_category);
                    syncSearchableDisplay($('.momcs-template-mapping-amazon-category'));
                    console.log('[MO Debug] Set Amazon category (selected_category) to:', data.selected_category);
                }

                $(document).trigger('momcs_template_prefill_done');
            }
            hideTemplateMappingSkeleton();
        }).fail(function(xhr, status, error) {
            console.log('[MO Debug] Failed to load WC category mapping:', error);
            hideTemplateMappingSkeleton();
        });
    }

    // Debug helper – safely parse JSON strings.
    const safeParse = (val, fallback = {}) => {
        if (typeof val !== 'string') return val;
        try { return JSON.parse(val); } catch (_) { return fallback; }
    };

    /**
     * Build <option> list from WC attributes for dropdown, grouped by category.
     * Groups: Product Fields, Global Attributes, Custom Fields.
     * @param {string} selected currently selected value
     * @returns {string}
     */
    const buildAttributeOptions = (selected = '') => {
        const placeholder = strings.selectFieldPlaceholder || '-- Select Field --';
        const groupLabels = {
            product: 'Product Fields',
            global: 'Global Attributes',
            custom: 'Custom Fields',
        };

        // Known core WC product fields used by mapping
        const productFieldKeys = new Set([
            'post_title', 'post_content', 'post_excerpt',
            '_thumbnail_id', '_sku', '_momcs_amz_asin', '_regular_price', '_sale_price',
            '_weight', '_length', '_width', '_height', '_stock', '_stock_status',
            '_visibility', 'product_cat', 'product_tag',
            // Commonly used field in our mapping defaults
            'product_brand'
        ]);

        // Prepare grouped buckets
        const buckets = { product: [], global: [], custom: [] };

        // Helper to push option HTML
        const pushOption = (arr, key, label) => {
            const sel = key === selected ? ' selected' : '';
            arr.push('<option value="' + key + '"' + sel + '>' + label + '</option>');
        };

        // Classify attributes into buckets
        $.each(wcAttributes || {}, function (key, label) {
            if (!key) return;
            if (key.indexOf('pa_') === 0) {
                pushOption(buckets.global, key, label);
            } else if (productFieldKeys.has(key)) {
                pushOption(buckets.product, key, label);
            } else {
                pushOption(buckets.custom, key, label);
            }
        });

        // If the current selection is not present (e.g., custom/third-party field), ensure it appears
        const allHtml = buckets.product.concat(buckets.global, buckets.custom).join('');
        const selectedExists = selected && allHtml.indexOf('value="' + selected + '"') !== -1;
        if (selected && !selectedExists && selected !== 'ADD_NEW_ATTRIBUTE') {
            const inferredBucket = (selected.indexOf('pa_') === 0)
                ? 'global'
                : (productFieldKeys.has(selected) || selected.charAt(0) === '_')
                    ? 'product'
                    : 'custom';
            const inferredLabel = wcAttributes && wcAttributes[selected]
                ? wcAttributes[selected]
                : selected.replace(/^_+/, '').replace(/_/g, ' ').replace(/\b\w/g, c => c.toUpperCase());
            pushOption(buckets[inferredBucket], selected, inferredLabel + '');
        }

        // Build final HTML with optgroups
        let html = '<option value="">' + placeholder + '</option>';

        const buildGroup = (label, options) => {
            if (!options.length) return '';
            return '<optgroup label="' + label + '">' + options.join('') + '</optgroup>';
        };

        html += buildGroup(groupLabels.product, buckets.product);
        html += buildGroup(groupLabels.global, buckets.global);
        html += buildGroup(groupLabels.custom, buckets.custom);

        // Add "Add New Attribute" option at the end
        const newAttrSelected = selected === 'ADD_NEW_ATTRIBUTE' ? ' selected' : '';
        html += '<option value="ADD_NEW_ATTRIBUTE"' + newAttrSelected + '>-- Add New Attribute --</option>';

        return html;
    };

    /**
     * Helper to find saved value in mapping object – extracted from original inline code.
     * @param {Object|string} map
     * @param {string} dottedKey
     * @returns {string|undefined}
     */
    const getSavedValue = (map, fieldKey) => {
        map = safeParse(map, {});
        
        // First check if the field exists directly
        if (map.hasOwnProperty(fieldKey)) {
            const value = map[fieldKey];
            // If it's in {value, entity} format, return the value part
            if (typeof value === 'object' && value !== null && value.hasOwnProperty('value')) {
                return value.value;
            }
            return value;
        }

        // Sanitized lookup – strip array notation and trailing ".value".
        const baseKey = fieldKey.replace(/\[\].*$/, '').replace(/\.value$/, '');
        if (map.hasOwnProperty(baseKey)) {
            const value = map[baseKey];
            // If it's in {value, entity} format, return the value part
            if (typeof value === 'object' && value !== null && value.hasOwnProperty('value')) {
                return value.value;
            }
            return value;
        }

        // Legacy nested-object support.
        const match = fieldKey.match(/^([^\[]+)(?:\[\]\.)?(.+)$/);
        if (match) {
            const [, base, prop] = match;
            if (map[base] && typeof map[base] === 'object') {
                return map[base][prop];
            }
        }
        return undefined;
    };

    /**
     * Build a WooCommerce-safe attribute slug (without pa_) for "Add New Attribute" mappings.
     * Truncates to 28 chars then trims hyphens again so substring() never leaves a trailing dash.
     *
     * @param {string} fieldName Amazon field key or path with underscores (dots already converted).
     * @returns {string}
     */
    function buildNewAttributeSlugFromFieldName(fieldName) {
        const base = String(fieldName || '').replace(/\./g, '_');
        let attributeSlug = 'momcs-' + base.replace(/_/g, '-').toLowerCase().replace(/[^a-z0-9-]+/g, '-').replace(/^-+|-+$/g, '');
        if (attributeSlug.length > 28) {
            attributeSlug = attributeSlug.substring(0, 28);
        }
        attributeSlug = attributeSlug.replace(/^-+|-+$/g, '');
        return attributeSlug;
    }

    /**
     * Universal field mapping collection function with multi-level nesting support.
     * Handles all field types: multi-level hierarchical, flat, simple, ADD_NEW_ATTRIBUTE.
     * 
     * @returns {Object} {fieldMappings: {}, newAttributes: {}, errors: []}
     */
    function collectAllFieldMappings() {
        console.log('[MO Debug] Starting universal field collection with multi-level support');
        
        const fieldMappings = {};
        const newAttributes = {};
        const errors = [];
        
        // Process all nested fields using the new data-field-path approach
        $('#momcs-field-mapping-rows .momcs-child-field-row').each(function () {
            const fieldPath = $(this).data('field-path');
            
            if (!fieldPath) {
                console.warn('[MO Debug] Missing field-path data attribute');
                return; // Skip this iteration
            }
            
            let chosenValue = '';
            
            // Get value from nested field selects
            $(this).find('.momcs-nested-field-select').each(function () {
                const val = $(this).val();
                if (val) { chosenValue = val; }
            });
            
            // Handle ADD_NEW_ATTRIBUTE for nested fields
            if (chosenValue === 'ADD_NEW_ATTRIBUTE') {
                const amazonTitle = $(this).find('.momcs-nested-field-select').data('amazon-title') || fieldPath.split('.').pop();
                const fieldName = fieldPath.replace(/\./g, '_');
                const attributeSlug = buildNewAttributeSlugFromFieldName(fieldName);
                
                newAttributes[fieldPath] = {
                    name: amazonTitle,
                    slug: attributeSlug
                };
                
                chosenValue = 'pa_' + attributeSlug;
                console.log('[MO Debug] Created nested attribute:', fieldPath, attributeSlug);
            }
            
            // Store the value in the nested structure using field path
            if (chosenValue) {
                setNestedValue(fieldMappings, fieldPath, chosenValue);
                console.log('[MO Debug] Stored nested mapping:', fieldPath, chosenValue);
            }
        });
        
        // Process simple/flat fields (non-hierarchical)
        $('#momcs-field-mapping-rows .momcs-field-mapping-row').each(function () {
            // Skip child field rows (already processed above)
            if ($(this).hasClass('momcs-child-field-row')) return;
            
            const field = $(this).data('field');
            if (!field) {
                console.warn('[MO Debug] Missing field data attribute');
                return; // Skip this iteration
            }
            
            let wcField = '';
            let enumValue = '';
            
            // Get values from different types of selects
            $(this).find('.momcs-field-mapping-row-wc-field').each(function () {
                const val = $(this).val();
                if (val) { wcField = val; }
            });
            
            $(this).find('.momcs-enum-select').each(function () {
                const val = $(this).val();
                if (val) { enumValue = val; }
            });
            
            let chosenValue = wcField || enumValue;
            
            // Handle ADD_NEW_ATTRIBUTE for simple fields
            if (wcField === 'ADD_NEW_ATTRIBUTE') {
                const amazonTitle = $(this).find('.momcs-field-mapping-row-wc-field').data('amazon-title') || field;
                const fieldName = field.replace(/\[\]\..*$/, '');
                const attributeSlug = buildNewAttributeSlugFromFieldName(fieldName);
                
                newAttributes[field] = {
                    name: amazonTitle,
                    slug: attributeSlug
                };
                
                chosenValue = 'pa_' + attributeSlug;
                console.log('[MO Debug] Created simple attribute:', field, attributeSlug);
            }
            
            // Store the simple field mapping
            if (chosenValue) {
                fieldMappings[field] = chosenValue;
                console.log('[MO Debug] Stored simple mapping:', field, chosenValue);
            }
        });
        
        console.log('[MO Debug] Universal collection complete:', {
            fieldMappings: fieldMappings,
            newAttributes: newAttributes,
            errors: errors
        });
        
        return {
            fieldMappings: fieldMappings,
            newAttributes: newAttributes,
            errors: errors
        };
    }

    /**
     * Helper function to set nested values in an object using dot notation.
     * Example: setNestedValue(obj, "ghs.classification.class", "explosive")
     * Results in: obj.ghs.classification.class = "explosive"
     */
    function setNestedValue(obj, path, value) {
        const keys = path.split('.');
        let current = obj;
        
        for (let i = 0; i < keys.length - 1; i++) {
            const key = keys[i];
            if (!current[key] || typeof current[key] !== 'object') {
                current[key] = {};
            }
            current = current[key];
        }
        
        current[keys[keys.length - 1]] = value;
    }

    /**
     * Expose collectAmazonMappingData() globally (Marketplace Stepper depends on it).
     * Now uses the universal collection function.
     *
     * Premium behavior: If no template is selected AND no WC category is selected,
     * allow the user to proceed without validation (they don't want to edit any template).
     * Free behavior: Always require both WC and Amazon category selection.
     */
    window.collectAmazonMappingData = function () {
        console.log('[MO Debug] collectAmazonMappingData() called - using universal collection');
        $('#momcs-mapping-validation-container').hide();
        $('#momcs-mapping-validation-list').empty();
        $('.momcs-mapping-field-error').removeClass('momcs-mapping-field-error');
        $('.momcs-searchable-error').removeClass('momcs-searchable-error');

        const errors = [];
        const wcCat = $('.momcs-template-mapping-wc-category').val();
        const amazonCategory = $('.momcs-template-mapping-amazon-category').val();
        const templateSelected = $('#momcs-template-select').val();

        // Premium mode: If no template AND no WC category selected, allow skipping
        // This means the user doesn't want to edit any template mapping
        if (!isFreePlan && !templateSelected && !wcCat) {
            console.log('[MO Debug] Premium mode: No template or WC category selected, allowing skip');
            return {
                isValid: true,
                skipped: true,
                mapping_data: {},
                category_mapping: {},
                field_mapping: '{}',
                selected_category: '',
            };
        }

        // Validate WC category - only if a template is selected (premium) or always (free)
        let wcCategoryValid = true;
        $('.momcs-template-mapping-wc-category').each(function () {
            if (!$(this).val()) {
                wcCategoryValid = false;
                $(this).addClass('momcs-mapping-field-error');
                var inst = $(this).data('searchableSelect');
                if (inst) inst.showError();
            }
        });
        if (!wcCategoryValid) errors.push(strings.errorSelectWcCat);

        // Validate Amazon category - only required if WC category OR template is selected
        // In free mode: Always require Amazon category
        // In premium mode: Only require if WC category or template is selected
        const requireAmazonCategory = isFreePlan || wcCat || templateSelected;
        if (requireAmazonCategory && !amazonCategory) {
            errors.push(strings.errorSelectAmazonCat);
            $('.momcs-template-mapping-amazon-category').addClass('momcs-mapping-field-error');
            var amzInst = $('.momcs-template-mapping-amazon-category').data('searchableSelect');
            if (amzInst) amzInst.showError();
        }

        if (errors.length) {
            $('#momcs-mapping-validation-list').html(errors.map(e => `<li>${e}</li>`).join(''));
            $('#momcs-mapping-validation-container').show();
            return { isValid: false, errors };
        }

        // Use the universal collection function
        const collectionResult = collectAllFieldMappings();
        
        // Merge any validation errors from field collection
        errors.push(...collectionResult.errors);
        
        if (errors.length) {
            $('#momcs-mapping-validation-list').html(errors.map(e => `<li>${e}</li>`).join(''));
            $('#momcs-mapping-validation-container').show();
            return { isValid: false, errors };
        }

        // Store new attributes globally for the save handler to pick up
        if (Object.keys(collectionResult.newAttributes).length > 0) {
            window.newAttributesFromNested = collectionResult.newAttributes;
        }

        return {
            isValid: true,
            mapping_data: {}, // not used yet
            category_mapping: {
                wc_category: $('.momcs-template-mapping-wc-category').val(),
                amazon_category: amazonCategory,
            },
            field_mapping: JSON.stringify(collectionResult.fieldMappings),
            selected_category: amazonCategory,
        };
    };

    /**
     * Collect default field mappings (SKU, Item Name, Brand, Price, Quantity)
     * These are the core fields configured in the Default Fields section
     * 
     * @returns {Object} Default field mappings in key-value pairs
     */
    function collectDefaultFieldMappings() {
        console.log('[MO Debug] Collecting default field mappings...');
        
        const defaultMappings = {};
        
        // Define the default field IDs and their corresponding field names
        const defaultFields = {
            'amazon_sku': 'sku',
            'amazon_item_name': 'item_name', 
            'amazon_brand': 'brand',
            'amazon_price': 'price',
            'amazon_quantity': 'quantity'
        };
        
        // Loop through each default field and collect its selected value
        Object.keys(defaultFields).forEach(function(fieldId) {
            const fieldName = defaultFields[fieldId];
            const selectElement = $('#' + fieldId);
            
            if (selectElement.length && selectElement.val()) {
                defaultMappings[fieldName] = selectElement.val();
                console.log('[MO Debug] Default field mapping:', fieldName, '=', selectElement.val());
            } else {
                console.log('[MO Debug] Default field not found or empty:', fieldId);
            }
        });
        
        console.log('[MO Debug] Collected default mappings:', defaultMappings);
        return defaultMappings;
    }

    /*** Amazon category change fetch ***/
    // -----------------------------------------------------------------------------
    //  Event: Save Mappings
    // -----------------------------------------------------------------------------
    $(document).on('click', '#momcs-template-mapping-save', function(){
        console.log('[MO Debug] Direct save button clicked - using universal collection');
        const wcCat   = $('.momcs-template-mapping-wc-category').val();
        const amzCat  = $('.momcs-template-mapping-amazon-category').val();
        const templateSelected = $('#momcs-template-select').val();

        // No template or categories selected: skip save to avoid error alerts when nothing configured
        if (!templateSelected && !wcCat && !amzCat) {
            console.log('[MO Debug] No template or categories selected, skipping save');
            $(document).trigger('momcs_template_mapping_saved', [{}, '']);
            return;
        }

        // Validation: Only require Amazon category if WC category OR template is selected
        // In free mode: Always require both WC and Amazon category
        // In premium mode: Only require if user has started editing (selected WC cat or template)
        const requireAmazonCategory = isFreePlan || wcCat || templateSelected;
        if (requireAmazonCategory && (!wcCat || !amzCat)) {
            // Notify stepper to re-enable Next on validation error
            const errorMsg = !wcCat ? strings.errorSelectWcCat : strings.errorSelectAmazonCat;
            $(document).trigger('momcs_template_mapping_error', [{ reason: 'validation', message: errorMsg }]);
            alert(errorMsg);
            return;
        }

        // Use the universal collection function directly
        const collectionResult = collectAllFieldMappings();
        
        if (collectionResult.errors.length > 0) {
            // Notify stepper to re-enable Next on validation error
            $(document).trigger('momcs_template_mapping_error', [{ reason: 'validation', errors: collectionResult.errors }]);
            alert('Errors found:\n' + collectionResult.errors.join('\n'));
            return;
        }
        
        const fieldMappings = collectionResult.fieldMappings;
        const newAttributes = collectionResult.newAttributes;
        
        // Collect default field mappings
        const defaultMappings = collectDefaultFieldMappings();
        
        console.log('[MO Debug] Final fieldMappings:', fieldMappings);
        console.log('[MO Debug] Final newAttributes:', newAttributes);
        console.log('[MO Debug] Final defaultMappings:', defaultMappings);
        
        // Debug: Check lengths of all slugs before sending
        Object.keys(newAttributes).forEach(function(key) {
            const attr = newAttributes[key];
            if (attr.slug) {
                console.log('[MO Debug] Attribute slug check:', key, 'slug:', attr.slug, 'length:', attr.slug.length);
                if (attr.slug.length > 28) {
                    console.error('[MO Debug] ERROR: Slug too long!', attr.slug);
                }
            }
        });

        $('#momcs-template-mapping-save').prop('disabled', true).text('Saving...');
        $('#momcs-template-mapping-status').removeClass('momcs-template-mapping-status-success momcs-template-mapping-status-error');

        $.post(ajaxUrl, {
            action: 'momcs_sync_save_unified_mapping',
            marketplace: 'amazon',
            category_mapping: JSON.stringify({ wc_category: wcCat, amazon_category: amzCat }),
            field_mapping: JSON.stringify(fieldMappings),
            new_attributes: JSON.stringify(newAttributes),
            selected_category: amzCat,
            mapping_data: JSON.stringify(defaultMappings),
            product_type: amzCat,
            marketplace_id: marketplaceId,
            channel_id: channelUuid,
            security: nonces.saveMapping,
        }).done(function(resp){
            if(resp.success){
                $('#momcs-template-mapping-status').addClass('momcs-template-mapping-status-success').text('Mappings saved successfully!');
                tmState.hasPrefillMapping = true;
                tmState.mappingSaveCompletedOnce = true;
                const tplUuid = resp.data && resp.data.template_uuid ? String(resp.data.template_uuid) : '';
                const wcSaved = wcCat;
                const amzSaved = amzCat;
                fetchTemplatesList({
                    beforePopulate: function () {
                        if (tplUuid && tmState.templates.some(function (t) { return t.uuid === tplUuid; })) {
                            tmState.selectedUuid = tplUuid;
                            $('#momcs-template-select').val(tplUuid);
                        } else {
                            const matched = findTemplateByCategoryPair(wcSaved, amzSaved);
                            if (matched) {
                                tmState.selectedUuid = matched.uuid;
                                $('#momcs-template-select').val(matched.uuid);
                            }
                        }
                    },
                }).done(function () {
                    updatePremiumTemplateDropdownVisibility();
                    if (tmState.selectedUuid) {
                        syncSearchableDisplay($('#momcs-template-select'));
                    }
                    showTemplateMappingEditorUi();
                    updateAddTemplateResetVisibility();
                    applyPlanGating();
                });
                $(document).trigger('momcs_template_mapping_saved', [fieldMappings, amzCat]);
            } else {
                const msg = resp.data && resp.data.message ? resp.data.message : 'Error';
                $('#momcs-template-mapping-status').addClass('momcs-template-mapping-status-error').text(msg);
                // Notify stepper to re-enable Next on server-declared error
                $(document).trigger('momcs_template_mapping_error', [{ reason: 'server', message: msg, response: resp }]);
            }
        }).fail(function(jqXHR, textStatus, errorThrown){
            $('#momcs-template-mapping-status').addClass('momcs-template-mapping-status-error').text('Ajax error');
            // Notify stepper to re-enable Next on transport error
            $(document).trigger('momcs_template_mapping_error', [{ reason: 'ajax', message: 'Ajax error', error: errorThrown, status: textStatus }]);
        }).always(function(){
            $('#momcs-template-mapping-save').prop('disabled', false).text('Save Mappings');
        });
    });

    $(document).on('change', '.momcs-template-mapping-amazon-category, .momcs-template-mapping-wc-category', function () {
        const selectedCategory = $(this).val();
        const wcSelected = $('.momcs-template-mapping-wc-category').val();
        const amzSelected = $('.momcs-template-mapping-amazon-category').val();
        
        // Handle parent category warning for WC category changes
        if ($(this).hasClass('momcs-template-mapping-wc-category')) {
            handleWcCategoryChange();
        }
        
        // Handle validation when Amazon category is selected after parent WC category
        if ($(this).hasClass('momcs-template-mapping-amazon-category')) {
            const wcCategoryId = $('.momcs-template-mapping-wc-category').val();
            const amzCategoryId = $(this).val();
            if (wcCategoryId && amzCategoryId && hasChildCategories(wcCategoryId)) {
                validateParentMapping(wcCategoryId, amzCategoryId);
            }
        }
        
        if (!wcSelected || !amzSelected) { return; }

        $('#momcs-required-fields-container').show();
        $('.momcs-loading-message').show();
        $('.momcs-field-mapping-table-container').hide();
        $('#momcs-field-mapping-rows').empty();

        $.post(ajaxUrl, {
            action: 'momcs_sync_get_product_type_schema',
            product_type: amzSelected,
            marketplace_id: marketplaceId,
            channel_id: channelUuid,
            security: nonces.getSchema,
        }).done(function (resp) {
            if (!resp.success) {
                handleEmpty();
                return;
            }
            
            // Use hierarchical fields if available, fallback to old structure
            const hierarchicalFields = resp.data.hierarchical_fields;
            const allFields = resp.data.all_fields;
            
            if (hierarchicalFields && Object.keys(hierarchicalFields).length > 0) {
                // Use new hierarchical structure
                const defaultSkip = ['sku', 'item_name', 'brand', 'price', 'quantity'];
                let filteredFields = {};

                $.each(hierarchicalFields, function (fieldName, fieldData) {
                    if (!defaultSkip.includes(fieldName) && !isFieldHidden(fieldName)) {
                        filteredFields[fieldName] = fieldData;
                    }
                });

                // If everything got filtered out, fall back to showing all non-hidden hierarchical fields
                if (Object.keys(filteredFields).length === 0) {
                    $.each(hierarchicalFields, function (fieldName, fieldData) {
                        if (!isFieldHidden(fieldName)) {
                            filteredFields[fieldName] = fieldData;
                        }
                    });
                }

                // As a last resort, show all hierarchical fields
                if (Object.keys(filteredFields).length === 0) {
                    filteredFields = hierarchicalFields;
                }
                fetchExistingMappingsHierarchical(filteredFields);
            } else if (allFields && Object.keys(allFields).length > 0) {
                // Fallback to old flat structure
                const defaultSkip = ['sku', 'item_name', 'brand', 'price', 'quantity'];
                const isHidden = (n) => {
                    const isMetaHidden = HIDDEN_META_FIELDS.some(hiddenField => n.includes(hiddenField));
                    const isSpecialBackendField = SPECIAL_BACKEND_FIELDS.some(specialField => {
                        return n === specialField || n.startsWith(specialField + '[');
                    });
                    return isMetaHidden || isSpecialBackendField;
                };
                const required = [], optional = [];
                $.each(allFields, function (name, details) {
                    if (defaultSkip.includes(name.split('[')[0]) || isHidden(name)) return;
                    (details.required ? required : optional).push([name, details]);
                });
                let ordered = required.concat(optional);

                // If empty after filtering, allow default fields too (hide only hard-hidden ones)
                if (!ordered.length) {
                    const req2 = [], opt2 = [];
                    $.each(allFields, function (name, details) {
                        if (isHidden(name)) return;
                        (details.required ? req2 : opt2).push([name, details]);
                    });
                    ordered = req2.concat(opt2);
                }

                // Last resort: show everything as provided
                if (!ordered.length) {
                    ordered = Object.entries(allFields);
                }
                fetchExistingMappings(ordered);
            } else {
                handleEmpty();
            }
        }).fail(handleEmpty);

        function handleEmpty() {
            $('.momcs-loading-message').hide();
            $('#momcs-field-mapping-rows').html(`<tr><td colspan="2">${strings.noFieldsFound}</td></tr>`);
            $('.momcs-field-mapping-table-container').show();
        }

        function fetchExistingMappings(ordered) {
            $.post(ajaxUrl, {
                action: 'momcs_sync_get_unified_mapping',
                marketplace: 'amazon',
                channel_id: channelUuid,
                wc_category: wcSelected,
                amazon_category: amzSelected,
                security: nonces.getMapping,
            }).done(function (mapResp) {
                const savedCat    = mapResp.data ? mapResp.data.selected_category : '';
                let   existingMap = mapResp.data ? mapResp.data.field_mappings : {};
                // We already fetched specific pair; use as-is
                buildRows(ordered, existingMap);
            }).fail(function () {
                buildRows(ordered, {});
            });
        }

        function fetchExistingMappingsHierarchical(hierarchicalFields) {
            $.post(ajaxUrl, {
                action: 'momcs_sync_get_unified_mapping',
                marketplace: 'amazon',
                channel_id: channelUuid,
                wc_category: wcSelected,
                amazon_category: amzSelected,
                security: nonces.getMapping,
            }).done(function (mapResp) {
                const savedCat = mapResp.data ? mapResp.data.selected_category : '';
                let existingMap = mapResp.data ? mapResp.data.field_mappings : {};
                // We already fetched specific pair; use as-is
                buildHierarchicalRows(hierarchicalFields, existingMap);
            }).fail(function () {
                buildHierarchicalRows(hierarchicalFields, {});
            });
        }

        function buildHierarchicalRows(hierarchicalFields, existingMap) {
            $('.momcs-loading-message').hide();
            console.log('[MO Debug] Building hierarchical rows:', hierarchicalFields);
            console.log('[MO Debug] Existing mappings:', existingMap);
            
            // Debug: Check GHS specifically
            if (hierarchicalFields.ghs) {
                console.log('[MO Debug] GHS field structure:', hierarchicalFields.ghs);
                if (hierarchicalFields.ghs.children) {
                    console.log('[MO Debug] GHS children:', hierarchicalFields.ghs.children);
                    if (hierarchicalFields.ghs.children.classification) {
                        console.log('[MO Debug] GHS classification structure:', hierarchicalFields.ghs.children.classification);
                    }
                }
            }
            
            let allRows = '';
            
            // Sort fields by priority: required first, then optional
            const sortedFields = Object.entries(hierarchicalFields).sort(([, a], [, b]) => {
                if (a.required && !b.required) return -1;
                if (!a.required && b.required) return 1;
                return 0;
            });
            
            sortedFields.forEach(([fieldName, fieldData]) => {
                allRows += buildFieldSection(fieldName, fieldData, existingMap);
            });
            
            $('#momcs-field-mapping-rows').html(allRows);
            $('.momcs-field-mapping-table-container').show();
            
            // Initialize collapsible behavior
            initializeCollapsibleSections();

            // Initialize searchable dropdowns on newly created rows
            initFieldMappingSearchables();

            // Reveal the Save button now that we have fields
            $('#momcs-template-mapping-save').show();
        }

        function buildFieldSection(fieldName, fieldData, existingMap) {
            console.log('[MO Debug] Building field section:', fieldName, fieldData);
            
            if (fieldData.parent) {
                // Parent field with children - create collapsible section
                return buildParentFieldSection(fieldName, fieldData, existingMap);
            } else {
                // Simple scalar field - create regular row
                return buildSimpleFieldRow(fieldName, fieldData, existingMap);
            }
        }

        function buildParentFieldSection(fieldName, fieldData, existingMap) {
            const isRequired = fieldData.required;
            const requiredIndicator = isRequired ? '<span class="momcs-required-indicator">*</span>' : '';
            const sectionClass = isRequired ? 'momcs-required-field' : 'momcs-optional-field';
            
            // Create parent section header (collapsible)
            let sectionHtml = `
                <tr class="momcs-field-section-header ${sectionClass}" data-field-section="${fieldName}">
                    <td colspan="2" class="momcs-parent-field-header">
                        <div class="momcs-collapsible-toggle" data-target="${fieldName}">
                            ${requiredIndicator}
                            <span class="momcs-toggle-icon">🔽</span>
                            <span class="momcs-field-tooltip-trigger" data-tooltip="${escapeAttr(fieldData.description)}">
                                <strong>${fieldData.title}</strong>
                                ${TOOLTIP_INFO_SVG}
                            </span>
                            <span class="momcs-field-type">(${fieldData.type})</span>
                        </div>
                    </td>
                </tr>
            `;
            
            // Add children rows (initially visible) with multi-level support
            if (fieldData.children) {
                Object.entries(fieldData.children).forEach(([childName, childData]) => {
                    if (childData.mappable !== false) {
                        sectionHtml += buildChildFieldRow(fieldName, childName, childData, existingMap, fieldName, 1);
                    }
                });
            }
            
            return sectionHtml;
        }

        function buildChildFieldRow(parentName, childName, childData, existingMap, fieldPath = '', level = 1) {
            // Build the complete field path for deep nesting
            const currentPath = fieldPath ? `${fieldPath}.${childName}` : `${parentName}.${childName}`;
            
            console.log('[MO Debug] buildChildFieldRow:', {
                parentName,
                childName, 
                currentPath,
                level,
                hasChildren: !!(childData.children && Object.keys(childData.children).length > 0),
                childrenKeys: childData.children ? Object.keys(childData.children) : [],
                childData: childData
            });
            
            // Check if this field has children (needs further nesting)
            if (childData.children && Object.keys(childData.children).length > 0) {
                console.log('[MO Debug] Creating nested section for:', currentPath);
                return buildNestedFieldSection(parentName, childName, childData, existingMap, currentPath, level);
            }
            
            // This is a terminal field (enum or mappable field)
            console.log('[MO Debug] Creating terminal field for:', currentPath);
            return buildTerminalField(parentName, childName, childData, existingMap, currentPath, level);
        }
        
        function buildNestedFieldSection(parentName, childName, childData, existingMap, currentPath, level) {
            const isRequired = childData.required;
            const requiredIndicator = isRequired ? '<span class="momcs-required-indicator">*</span>' : '';
            const sectionClass = isRequired ? 'momcs-required-field' : 'momcs-optional-field';
            const indentClass = level > 1 ? `momcs-nested-level-${level}` : 'momcs-child-field-indent';
            
            // Create collapsible subsection header
            let sectionHtml = `
                <tr class="momcs-field-section-header momcs-nested-section ${sectionClass}" 
                    data-field-section="${currentPath}" data-nesting-level="${level}">
                    <td colspan="2" class="momcs-nested-field-header">
                        <div class="momcs-collapsible-toggle ${indentClass}" data-target="${currentPath}">
                            ${requiredIndicator}
                            <span class="momcs-toggle-icon">🔽</span>
                            <span class="momcs-field-tooltip-trigger" data-tooltip="${escapeAttr(childData.description)}">
                                <strong>${childData.title}</strong>
                                ${TOOLTIP_INFO_SVG}
                            </span>
                            <span class="momcs-field-type">(${childData.type})</span>
                        </div>
                    </td>
                </tr>
            `;
            
            // Recursively build children at the next level
            if (childData.children) {
                Object.entries(childData.children).forEach(([grandChildName, grandChildData]) => {
                    if (grandChildData.mappable !== false) {
                        sectionHtml += buildChildFieldRow(parentName, grandChildName, grandChildData, existingMap, currentPath, level + 1);
                    }
                });
            }
            
            return sectionHtml;
        }
        
        function buildTerminalField(parentName, childName, childData, existingMap, currentPath, level) {
            // Get saved value by traversing the nested path
            let savedValue = '';
            const pathParts = currentPath.split('.');
            let currentObj = existingMap;
            
            // Navigate through the nested structure
            for (const part of pathParts) {
                if (currentObj && typeof currentObj === 'object' && currentObj.hasOwnProperty(part)) {
                    currentObj = currentObj[part];
                } else {
                    currentObj = null;
                    break;
                }
            }
            
            if (typeof currentObj === 'string') {
                savedValue = currentObj;
            }
            
            const isRequired = childData.required;
            const isNestedRequired = childData.nested_required;
            const requiredIndicator = isRequired ? '<span class="momcs-required-indicator">*</span>' : '';
            const rowClass = isRequired ? 'momcs-required-field' : (isNestedRequired ? 'momcs-nested-required-field' : 'momcs-optional-field');
            const indentClass = level > 1 ? `momcs-nested-level-${level}` : 'momcs-child-field-indent';
            
            let fieldHtml = '';
            
            if (childData.enum && Array.isArray(childData.enum) && childData.enum.length) {
                // Enum field - this is what we want for GHS class
                const enumOptions = childData.enum.map(v => {
                    const valStr = String(v);
                    const sel = savedValue && savedValue.toString().toLowerCase() === valStr.toLowerCase() ? ' selected' : '';
                    // Use enumNames if available for better display
                    const displayName = childData.enumNames && childData.enumNames[childData.enum.indexOf(v)] 
                        ? childData.enumNames[childData.enum.indexOf(v)]
                        : valStr.replace(/_/g, ' ').toLowerCase().replace(/\b\w/g, l => l.toUpperCase());
                    return `<option value="${valStr}"${sel}>${displayName}</option>`;
                }).join('');
                
                fieldHtml = `
                    <div class="momcs-enum-wrapper">
                        <select class="momcs-enum-select momcs-nested-field-select" 
                                data-field-path="${currentPath}"
                                data-nesting-level="${level}">
                            <option value="">-- Select Fixed Value --</option>
                            ${enumOptions}
                        </select>
                    </div>
                `;
            } else {
                // Regular mappable field
                const selectedWcField = savedValue || '';
                const requiredHint = ''; // Required hints temporarily disabled
                const patternHint = childData.pattern ? 
                    `<small style="color: #e74c3c; display: block;">Must match pattern: ${childData.pattern}</small>` : '';
                
                fieldHtml = `
                    <select class="momcs-field-mapping-row-wc-field momcs-nested-field-select" 
                            data-field-path="${currentPath}"
                            data-nesting-level="${level}"
                            data-amazon-title="${childData.title}">
                        ${buildAttributeOptions(selectedWcField)}
                    </select>
                    ${requiredHint}
                    ${patternHint}
                `;
            }
            
            return `
                <tr class="momcs-field-mapping-row momcs-child-field-row ${rowClass}" 
                    data-field-path="${currentPath}"
                    data-nesting-level="${level}"
                    data-field-section="${currentPath.split('.').slice(0, -1).join('.')}">
                    <td class="momcs-field-mapping-row-amazon-field momcs-child-field">
                        <div class="${indentClass}">
                            ${requiredIndicator}
                            <span class="momcs-field-tooltip-trigger" data-tooltip="${escapeAttr(childData.description)}">
                                ${childData.title}
                                ${TOOLTIP_INFO_SVG}
                            </span>
                        </div>
                    </td>
                    <td>
                        <div class="momcs-field-wrapper">
                            ${fieldHtml}
                        </div>
                    </td>
                </tr>
            `;
        }

        function buildSimpleFieldRow(fieldName, fieldData, existingMap) {
            // Simple scalar field - similar to old buildRows logic
            const savedValue = existingMap[fieldName] || '';
            const isRequired = fieldData.required;
            const requiredIndicator = isRequired ? '<span class="momcs-required-indicator">*</span>' : '';
            const rowClass = isRequired ? 'momcs-required-field' : 'momcs-optional-field';
            
            let selectedWcField = savedValue;
            if (!selectedWcField) {
                if (fieldName.toLowerCase() === 'sku') {
                    selectedWcField = '_sku';
                } else if (fieldName.toLowerCase() === 'brand') {
                    selectedWcField = 'product_brand';
                }
            }
            
            let fieldHtml = '';
            
            if (fieldData.enum && Array.isArray(fieldData.enum) && fieldData.enum.length) {
                // Enum field
                const enumOptions = fieldData.enum.map(v => {
                    const valStr = String(v);
                    const sel = savedValue && savedValue.toString().toLowerCase() === valStr.toLowerCase() ? ' selected' : '';
                    return `<option value="${valStr}"${sel}>${valStr.replace(/_/g, ' ').toLowerCase().replace(/\\b\\w/g, l => l.toUpperCase())}</option>`;
                }).join('');
                
                fieldHtml = `
                    <div class="momcs-enum-wrapper">
                        <select class="momcs-enum-select" data-amazon-field="${fieldName}">
                            <option value="">-- Select Fixed Value --</option>
                            ${enumOptions}
                        </select>
                    </div>
                `;
            } else {
                // Regular mappable field
                const requiredHint = ''; // Required hints temporarily disabled
                const patternHint = fieldData.pattern ? 
                    `<small style="color: #e74c3c; display: block;">Must match pattern: ${fieldData.pattern}</small>` : '';
                
                fieldHtml = `
                    <select class="momcs-field-mapping-row-wc-field" 
                            data-amazon-field="${fieldName}" 
                            data-amazon-title="${fieldData.title}">
                        ${buildAttributeOptions(selectedWcField)}
                    </select>
                    ${requiredHint}
                    ${patternHint}
                `;
            }
            
            return `
                <tr class="momcs-field-mapping-row ${rowClass}" data-field="${fieldName}">
                    <td class="momcs-field-mapping-row-amazon-field">
                        ${requiredIndicator}
                        <span class="momcs-field-tooltip-trigger" data-tooltip="${escapeAttr(fieldData.description)}">
                            ${fieldData.title}
                            ${TOOLTIP_INFO_SVG}
                        </span>
                    </td>
                    <td>
                        <div class="momcs-field-wrapper">
                            ${fieldHtml}
                        </div>
                    </td>
                </tr>
            `;
        }

        function initializeCollapsibleSections() {
            // Add click handler for collapsible toggles with multi-level support
            $(document).off('click', '.momcs-collapsible-toggle').on('click', '.momcs-collapsible-toggle', function(e) {
                e.preventDefault();
                const targetSection = $(this).data('target');
                const $toggle = $(this);
                const $icon = $toggle.find('.momcs-toggle-icon');
                
                // Find all child rows and nested sections under this target
                const $childRows = $(`.momcs-child-field-row[data-field-section="${targetSection}"]`);
                const $nestedSections = $(`.momcs-nested-section[data-field-section^="${targetSection}."]`);
                const $allChildren = $childRows.add($nestedSections);
                
                if ($allChildren.is(':visible')) {
                    // Collapse all children and nested sections
                    $allChildren.hide();
                    $icon.text('🔽');
                    
                    // Also collapse any deeply nested sections
                    $(`.momcs-child-field-row[data-field-section^="${targetSection}."]`).hide();
                } else {
                    // Expand immediate children only
                    $childRows.show();
                    $nestedSections.show();
                    $icon.text('🔼');
                }
            });
        }

        // Old collection functions removed - now using universal collectAllFieldMappings()

        function buildRows(entries, existing) {
            $('.momcs-loading-message').hide();
            const rows = entries.map(([name, details]) => {
                const label        = details.title || name;
                const desc         = details.description || '';
                const isReq        = details.required ? 'data-required="true"' : '';
                const rowClass     = details.required ? 'momcs-required-field' : (details.nested_required ? 'momcs-nested-required-field' : 'momcs-optional-field');
                const disabledAttr = details.configurable === false ? 'disabled' : '';
                const fieldPriority = details.required ? 'high' : (details.nested_required ? 'medium' : 'low');
                let   saved        = getSavedValue(existing, name) || '';
                let   selectedWcField = saved;
                if (!selectedWcField) {
                    if (name.toLowerCase() === 'sku') {
                        selectedWcField = '_sku';
                    } else if (name.toLowerCase() === 'brand') {
                        selectedWcField = 'product_brand';
                    }
                }

                let wcFieldHtml = '';
                let enumSelectHtml = '';

                if (details.enum && Array.isArray(details.enum) && details.enum.length) {
                    const enumOptions = details.enum.map(v => {
                        const valStr = String(v);
                        const sel = saved && saved.toString().toLowerCase() === valStr.toLowerCase() ? ' selected' : '';
                        return '<option value="' + valStr + '"' + sel + '>' + valStr.replace(/_/g, ' ').toLowerCase().replace(/\\b\\w/g, l => l.toUpperCase()) + '</option>';
                    }).join('');
                    enumSelectHtml = `
                        <div class="momcs-enum-wrapper">
                            <select class="momcs-enum-select" data-amazon-field="${name}" ${disabledAttr}>
                                <option value="">-- Select Fixed Value --</option>
                                ${enumOptions}
                            </select>
                        </div>
                    `;
                } else {
                    // Add pattern validation hint if present
                    let patternHint = '';
                    if (details.pattern) {
                        if (name === 'recommended_browse_nodes') {
                            patternHint = '<small style="color: #e74c3c; display: block;"><strong>Must be numeric only</strong> (browse node ID like: 123456)</small>';
                        } else {
                            patternHint = `<small style="color: #e74c3c; display: block;">Must match pattern: ${details.pattern}</small>`;
                        }
                    }
                    
                    // Required field highlighting temporarily disabled
                    let requiredHint = '';
                    
                    wcFieldHtml = `
                        <select class="momcs-field-mapping-row-wc-field" data-amazon-field="${name}" data-amazon-title="${label}" ${disabledAttr}>
                            ${buildAttributeOptions(selectedWcField)}
                        </select>
                        ${requiredHint}
                        ${patternHint}
                    `;
                }

                return `
                    <tr class="momcs-field-mapping-row ${rowClass}" data-field="${name}" data-priority="${fieldPriority}" ${isReq}>
                        <td class="momcs-field-mapping-row-amazon-field">
                            ${details.required ? '<span class="momcs-required-indicator">*</span>' : ''}
                            <span class="momcs-field-tooltip-trigger" data-tooltip="${escapeAttr(desc)}">
                                ${label}
                                ${TOOLTIP_INFO_SVG}
                            </span>
                        </td>
                        <td>
                            <div class="momcs-field-wrapper">
                                ${wcFieldHtml}
                                ${enumSelectHtml}
                            </div>
                        </td>
                    </tr>`;
            }).join('');
            $('#momcs-field-mapping-rows').html(rows);
            $('.momcs-field-mapping-table-container').show();
            // Reveal the Save button now that we have fields.
            $('#momcs-template-mapping-save').show();
            // Initialize searchable dropdowns on newly created rows
            initFieldMappingSearchables();
        }
    });

    // Remove error highlighting on dropdown change
    $(document).on('change', '.momcs-template-mapping-wc-category, .momcs-template-mapping-amazon-category', function () {
        $(this).removeClass('momcs-mapping-field-error');
        // Also clear SearchableSelect error
        var inst = $(this).data('searchableSelect');
        if (inst) inst.clearError();
        const wcVal = $('.momcs-template-mapping-wc-category:first').val();
        const amzVal = $('.momcs-template-mapping-amazon-category:first').val();
        if (wcVal || amzVal) {
            hideTemplateMappingSkeleton();
        }
        // Update category chips display
        var wcName = wcVal && wcCategoryNames[wcVal] ? wcCategoryNames[wcVal] : '';
        var amzName = amzVal && amazonCategoryNames[amzVal] ? amazonCategoryNames[amzVal] : '';
        $('#momcs-category-chips-display').html(buildCategoryChipsHtml(wcName, amzName));
    });

    $(document).on('momcs_template_prefill_done', function(){
        hideTemplateMappingSkeleton();
    });

    // Enhanced enum / WC field select interaction
    $(document).on('change', '.momcs-field-mapping-row-wc-field, .momcs-enum-select', function () {
        const $currentSelect = $(this);
        const $wrapper   = $currentSelect.closest('.momcs-field-wrapper');
        const $wcSelect  = $wrapper.find('.momcs-field-mapping-row-wc-field');
        const $enumSelect = $wrapper.find('.momcs-enum-select');

        if ($currentSelect.hasClass('momcs-field-mapping-row-wc-field')) {
            const amazonField = $wcSelect.data('amazon-field');
            if (amazonField === 'brand') {
                $wcSelect.val('product_brand');
            }
            if ($wcSelect.val()) {
                $enumSelect.hide();
            } else {
                $enumSelect.show();
            }
            $enumSelect.val('');
        } else {
            if ($enumSelect.val()) {
                $wcSelect.val('').prop('disabled', true);
            } else {
                $wcSelect.prop('disabled', false);
            }
        }
    });
 
})(jQuery);
