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

    var nonce     = '';
    var editNonce = '';
    var ajaxUrl   = '';

    $(function () {
        var nonceEl = document.getElementById('skyemag-nonce');
        var pingEl  = document.getElementById('skyemag-ping-nonce');
        var productsNonceEl = document.getElementById('skyemag-products-nonce');

        // Always pick up ajaxUrl from the localized script — pages without
        // the Products-specific nonce element (Orders, Notifications) still
        // need it for their own AJAX buttons. Falls back to the WP default
        // path so the variable is never an empty string.
        ajaxUrl = ( typeof skyemagAdmin !== 'undefined' && skyemagAdmin.ajaxUrl )
            ? skyemagAdmin.ajaxUrl
            : '/wp-admin/admin-ajax.php';

        if ( nonceEl ) {
            nonce     = nonceEl.value;
            editNonce = productsNonceEl ? productsNonceEl.value : nonce;

            initSyncToggles();
            initMarginInputs();
            initMinMarginInputs();
            initMaxMarginInputs();
            initStockPctInputs();
            initSaveAll();
            initBulkActions();
            initTypeColToggle();
            initEanColToggle();
            initEmagStatusToggle();
            initUnlink();
            initFixDuplicates();
        }

        // 3.8.0 — async sync UI. Bound on every plugin admin page so the
        // Settings inline section and the Products modal can both react to
        // an in-flight sync regardless of where the user starts it.
        SkyEmagSyncProgress.init();

        // Publish page
        if ( $( '.skyemag-publish-wrap' ).length ) {
            initPublishPage();
        }

        // Buy Button track button
        if ( $( '#skyemag-bb-track-btn' ).length ) {
            initBBTrack();
        }

        // Detect field sources button
        if ( $( '#skyemag-detect-sources' ).length ) {
            initDetectSources();
        }

        if ( pingEl ) {
            initPing( pingEl.value );
        }

        // Notifications page: Send test email
        if ( $( '#skyemag-notif-test' ).length ) {
            initNotifTest();
        }

        // Orders page: Test connection + manual import + rotate key + copy buttons
        if ( $( '#skyemag-orders-test' ).length ) {
            initOrdersTest();
        }
        if ( $( '#skyemag-manual-import-btn' ).length ) {
            initOrdersManualImport();
        }
        if ( $( '#skyemag-rotate-callback-key' ).length ) {
            initOrdersRotateKey();
        }
        $( '[data-clipboard-target]' ).each(function () {
            initClipboardCopy( $(this) );
        });

        // Margin history modal (Products page)
        if ( $( '.skyemag-products-wrap' ).length ) {
            initMarginHistory();
        }
    });

    // ── Margin history modal (rollback) ─────────────────────────────────
    function initMarginHistory() {
        var $modal = null;

        function ensureModal() {
            if ( $modal && document.body.contains( $modal[0] ) ) { return $modal; }
            $modal = $(
                '<div class="skyemag-modal-backdrop" style="display:none">' +
                  '<div class="skyemag-modal" role="dialog" aria-labelledby="skyemag-margin-history-title">' +
                    '<div class="skyemag-modal-header">' +
                      '<h2 id="skyemag-margin-history-title"></h2>' +
                      '<button type="button" class="skyemag-modal-close" aria-label="Close">&times;</button>' +
                    '</div>' +
                    '<div class="skyemag-modal-body"></div>' +
                  '</div>' +
                '</div>'
            );
            $('body').append( $modal );
            $modal.on('click', function (e) {
                if ( e.target === this ) { closeModal(); }
            });
            $modal.find('.skyemag-modal-close').on('click', closeModal);
            $(document).on('keydown.skyemagModal', function (e) {
                if ( 27 === e.keyCode ) { closeModal(); }
            });
            return $modal;
        }

        function closeModal() {
            if ( $modal ) { $modal.hide(); }
        }

        function formatMargin( val ) {
            if ( val === null || val === undefined ) {
                return '<em>' + ( skyemagAdmin.i18n.inherited || '(inherited)' ) + '</em>';
            }
            return parseFloat(val).toFixed(2) + '%';
        }

        function render( productId, entries, total ) {
            var $m    = ensureModal();
            var $body = $m.find('.skyemag-modal-body');
            $m.find('h2').text(
                ( skyemagAdmin.i18n.marginHistoryTitle || 'Margin history — product #%d' ).replace('%d', productId)
            );

            if ( !entries || !entries.length ) {
                $body.html('<p>' + ( skyemagAdmin.i18n.noHistory || 'No margin changes recorded yet.' ) + '</p>');
                $m.css('display', 'flex');
                return;
            }

            var rows = entries.map(function (e) {
                var fromTo = formatMargin( e.old_margin ) + ' <span class="skyemag-arrow">→</span> ' + formatMargin( e.new_margin );
                var user   = e.user_name ? ( ' · ' + $('<div>').text(e.user_name).html() ) : '';
                return '<tr data-entry-id="' + e.id + '">' +
                    '<td class="skyemag-mh-date">' + $('<div>').text(e.changed_at).html() + user + '</td>' +
                    '<td class="skyemag-mh-change">' + fromTo + '</td>' +
                    '<td class="skyemag-mh-action">' +
                        '<button type="button" class="button button-small skyemag-revert-btn" data-entry-id="' + e.id + '" data-product-id="' + productId + '">' +
                        ( skyemagAdmin.i18n.revertTo || 'Revert to' ) + ' ' + formatMargin( e.old_margin ) +
                        '</button>' +
                    '</td>' +
                    '</tr>';
            }).join('');

            var note = '';
            if ( total > entries.length ) {
                note = '<p class="description">' +
                    ( skyemagAdmin.i18n.showingLast || 'Showing last %1$d of %2$d changes.' )
                        .replace('%1$d', entries.length).replace('%2$d', total) +
                    '</p>';
            }

            $body.html(
                '<table class="widefat striped skyemag-mh-table">' +
                  '<thead><tr>' +
                    '<th>' + ( skyemagAdmin.i18n.when || 'When' ) + '</th>' +
                    '<th>' + ( skyemagAdmin.i18n.change || 'Change' ) + '</th>' +
                    '<th></th>' +
                  '</tr></thead>' +
                  '<tbody>' + rows + '</tbody>' +
                '</table>' +
                note
            );
            $m.css('display', 'flex');
        }

        $(document).on('click', '.skyemag-margin-history-link', function (e) {
            e.preventDefault();
            var productId = parseInt( $(this).data('product-id'), 10 );
            ensureModal().find('.skyemag-modal-body').html('<p>' + ( skyemagAdmin.i18n.loading || 'Loading…' ) + '</p>');
            ensureModal().css('display', 'flex');

            $.post( ajaxUrl, {
                action:     'skyemag_margin_history',
                nonce:      editNonce,
                product_id: productId,
            }, function (r) {
                if ( r.success ) {
                    render( productId, r.data.entries, r.data.total );
                } else {
                    ensureModal().find('.skyemag-modal-body').html(
                        '<p>' + ( r.data && r.data.message ? r.data.message : skyemagAdmin.i18n.error ) + '</p>'
                    );
                }
            }).fail(function () {
                ensureModal().find('.skyemag-modal-body').html(
                    '<p>' + skyemagAdmin.i18n.error + '</p>'
                );
            });
        });

        $(document).on('click', '.skyemag-revert-btn', function () {
            var $btn       = $(this).prop('disabled', true);
            var productId  = parseInt( $btn.data('product-id'), 10 );
            var entryId    = parseInt( $btn.data('entry-id'),   10 );

            $.post( ajaxUrl, {
                action:     'skyemag_margin_revert',
                nonce:      editNonce,
                product_id: productId,
                entry_id:   entryId,
            }, function (r) {
                if ( r.success ) {
                    showNotice( r.data.message, 'success' );
                    // Reflect the reverted value in the row's margin input and price preview.
                    var $input = $( '.skyemag-margin-input[data-product-id="' + productId + '"]' );
                    $input.val( r.data.margin === null || r.data.margin === undefined ? '' : r.data.margin );
                    var $preview = $( '.skyemag-price-preview[data-id="' + productId + '"]' );
                    if ( $preview.length && r.data.emag_price ) {
                        $preview.text( r.data.emag_price );
                    }
                    closeModal();
                    // Reload after a beat so the history count link updates.
                    setTimeout(function () { window.location.reload(); }, 1000);
                } else {
                    showNotice( r.data && r.data.message ? r.data.message : skyemagAdmin.i18n.error, 'error' );
                    $btn.prop('disabled', false);
                }
            }).fail(function () {
                showNotice( skyemagAdmin.i18n.error, 'error' );
                $btn.prop('disabled', false);
            });
        });
    }

    // ── Notifications: Send test email ──────────────────────────────────
    function initNotifTest() {
        $('#skyemag-notif-test').on('click', function () {
            var $btn    = $(this).prop('disabled', true);
            var $status = $('#skyemag-notif-test-status').text( skyemagAdmin.i18n.saving || 'Sending…' );
            var address = $('#skyemag_notif_email_address').val() || '';
            var nonce   = $('#skyemag-notif-test-nonce').val();

            $.post( ajaxUrl, {
                action:  'skyemag_notif_send_test',
                nonce:   nonce,
                address: address,
            }, function (r) {
                if ( r.success ) {
                    $status.css('color', '#027200').text( r.data.message );
                } else {
                    $status.css('color', '#d63638').text( r.data && r.data.message ? r.data.message : skyemagAdmin.i18n.error );
                }
            }).fail(function () {
                $status.css('color', '#d63638').text( skyemagAdmin.i18n.error );
            }).always(function () {
                $btn.prop('disabled', false);
            });
        });
    }

    // ── Orders page: Test connection ────────────────────────────────────
    function initOrdersTest() {
        $('#skyemag-orders-test').on('click', function () {
            var $btn    = $(this).prop('disabled', true);
            var $status = $('#skyemag-orders-test-status').css('color', '').text( skyemagAdmin.i18n.saving || 'Testing…' );
            var nonce   = $('#skyemag-orders-test-nonce').val();

            $.post( ajaxUrl, {
                action: 'skyemag_orders_test_connection',
                nonce:  nonce,
            }, function (r) {
                if ( r && r.success ) {
                    $status.css('color', '#027200').text( r.data.message );
                } else {
                    var msg = ( r && r.data && r.data.message ) ? r.data.message : skyemagAdmin.i18n.error;
                    $status.css('color', '#d63638').text( msg );
                }
            }).fail(function (xhr) {
                var msg;
                if ( xhr.responseJSON && xhr.responseJSON.data && xhr.responseJSON.data.message ) {
                    msg = xhr.responseJSON.data.message;
                } else if ( xhr.status ) {
                    msg = 'HTTP ' + xhr.status + ' ' + ( xhr.statusText || skyemagAdmin.i18n.error );
                } else {
                    msg = skyemagAdmin.i18n.error;
                }
                $status.css('color', '#d63638').text( msg );
            }).always(function () {
                $btn.prop('disabled', false);
            });
        });
    }

    // ── Orders page: Manual import by ID ────────────────────────────────
    function initOrdersManualImport() {
        $('#skyemag-manual-import-btn').on('click', function () {
            var $btn   = $(this);
            var $input = $('#skyemag-manual-order-id');
            var $status = $('#skyemag-manual-import-status').css('color', '');
            var orderId = parseInt( $input.val(), 10 );

            if ( ! orderId || orderId < 1 ) {
                $status.css('color', '#d63638').text( skyemagAdmin.i18n.error || 'Enter a valid order id.' );
                return;
            }

            $btn.prop('disabled', true);
            $status.css('color', '').text( skyemagAdmin.i18n.saving || 'Importing…' );

            $.post( ajaxUrl, {
                action:        'skyemag_orders_manual_import',
                nonce:         $('#skyemag-orders-manual-import-nonce').val(),
                emag_order_id: orderId,
            }, function (r) {
                if ( r && r.success ) {
                    $status.css('color', '#027200').text( r.data.message );
                } else {
                    var msg = ( r && r.data && r.data.message ) ? r.data.message : skyemagAdmin.i18n.error;
                    $status.css('color', '#d63638').text( msg );
                }
            }).fail(function (xhr) {
                var msg = ( xhr.responseJSON && xhr.responseJSON.data && xhr.responseJSON.data.message )
                    ? xhr.responseJSON.data.message
                    : ( 'HTTP ' + xhr.status + ' ' + ( xhr.statusText || '' ) );
                $status.css('color', '#d63638').text( msg );
            }).always(function () {
                $btn.prop('disabled', false);
            });
        });
    }

    // ── Orders page: Rotate callback key ─────────────────────────────────
    function initOrdersRotateKey() {
        $('#skyemag-rotate-callback-key').on('click', function () {
            if ( ! confirm( 'Generate a new callback key? The current URLs in eMAG will stop working until you paste the new ones.' ) ) {
                return;
            }
            var $btn    = $(this).prop('disabled', true);
            var $status = $('#skyemag-rotate-status').css('color', '').text( skyemagAdmin.i18n.saving || 'Rotating…' );

            $.post( ajaxUrl, {
                action: 'skyemag_orders_rotate_callback_key',
                nonce:  $('#skyemag-orders-rotate-key-nonce').val(),
            }, function (r) {
                if ( r && r.success ) {
                    // Update both URL fields in place so the user sees the
                    // new values without a page reload.
                    $('#skyemag-order-callback-url').val( r.data.callback_url );
                    $('#skyemag-order-cancellation-url').val( r.data.cancellation_url );
                    $status.css('color', '#027200').text( r.data.message );
                } else {
                    var msg = ( r && r.data && r.data.message ) ? r.data.message : skyemagAdmin.i18n.error;
                    $status.css('color', '#d63638').text( msg );
                }
            }).always(function () {
                $btn.prop('disabled', false);
            });
        });
    }

    // ── Clipboard copy for [data-clipboard-target] buttons ──────────────
    // Vanilla execCommand fallback so we don't pull in a third-party lib.
    function initClipboardCopy( $btn ) {
        $btn.on('click', function () {
            var sel = $btn.data('clipboard-target');
            var $target = $( sel );
            if ( ! $target.length ) { return; }
            $target[0].select();
            $target[0].setSelectionRange( 0, 99999 );
            try {
                document.execCommand('copy');
                var original = $btn.text();
                $btn.text( '✓ Copied' );
                setTimeout(function () { $btn.text( original ); }, 1500);
            } catch ( e ) {
                // Browser blocked the synchronous copy; user can still
                // copy manually since the field is selected.
            }
        });
    }

    // ── Sync toggle ───────────────────────────────────────────────────────
    function initSyncToggles() {
        $(document).on('change', '.skyemag-sync-toggle', function () {
            var $cb    = $(this);
            var $label = $cb.closest('.skyemag-toggle');
            var id     = parseInt( $cb.data('id'), 10 );
            var enabled = $cb.prop('checked');

            $label.addClass('is-saving');

            $.post( ajaxUrl, {
                action: 'skyemag_toggle_sync',
                nonce: editNonce,
                product_id: id,
                enabled: enabled ? 1 : 0,
            }).fail(function () {
                $cb.prop('checked', !enabled);
            }).always(function () {
                $label.removeClass('is-saving');
            });
        });
    }

    // ── Margin input ──────────────────────────────────────────────────────
    function initMarginInputs() {
        var timers = {};
        $(document).on('input change', '.skyemag-margin-input', function () {
            var $input = $(this);
            var id     = parseInt( $input.data('product-id'), 10 );

            // Auto-mirror to min margin if min margin is empty (no custom value set)
            var $minInput = $('.skyemag-min-margin-input[data-product-id="' + id + '"]');
            if ( $minInput.length && $minInput.val() === '' ) {
                $minInput.attr('placeholder', ( $input.val() || '' ) + ' (eff.)' );
            }

            clearTimeout( timers[id] );
            timers[id] = setTimeout(function () { saveMargin( $input, id ); }, 600);
        });
    }

    function saveMargin( $input, id ) {
        var margin  = $input.val();
        var $saving = $input.siblings('.skyemag-margin-saving');
        // The history link sits in the same vertical slot as the saving
        // overlay, so hide it during save to avoid the two rendering on
        // top of each other.
        var $hist   = $input.closest('tr').find('.skyemag-margin-history-wrap');

        if ( margin !== '' && ( isNaN(parseFloat(margin)) || parseFloat(margin) < -50 || parseFloat(margin) > 300 ) ) {
            $input.addClass('is-error');
            return;
        }
        $input.removeClass('is-error');
        $saving.show().text( skyemagAdmin.i18n.saving );
        $hist.hide();

        $.post( ajaxUrl, {
            action: 'skyemag_save_margin',
            nonce: editNonce,
            product_id: id,
            margin: margin,
        }, function (r) {
            if ( r.success ) {
                $saving.text( skyemagAdmin.i18n.saved ).delay(1500).fadeOut(400, function () {
                    $hist.show();
                });
                if ( r.data.emag_price !== null ) {
                    flashPrice( id, r.data.emag_price, r.data.emag_price_inc );
                }
                updateBelowMinWarning( id, r.data.below_min_margin );
            } else {
                $input.addClass('is-error');
                $saving.text( r.data.message || skyemagAdmin.i18n.error ).css('color','#d63638');
                setTimeout(function () {
                    $saving.hide().css('color','');
                    $hist.show();
                }, 3000);
            }
        }).fail(function () {
            $saving.text( skyemagAdmin.i18n.error ).css('color','#d63638');
            setTimeout(function () {
                $saving.hide().css('color','');
                $hist.show();
            }, 3000);
        });
    }

    // ── Min margin input ──────────────────────────────────────────────────
    function initMinMarginInputs() {
        var timers = {};
        $(document).on('input change', '.skyemag-min-margin-input', function () {
            var $input = $(this);
            var id     = parseInt( $input.data('product-id'), 10 );
            clearTimeout( timers['mm' + id] );
            timers['mm' + id] = setTimeout(function () { saveMinMargin( $input, id ); }, 600);
        });
    }

    function saveMinMargin( $input, id ) {
        var minMargin = $input.val();
        var $saving   = $input.siblings('.skyemag-min-margin-saving');

        if ( minMargin !== '' && ( isNaN(parseFloat(minMargin)) || parseFloat(minMargin) < -50 || parseFloat(minMargin) > 300 ) ) {
            $input.addClass('is-error');
            return;
        }
        $input.removeClass('is-error');
        $saving.show().text( skyemagAdmin.i18n.saving );

        $.post( ajaxUrl, {
            action: 'skyemag_save_min_margin',
            nonce: editNonce,
            product_id: id,
            min_margin: minMargin,
        }, function (r) {
            if ( r.success ) {
                $saving.text( skyemagAdmin.i18n.saved ).delay(1500).fadeOut(400);
                updateBelowMinWarning( id, r.data.below_min_margin );
            } else {
                $input.addClass('is-error');
                $saving.text( r.data.message || skyemagAdmin.i18n.error ).css('color','#d63638');
                setTimeout(function () { $saving.hide().css('color',''); }, 3000);
            }
        }).fail(function () {
            $saving.text( skyemagAdmin.i18n.error ).css('color','#d63638');
            setTimeout(function () { $saving.hide().css('color',''); }, 3000);
        });
    }

    // Show/hide the ⚠ warning on the min margin cell
    function updateBelowMinWarning( id, isBelow ) {
        var $warn = $('.skyemag-min-margin-input[data-product-id="' + id + '"]')
                        .siblings('.skyemag-min-margin-warn');
        if ( isBelow ) {
            if ( ! $warn.length ) {
                $('.skyemag-min-margin-input[data-product-id="' + id + '"]').after(
                    '<span class="skyemag-min-margin-warn" title="Calculated price is below minimum margin — sync blocked">⚠</span>'
                );
            }
        } else {
            $warn.remove();
        }
    }

    // ── Max margin input ──────────────────────────────────────────────────
    function initMaxMarginInputs() {
        var timers = {};
        $(document).on('input change', '.skyemag-max-margin-input', function () {
            var $input = $(this);
            var id     = parseInt( $input.data('product-id'), 10 );
            clearTimeout( timers['mx' + id] );
            timers['mx' + id] = setTimeout(function () { saveMaxMargin( $input, id ); }, 600);
        });
    }

    function saveMaxMargin( $input, id ) {
        var maxMargin = $input.val();
        var $saving   = $input.siblings('.skyemag-max-margin-saving');

        if ( maxMargin !== '' && ( isNaN(parseFloat(maxMargin)) || parseFloat(maxMargin) < -50 || parseFloat(maxMargin) > 1000 ) ) {
            $input.addClass('is-error');
            return;
        }
        $input.removeClass('is-error');
        $saving.show().text( skyemagAdmin.i18n.saving );

        $.post( ajaxUrl, {
            action: 'skyemag_save_max_margin',
            nonce: editNonce,
            product_id: id,
            max_margin: maxMargin,
        }, function (r) {
            if ( r.success ) {
                $saving.text( skyemagAdmin.i18n.saved ).delay(1500).fadeOut(400);
            } else {
                $input.addClass('is-error');
                $saving.text( r.data.message || skyemagAdmin.i18n.error ).css('color','#d63638');
                setTimeout(function () { $saving.hide().css('color',''); }, 3000);
            }
        }).fail(function () {
            $saving.text( skyemagAdmin.i18n.error ).css('color','#d63638');
            setTimeout(function () { $saving.hide().css('color',''); }, 3000);
        });
    }
    function initStockPctInputs() {
        var timers = {};
        $(document).on('input change', '.skyemag-stock-pct-input', function () {
            var $input = $(this);
            var id     = parseInt( $input.data('product-id'), 10 );
            clearTimeout( timers['s' + id] );
            timers['s' + id] = setTimeout(function () { saveStockPct( $input, id ); }, 600);
        });
    }

    function saveStockPct( $input, id ) {
        var pct     = $input.val();
        var $saving = $input.siblings('.skyemag-stock-pct-saving');

        if ( pct !== '' && ( isNaN(parseFloat(pct)) || parseFloat(pct) < 0 || parseFloat(pct) > 100 ) ) {
            $input.addClass('is-error');
            return;
        }
        $input.removeClass('is-error');
        $saving.show().text( skyemagAdmin.i18n.saving );

        $.post( ajaxUrl, {
            action: 'skyemag_save_stock_pct',
            nonce: editNonce,
            product_id: id,
            stock_percent: pct,
        }, function (r) {
            if ( r.success ) {
                $saving.text( skyemagAdmin.i18n.saved ).delay(1500).fadeOut(400);
                // Update eMAG stock preview cell
                var $stockCell = $('span.skyemag-emag-stock[data-id="' + id + '"]');
                if ( $stockCell.length && r.data.emag_stock !== null ) {
                    $stockCell.text( r.data.emag_stock ).addClass('skyemag-price-updated');
                    setTimeout(function () { $stockCell.removeClass('skyemag-price-updated'); }, 700);
                }
            } else {
                $input.addClass('is-error');
                $saving.text( r.data.message || skyemagAdmin.i18n.error ).css('color','#d63638');
                setTimeout(function () { $saving.hide().css('color',''); }, 3000);
            }
        });
    }

    function flashPrice( id, price, priceInc ) {
        var $el = $('.skyemag-price-preview[data-id="' + id + '"]');
        if ( ! $el.length ) return;

        $el.text( price ).addClass('skyemag-price-updated');
        setTimeout(function () { $el.removeClass('skyemag-price-updated'); }, 700);

        // Update inc. VAT line
        var $inc = $el.closest('td').find('.skyemag-price-inc');
        if ( ! $inc.length ) return;

        // Use server value if available, otherwise recalculate client-side
        var incVal = priceInc;
        if ( ! incVal ) {
            var vatRate = parseFloat( $el.data('vat-rate') );
            if ( vatRate && vatRate > 0 ) {
                var exVat = parseFloat( price.replace(/[^0-9.-]/g, '') );
                if ( ! isNaN( exVat ) ) {
                    incVal = ( exVat * ( 1 + vatRate ) ).toFixed(2);
                }
            }
        }

        if ( incVal ) {
            // Preserve VAT% suffix if present
            var oldText = $inc.text();
            var vatMatch = oldText.match(/\(\d+%\)/);
            var suffix = vatMatch ? ' inc. VAT ' + vatMatch[0] : ' inc. VAT';
            $inc.text( incVal + suffix ).addClass('skyemag-price-updated');
            setTimeout(function () { $inc.removeClass('skyemag-price-updated'); }, 700);
        }
    }

    // ── Save All ──────────────────────────────────────────────────────────
    function initSaveAll() {
        $('#skyemag-save-all-btn').on('click', function () {
            var entries = [];
            $('.skyemag-margin-input').each(function () {
                var id  = parseInt( $(this).data('product-id'), 10 );
                var pctInput = $('.skyemag-stock-pct-input[data-product-id="' + id + '"]');
                entries.push({
                    product_id:    id,
                    margin:        $(this).val(),
                    stock_percent: pctInput.length ? pctInput.val() : null,
                });
            });

            var $btn    = $(this).prop('disabled', true);
            var $status = $('#skyemag-save-all-status').text( skyemagAdmin.i18n.saving );

            $.post( ajaxUrl, {
                action: 'skyemag_save_all',
                nonce: editNonce,
                entries: entries,
            }, function (r) {
                if ( r.success ) {
                    var msg = r.data.saved + ' ' + skyemagAdmin.i18n.saved;
                    if ( r.data.errors && r.data.errors.length ) {
                        msg += ' | ' + r.data.errors.join('; ');
                    }
                    $status.text( msg );
                } else {
                    $status.text( skyemagAdmin.i18n.error );
                }
            }).fail(function () {
                $status.text( skyemagAdmin.i18n.error );
            }).always(function () {
                $btn.prop('disabled', false);
            });
        });
    }

    // ── Bulk actions ──────────────────────────────────────────────────────
    function initBulkActions() {
        var bulkValueActions = ['set_margin', 'set_stock_pct', 'increase_margin', 'decrease_margin'];

        $(document).on('change', 'select[name="action"], select[name="action2"]', function () {
            var val     = $(this).val();
            if ( bulkValueActions.indexOf( val ) !== -1 ) {
                $('.skyemag-bulk-margin-wrap').show();
                var isStock   = val === 'set_stock_pct';
                var isDelta   = val === 'increase_margin' || val === 'decrease_margin';
                var minVal    = isStock ? 1 : ( isDelta ? 0 : -50 );
                var maxVal    = isStock ? 100 : 300;
                var placehold = isStock ? 'Stock %' : ( isDelta ? 'Delta %' : 'Margin %' );
                $('#skyemag-bulk-value')
                    .attr({ min: minVal, max: maxVal, placeholder: placehold })
                    .attr('step', isStock ? 1 : 0.01);
            } else {
                $('.skyemag-bulk-margin-wrap').hide();
            }
        });

        function currentFilterState() {
            var params = new URLSearchParams( window.location.search );
            return {
                filter_search:   params.get('s')           || '',
                filter_sync:     params.get('sync_filter') || '',
                filter_category: params.get('skyemag_cat') || '',
            };
        }

        $(document).on('click', '#doaction, #doaction2', function (e) {
            var $btn    = $(this);
            var isSec   = $btn.attr('id') === 'doaction2';
            var $select = isSec ? $('select[name="action2"]') : $('select[name="action"]');
            var action  = $select.val();

            var ajaxActions = ['enable_sync','disable_sync','set_margin','clear_margin',
                               'set_stock_pct','clear_stock_pct','sync_selected',
                               'increase_margin','decrease_margin'];
            if ( ajaxActions.indexOf(action) === -1 ) { return; }
            e.preventDefault();

            var allFiltered = $('#skyemag-all-filtered').is(':checked');
            var total       = parseInt( $('#skyemag-all-filtered').data('total') || 0, 10 );

            var payload = {
                action: 'skyemag_bulk_action',
                nonce: editNonce,
                bulk_action: action,
            };

            if ( allFiltered ) {
                if ( action === 'sync_selected' && !confirm(
                    ( skyemagAdmin.i18n.confirmSyncAll || 'Sync all %d filtered products now?' ).replace('%d', total)
                ) ) { return; }
                if ( action !== 'sync_selected' && !confirm(
                    ( skyemagAdmin.i18n.confirmBulkAll || 'Apply to all %d filtered products?' ).replace('%d', total)
                ) ) { return; }

                payload.bulk_target = 'all_filtered';
                $.extend( payload, currentFilterState() );
            } else {
                var ids = [];
                $('input[name="product_ids[]"]:checked').each(function () {
                    ids.push( parseInt( $(this).val(), 10 ) );
                });
                if ( !ids.length ) {
                    alert( skyemagAdmin.i18n.noSelection );
                    return;
                }
                if ( action === 'sync_selected' && !confirm( skyemagAdmin.i18n.confirmSync ) ) {
                    return;
                }
                payload.product_ids = ids;
            }

            var bulkValue = '';
            if ( bulkValueActions.indexOf( action ) !== -1 ) {
                bulkValue = $('#skyemag-bulk-value').val();
                if ( bulkValue === '' ) {
                    alert( skyemagAdmin.i18n.enterMargin );
                    return;
                }
            }
            payload.bulk_value = bulkValue;

            $btn.prop('disabled', true);

            $.post( ajaxUrl, payload, function (r) {
                // 3.8.0 — sync_selected enqueues to Action Scheduler and
                // returns immediately with a sync_id. Open the modal so the
                // user sees live progress while AS chews through the
                // batches. Other bulk actions still use the toast + reload
                // pattern as before.
                if ( action === 'sync_selected' && r.success && r.data && r.data.sync_id ) {
                    SkyEmagSyncProgress.openModal( r.data );
                    $btn.prop('disabled', false);
                    return;
                }

                showNotice( r.success ? r.data.message : (r.data.message || skyemagAdmin.i18n.error),
                            r.success ? 'success' : 'error' );
                if ( r.success && action !== 'sync_selected' ) {
                    setTimeout(function () { window.location.reload(); }, 1200);
                }
            }).fail(function () {
                showNotice( skyemagAdmin.i18n.error, 'error' );
            }).always(function () {
                $btn.prop('disabled', false);
            });
        });
    }

    // ── Settings page: Global Margin → Global Min Margin auto-mirror ─────
    $(document).on('input change', '#skyemag_global_margin', function () {
        var $minInput = $('#skyemag_global_min_margin');
        // Only update placeholder — don't overwrite a custom value the user typed
        $minInput.attr('placeholder', $(this).val() || '0');
    });

    // ── Test Connection (Settings page) ───────────────────────────────────
    function initPing( pingNonce ) {
        $('#skyemag-test-connection').on('click', function () {
            var $btn    = $(this).prop('disabled', true);
            var $result = $('#skyemag-ping-result').text( skyemagAdmin.i18n.saving );

            // Send current form values so unsaved credentials can be tested.
            var username = $('input[name="api_username"]').val() || '';
            var password = $('input[name="api_password"]').val() || '';

            $.post( skyemagAdmin.ajaxUrl, {
                action: 'skyemag_ping',
                nonce: pingNonce,
                username: username,
                password: password,
            }, function (r) {
                $result.text( r.success ? r.data.message : (r.data.message || skyemagAdmin.i18n.error) )
                       .css('color', r.success ? '#2271b1' : '#d63638');
            }).fail(function (xhr) {
                $result.text( skyemagAdmin.i18n.error ).css('color','#d63638');
            }).always(function () {
                $btn.prop('disabled', false);
            });
        });
    }

    // ── Type column toggle ────────────────────────────────────────────────
    function initTypeColToggle() {
        var $table = $( '.skyemag-products-table' );
        if ( ! $table.length ) { return; }

        // Build checkbox
        var stored  = localStorage.getItem( 'skyemag_show_type' );
        var visible = stored === null ? true : stored === '1';

        var $cb = $( '<label class="skyemag-type-toggle"><input type="checkbox" id="skyemag-show-type" /> Show &ldquo;Type&rdquo; column</label>' );
        $cb.find('input').prop( 'checked', visible );
        $( '.skyemag-products-wrap .search-box, .skyemag-products-wrap .subsubsub' ).last().after( $cb );

        applyTypeCol( visible );

        $cb.find('input').on( 'change', function() {
            var v = $( this ).prop('checked');
            localStorage.setItem( 'skyemag_show_type', v ? '1' : '0' );
            applyTypeCol( v );
        });
    }

    function applyTypeCol( visible ) {
        $( '.skyemag-products-table .column-type, .skyemag-products-table th.column-type' ).toggle( visible );
    }

    // ── EAN column toggle ─────────────────────────────────────────────────
    function initEanColToggle() {
        var $table = $( '.skyemag-products-table' );
        if ( ! $table.length ) { return; }

        var stored  = localStorage.getItem( 'skyemag_show_ean' );
        var visible = stored === null ? false : stored === '1';

        var $cb = $( '<label class="skyemag-type-toggle" style="margin-left:12px"><input type="checkbox" id="skyemag-show-ean" /> Show &ldquo;EAN&rdquo; column</label>' );
        $cb.find('input').prop( 'checked', visible );
        $( '#skyemag-show-type' ).closest('label').after( $cb );

        applyEanCol( visible );

        $cb.find('input').on( 'change', function() {
            var v = $( this ).prop('checked');
            localStorage.setItem( 'skyemag_show_ean', v ? '1' : '0' );
            applyEanCol( v );
        });
    }

    function applyEanCol( visible ) {
        $( '.skyemag-products-table .column-ean, .skyemag-products-table th.column-ean' ).toggle( visible );
    }

    // ── eMAG Status toggle (activate/deactivate) ──────────────────────────
    function initEmagStatusToggle() {
        $( document ).on( 'click', '.skyemag-status-toggle-btn', function() {
            var $btn       = $( this );
            var id         = parseInt( $btn.data('product-id'), 10 );
            var newStatus  = parseInt( $btn.data('new-status'), 10 );
            var nonce      = $( '#skyemag-nonce' ).val();

            $btn.prop( 'disabled', true ).text( '…' );

            $.post( ajaxurl, {
                action:      'skyemag_set_emag_status',
                nonce:       nonce,
                product_id:  id,
                emag_status: newStatus
            }, function( res ) {
                if ( res.success ) {
                    // Reload the page to reflect new status badges.
                    location.reload();
                } else {
                    alert( res.data ? res.data.message : 'Error' );
                    $btn.prop( 'disabled', false ).text( newStatus === 0 ? 'Deactivate' : 'Activate' );
                }
            }).fail( function() {
                $btn.prop( 'disabled', false );
            });
        });
    }

    // ── Publish Page ────────────────────────────────────────────────────
    function initPublishPage() {
        var nonce = $( '#skyemag-nonce' ).val();

        // Check all (top + bottom synced)
        $( '#skyemag-pub-check-all, .skyemag-pub-check-all-bottom' ).on( 'change', function() {
            var checked = $( this ).prop('checked');
            $( '.skyemag-pub-check' ).prop( 'checked', checked );
            $( '#skyemag-pub-check-all, .skyemag-pub-check-all-bottom' ).prop( 'checked', checked );
        });

        // Single publish
        $( document ).on( 'click', '.skyemag-pub-btn', function() {
            var $btn    = $( this );
            var id      = parseInt( $btn.data('product-id'), 10 );
            var $status = $btn.closest('td').find('.skyemag-pub-status');

            $btn.prop( 'disabled', true );
            $status.text( '…' );

            $.post( ajaxurl, {
                action:     'skyemag_publish_product',
                nonce:      nonce,
                product_id: id
            }, function( res ) {
                $btn.prop( 'disabled', false );
                if ( res.success ) {
                    $status.html( '<span class="skyemag-badge skyemag-badge--success">' + res.data.message + '</span>' );
                    if ( ! res.data.dry_run ) {
                        $btn.closest('tr').fadeOut( 600 );
                    }
                } else {
                    $status.html( '<span class="skyemag-badge skyemag-badge--error">' + ( res.data ? res.data.message : 'Error' ) + '</span>' );
                }
            }).fail( function() {
                $btn.prop( 'disabled', false );
                $status.text( 'Request failed.' );
            });
        });

        // Preview
        $( document ).on( 'click', '.skyemag-preview-btn', function() {
            var id = parseInt( $( this ).data('product-id'), 10 );

            $.post( ajaxurl, {
                action:     'skyemag_publish_preview',
                nonce:      nonce,
                product_id: id
            }, function( res ) {
                if ( res.success ) {
                    $( '#skyemag-preview-json' ).text( JSON.stringify( res.data.payload, null, 2 ) );
                    $( '#skyemag-preview-modal' ).show();
                } else {
                    alert( res.data ? res.data.message : 'Error' );
                }
            });
        });

        // Close modal
        $( document ).on( 'click', '.skyemag-modal-close, .skyemag-modal-overlay', function() {
            $( '#skyemag-preview-modal' ).hide();
        });

        // ── Sequential bulk publisher (shared by "Selected" and "All") ───
        function runBulkPublish( ids ) {
            if ( ! ids.length ) {
                alert( 'No products to process.' );
                return;
            }

            var $bar       = $( '#skyemag-pub-bar' );
            var $barText   = $( '#skyemag-pub-bar-text' );
            var $progress  = $( '#skyemag-pub-progress' );
            var $bulkStat  = $( '#skyemag-pub-bulk-status' );
            var total = ids.length, done = 0, ok = 0, fail = 0;

            // Disable all buttons during bulk.
            $( '#skyemag-pub-selected, #skyemag-pub-all, .skyemag-pub-btn' ).prop( 'disabled', true );
            $progress.show();
            $bar.css( 'width', '0%' );
            $barText.text( '0 / ' + total );
            $bulkStat.text( '' );

            // Process one at a time (sequential) to respect rate limits.
            function next( idx ) {
                if ( idx >= total ) {
                    $bulkStat.html(
                        '<span class="skyemag-badge skyemag-badge--success">' +
                        'Done: ' + ok + ' OK, ' + fail + ' failed' +
                        '</span>'
                    );
                    $( '#skyemag-pub-selected, #skyemag-pub-all, .skyemag-pub-btn' ).prop( 'disabled', false );
                    return;
                }

                var id = ids[ idx ];
                $.post( ajaxurl, {
                    action:     'skyemag_publish_product',
                    nonce:      nonce,
                    product_id: id
                }, function( res ) {
                    done++;
                    if ( res.success ) {
                        ok++;
                        var $row = $( 'tr[data-product-id="' + id + '"]' );
                        $row.find('.skyemag-pub-status').html( '<span class="skyemag-badge skyemag-badge--success">OK</span>' );
                        if ( ! res.data.dry_run ) {
                            $row.fadeOut( 400 );
                        }
                    } else {
                        fail++;
                        $( 'tr[data-product-id="' + id + '"] .skyemag-pub-status' )
                            .html( '<span class="skyemag-badge skyemag-badge--error">Failed</span>' );
                    }
                    var pct = Math.round( done / total * 100 );
                    $bar.css( 'width', pct + '%' );
                    $barText.text( done + ' / ' + total + ' (' + ok + ' OK, ' + fail + ' failed)' );
                    next( idx + 1 );
                }).fail( function() {
                    done++; fail++;
                    var pct = Math.round( done / total * 100 );
                    $bar.css( 'width', pct + '%' );
                    $barText.text( done + ' / ' + total + ' (' + ok + ' OK, ' + fail + ' failed)' );
                    next( idx + 1 );
                });
            }

            next( 0 );
        }

        // Publish Selected
        $( '#skyemag-pub-selected' ).on( 'click', function() {
            var ids = [];
            $( '.skyemag-pub-check:checked' ).each( function() {
                ids.push( parseInt( $( this ).val(), 10 ) );
            });
            if ( ! ids.length ) {
                alert( 'No products selected.' );
                return;
            }
            if ( ! confirm( 'Process ' + ids.length + ' product(s)?' ) ) { return; }
            runBulkPublish( ids );
        });

        // Publish All Ready
        $( '#skyemag-pub-all' ).on( 'click', function() {
            var ids = [];
            $( '.skyemag-pub-check' ).each( function() {
                ids.push( parseInt( $( this ).val(), 10 ) );
            });
            if ( ! ids.length ) {
                alert( 'No products found.' );
                return;
            }
            if ( ! confirm( 'Process ALL ' + ids.length + ' ready product(s)?' ) ) { return; }
            runBulkPublish( ids );
        });

        // Export All Payloads as JSON
        $( '#skyemag-export-json' ).on( 'click', function() {
            var $btn = $( this );
            $btn.prop( 'disabled', true ).text( 'Generating…' );

            $.post( ajaxurl, {
                action: 'skyemag_publish_export',
                nonce:  nonce
            }, function( res ) {
                $btn.prop( 'disabled', false ).text( 'Export All Payloads as JSON' );
                if ( res.success ) {
                    var json = JSON.stringify( res.data.payloads, null, 2 );
                    var blob = new Blob( [ json ], { type: 'application/json' } );
                    var url  = URL.createObjectURL( blob );
                    var a    = document.createElement( 'a' );
                    a.href     = url;
                    a.download = 'emag-dry-run-' + res.data.count + '-products.json';
                    document.body.appendChild( a );
                    a.click();
                    document.body.removeChild( a );
                    URL.revokeObjectURL( url );
                } else {
                    alert( res.data ? res.data.message : 'Error' );
                }
            }).fail( function() {
                $btn.prop( 'disabled', false ).text( 'Export All Payloads as JSON' );
                alert( 'Request failed.' );
            });
        });

        // EAN pre-check against eMAG catalogue
        $( '#skyemag-ean-precheck' ).on( 'click', function() {
            var $btn     = $( this );
            var $results = $( '#skyemag-ean-precheck-results' );
            var $status  = $( '#skyemag-pub-bulk-status' );

            // Collect EANs only from CHECKED rows.
            var eans = [];
            $( '.skyemag-pub-check:checked' ).each( function() {
                var $row = $( this ).closest('tr');
                var ean  = $row.attr('data-ean');
                if ( ean && ean !== '' ) {
                    eans.push( ean );
                }
            });

            if ( ! eans.length ) {
                alert( 'No products with EAN selected. Please check the products you want to verify.' );
                return;
            }

            $btn.prop( 'disabled', true );
            $status.text( 'Checking ' + eans.length + ' EAN(s) on eMAG…' );
            $results.hide().empty();

            $.post( ajaxurl, {
                action: 'skyemag_ean_precheck',
                nonce:  nonce,
                eans:   eans
            }, function( res ) {
                $btn.prop( 'disabled', false );
                $status.text( '' );

                if ( ! res.success ) {
                    $status.html( '<span class="skyemag-badge skyemag-badge--error">' + ( res.data ? res.data.message : 'Error' ) + '</span>' );
                    return;
                }

                var d = res.data;
                var html = '<div class="notice notice-info inline" style="padding:8px 12px;">';
                html += '<strong>EAN Check:</strong> ' + d.total + ' checked — ';
                html += '<span style="color:#155724;">' + d.found + ' exist on eMAG</span> (offer will be attached), ';
                html += '<span style="color:#0c5460;">' + d['new'] + ' new products</span> (will go to validation).';
                html += '</div>';

                $results.html( html ).show();

                // Mark rows in the table.
                $( '.skyemag-publish-table tr[data-ean]' ).each( function() {
                    var $row = $( this );
                    var ean  = $row.attr('data-ean');
                    var $eanCell = $row.find('td:nth-child(4)');

                    if ( ! ean || ean === '' ) return;

                    // Remove previous badges.
                    $eanCell.find('.skyemag-ean-check-badge').remove();

                    if ( d.results && d.results[ ean ] ) {
                        var r = d.results[ ean ];
                        if ( r.exists ) {
                            var pnk   = r.product.part_number_key || '';
                            var name  = r.product.name || '';
                            var brand = r.product.brand || '';
                            var canAdd = r.product.can_add_offer;
                            var url   = r.product.site_url || '';
                            var tip   = 'Exists on eMAG';
                            if ( pnk ) tip += ' | PNK: ' + pnk;
                            if ( brand ) tip += ' | Brand: ' + brand;
                            if ( name ) tip += ' | ' + name;
                            if ( !canAdd ) tip += ' | ⚠ Cannot add offer';
                            var badgeClass = canAdd ? 'skyemag-badge--ready' : 'skyemag-badge--error';
                            var badgeText  = canAdd ? 'Exists' : 'Exists (blocked)';
                            if ( url ) {
                                $eanCell.append( ' <a href="' + url + '" target="_blank" class="skyemag-badge ' + badgeClass + ' skyemag-ean-check-badge" title="' + tip + '" style="text-decoration:none;">' + badgeText + ' ↗</a>' );
                            } else {
                                $eanCell.append( ' <span class="skyemag-badge ' + badgeClass + ' skyemag-ean-check-badge" title="' + tip + '">' + badgeText + '</span>' );
                            }
                        } else {
                            $eanCell.append( ' <span class="skyemag-badge skyemag-badge--val-pending skyemag-ean-check-badge" title="New product — will be sent for eMAG validation">New</span>' );
                        }
                    }
                });

            }).fail( function() {
                $btn.prop( 'disabled', false );
                $status.text( 'Request failed.' );
            });
        });
    }

    // ── Buy Button Track ────────────────────────────────────────────────
    function initBBTrack() {
        $( '#skyemag-bb-track-btn' ).on( 'click', function() {
            var $btn    = $( this );
            var $status = $( '#skyemag-bb-track-status' );
            var nonce   = $( '#skyemag-settings-nonce' ).val();

            $btn.prop( 'disabled', true );
            $status.text( 'Tracking…' );

            $.post( ajaxurl, {
                action: 'skyemag_bb_track',
                nonce:  nonce
            }, function( res ) {
                $btn.prop( 'disabled', false );
                if ( res.success ) {
                    $status.html( '<span class="skyemag-badge skyemag-badge--success">' + res.data.message + '</span>' );
                } else {
                    $status.html( '<span class="skyemag-badge skyemag-badge--error">' + ( res.data ? res.data.message : 'Error' ) + '</span>' );
                }
            }).fail( function() {
                $btn.prop( 'disabled', false );
                $status.text( 'Request failed.' );
            });
        });
    }

    // ── Unlink from eMAG (Products page) ─────────────────────────────────
    function initUnlink() {
        $(document).on('click', '.skyemag-unlink', function (e) {
            e.preventDefault();
            var $link    = $(this);
            var id       = parseInt($link.data('product-id'), 10);
            var vendorId = parseInt($link.data('vendor-id'), 10);

            if (!window.confirm('Remove the eMAG mapping (offer #' + vendorId + ') from this product? The eMAG offer itself is not touched, but this product will stop syncing until it is mapped again.')) {
                return;
            }

            $link.css('pointer-events', 'none').text('…');

            $.post(ajaxUrl, {
                action: 'skyemag_unlink_product',
                nonce: editNonce,
                product_id: id,
            }, function (res) {
                if (res.success) {
                    window.location.reload();
                } else {
                    window.alert(res.data && res.data.message ? res.data.message : 'Unlink failed.');
                    $link.css('pointer-events', '').text('Unlink');
                }
            }).fail(function () {
                window.alert('Request failed.');
                $link.css('pointer-events', '').text('Unlink');
            });
        });
    }

    // ── One-click repair of duplicate eMAG mappings ──────────────────────
    function initFixDuplicates() {
        $('#skyemag-fix-duplicates').on('click', function () {
            var $btn    = $(this);
            var $status = $('#skyemag-fix-duplicates-status');

            if (!window.confirm('Unlink every wrongly mapped product (the one whose SKU matches the eMAG part_number keeps its mapping)?')) {
                return;
            }

            $btn.prop('disabled', true);
            $status.text('Repairing…');

            $.post(ajaxUrl, {
                action: 'skyemag_fix_duplicate_mappings',
                nonce: editNonce,
            }, function (res) {
                if (res.success) {
                    $status.text(res.data.message);
                    window.setTimeout(function () { window.location.reload(); }, 1500);
                } else {
                    $btn.prop('disabled', false);
                    $status.text(res.data && res.data.message ? res.data.message : 'Repair failed.');
                }
            }).fail(function () {
                $btn.prop('disabled', false);
                $status.text('Request failed.');
            });
        });
    }

    // ── Detect Field Sources ────────────────────────────────────────────
    function initDetectSources() {
        $( '#skyemag-detect-sources' ).on( 'click', function() {
            var $btn     = $( this );
            var $status  = $( '#skyemag-detect-status' );
            var $results = $( '#skyemag-detect-results' );
            var nonce    = $( '#skyemag-settings-nonce' ).val();

            $btn.prop( 'disabled', true );
            $status.text( 'Scanning products…' );
            $results.hide().empty();

            $.post( ajaxurl, {
                action: 'skyemag_detect_field_sources',
                nonce:  nonce
            }, function( res ) {
                $btn.prop( 'disabled', false );
                $status.text( '' );

                if ( ! res.success ) {
                    $status.html( '<span class="skyemag-badge skyemag-badge--error">' + ( res.data ? res.data.message : 'Error' ) + '</span>' );
                    return;
                }

                var html = '';

                // EAN results
                if ( res.data.ean.length > 0 ) {
                    html += '<strong>EAN / GTIN fields found:</strong><ul style="margin:4px 0 12px 16px;">';
                    res.data.ean.forEach( function( item ) {
                        html += '<li><code>' + item.key + '</code> — <strong>' + item.count + '</strong> products';
                        html += ' <small style="color:#666">(sample: ' + item.sample + ')</small>';
                        html += ' <button type="button" class="button-link skyemag-use-source" data-type="ean" data-key="' + item.key + '">Use this</button>';
                        html += '</li>';
                    });
                    html += '</ul>';
                } else {
                    html += '<p style="color:#856404;">No EAN/GTIN meta keys found with data.</p>';
                }

                // Brand results
                if ( res.data.brand.length > 0 ) {
                    html += '<strong>Brand fields found:</strong><ul style="margin:4px 0 0 16px;">';
                    res.data.brand.forEach( function( item ) {
                        html += '<li><code>' + item.key + '</code> (' + item.type + ') — <strong>' + item.count + '</strong> products';
                        html += ' <small style="color:#666">(sample: ' + item.sample + ')</small>';
                        html += ' <button type="button" class="button-link skyemag-use-source" data-type="brand" data-key="' + item.key + '">Use this</button>';
                        html += '</li>';
                    });
                    html += '</ul>';
                } else {
                    html += '<p style="color:#856404;">No brand meta keys found with data.</p>';
                }

                $results.html( html ).show();
            }).fail( function() {
                $btn.prop( 'disabled', false );
                $status.text( 'Request failed.' );
            });
        });

        // "Use this" button — set as first source in the dropdown
        $( document ).on( 'click', '.skyemag-use-source', function() {
            var key  = $( this ).data('key');
            var type = $( this ).data('type');
            var sel  = type === 'ean' ? '.skyemag-ean-source' : '.skyemag-brand-source';
            var $first = $( sel ).first();

            // Check if key exists in options, if not add it
            if ( $first.find( 'option[value="' + key + '"]' ).length === 0 ) {
                $first.append( '<option value="' + key + '">' + key + ' (detected)</option>' );
            }
            $first.val( key );

            // Visual feedback
            $first.css( 'background-color', '#d4edda' );
            setTimeout( function() { $first.css( 'background-color', '' ); }, 1500 );
        });
    }

    // ── Category Import ─────────────────────────────────────────────────
    $(function () {
        var $btn       = $('#skyemag-import-cats-btn');
        var $spinner   = $('#skyemag-cat-spinner');
        var $progress  = $('#skyemag-cat-progress');
        var $bar       = $('#skyemag-cat-bar');
        var $barText   = $('#skyemag-cat-bar-text');
        var $status    = $('#skyemag-cat-status');
        var $result    = $('#skyemag-cat-result');
        var $log       = $('#skyemag-cat-log');
        var importNonce  = ($('#skyemag-cat-import-nonce').val() || '');
        var progressNonce = ($('#skyemag-cat-progress-nonce').val() || '');

        if ( ! $btn.length || ! importNonce ) {
            return;
        }

        function log( msg ) {
            var ts = new Date().toLocaleTimeString();
            $log.show().append( '[' + ts + '] ' + msg + '\n' );
            $log.scrollTop( $log[0].scrollHeight );
        }

        $btn.on('click', function () {
            if ( ! confirm( 'Import all eMAG categories? This may take up to a minute.' ) ) {
                return;
            }

            $btn.prop('disabled', true);
            $spinner.css('visibility', 'visible');
            $progress.show();
            $result.hide();
            $log.show().empty();
            $bar.css({ width: '5%', background: '#2271b1' });
            $barText.text('Starting...');

            log('Starting category import...');

            // Poll progress while import runs.
            var pollTimer = setInterval(function () {
                $.post(skyemagAdmin.ajaxUrl, {
                    action: 'skyemag_cat_import_progress',
                    nonce: progressNonce
                }, function (resp) {
                    if ( ! resp.success || ! resp.data ) return;
                    var d = resp.data;
                    if ( d.phase === 'reading' && d.total > 0 ) {
                        var pct = Math.round( (d.imported / d.total) * 95 );
                        $bar.css('width', Math.max(pct, 5) + '%');
                        $barText.text( d.imported + ' / ' + d.total + ' categories' );
                        $status.text( d.allowed + ' allowed, ' + d.detailed + ' with details' );
                    }
                    if ( d.phase === 'done' ) {
                        clearInterval( pollTimer );
                    }
                });
            }, 2000);

            $.ajax({
                url: skyemagAdmin.ajaxUrl,
                method: 'POST',
                data: { action: 'skyemag_import_categories', nonce: importNonce },
                timeout: 300000,
                success: function (resp) {
                    clearInterval( pollTimer );
                    $spinner.css('visibility', 'hidden');
                    $btn.prop('disabled', false);

                    log('Response: success=' + resp.success);

                    if ( resp.success ) {
                        var s = resp.data.stats || resp.data || {};
                        log('Done: imported=' + s.imported + ', allowed=' + s.allowed + ', detailed=' + s.detailed);

                        $bar.css('width', '100%');
                        $barText.text('Done!');
                        $status.text('');
                        $result.html(
                            '<div class="notice notice-success inline" style="margin:0"><p>' +
                            (resp.data.message || 'Import complete: ' + s.imported + ' categories, ' + s.allowed + ' allowed, ' + s.detailed + ' with details.') +
                            '</p></div>'
                        ).show();

                        $('#skyemag-cat-total strong').text( s.imported || s.total || 0 );
                        $('#skyemag-cat-allowed strong').text( s.allowed || 0 );
                        $('#skyemag-cat-detailed strong').text( s.detailed || 0 );
                    } else {
                        log('ERROR: ' + (resp.data ? resp.data.message : 'Unknown'));
                        $bar.css({ width: '100%', background: '#dc3545' });
                        $barText.text('Error');
                        $result.html(
                            '<div class="notice notice-error inline" style="margin:0"><p>' +
                            (resp.data ? resp.data.message : 'Unknown error') +
                            '</p></div>'
                        ).show();
                    }
                },
                error: function (xhr, textStatus) {
                    clearInterval( pollTimer );
                    log('AJAX ERROR: ' + textStatus);
                    $spinner.css('visibility', 'hidden');
                    $btn.prop('disabled', false);
                    $bar.css({ width: '100%', background: '#dc3545' });
                    $barText.text('Error');
                    $result.html(
                        '<div class="notice notice-error inline" style="margin:0"><p>Request failed: ' + textStatus + '</p></div>'
                    ).show();
                }
            });
        });
    });

    // ── Bootstrap (eMAG offers) Import ──────────────────────────────────
    // Mirrors the Category Import pattern: a long-running AJAX request
    // does the work while a separate poll endpoint feeds the progress bar.
    $(function () {
        var $btn          = $('#skyemag-bs-import-btn');
        var $spinner      = $('#skyemag-bs-spinner');
        var $progress     = $('#skyemag-bs-progress');
        var $bar          = $('#skyemag-bs-bar');
        var $barText      = $('#skyemag-bs-bar-text');
        var $status       = $('#skyemag-bs-status');
        var $result       = $('#skyemag-bs-result');
        var $log          = $('#skyemag-bs-log');
        var importNonce   = ($('#skyemag-bs-import-nonce').val() || '');
        var progressNonce = ($('#skyemag-bs-progress-nonce').val() || '');

        if ( ! $btn.length || ! importNonce ) {
            return;
        }

        function logLine( msg ) {
            var ts = new Date().toLocaleTimeString();
            $log.show().append( '[' + ts + '] ' + msg + '\n' );
            $log.scrollTop( $log[0].scrollHeight );
        }

        function applyProgress( d ) {
            if ( ! d ) { return; }
            if ( d.phase === 'vat_cache' ) {
                $bar.css('width', '5%');
                $barText.text('Caching VAT rates...');
                $status.text('');
                return;
            }
            if ( d.phase === 'fetching' ) {
                // Bootstrap can't know the offer total upfront — show fetched so far.
                $bar.css('width', '20%');
                $barText.text( (d.fetched_offers || 0) + ' offers fetched' );
                $status.text('Reading offers from eMAG (paginated)...');
                return;
            }
            if ( d.phase === 'matching' && d.total_offers > 0 ) {
                // Matching loop is the bulk of perceived work; map to 30%-95%.
                var done = (d.processed || 0);
                var pct  = 30 + Math.round( (done / d.total_offers) * 65 );
                $bar.css('width', Math.min(95, Math.max(30, pct)) + '%');
                $barText.text( done + ' / ' + d.total_offers + ' offers matched' );
                $status.text( (d.matched || 0) + ' matched, ' + (d.unmatched || 0) + ' without WC SKU' );
                return;
            }
            if ( d.phase === 'done' ) {
                $bar.css('width', '100%');
                $barText.text('Done!');
                $status.text('');
                return;
            }
            if ( d.phase === 'error' ) {
                $bar.css({ width: '100%', background: '#dc3545' });
                $barText.text('Error');
                $status.text( d.error || '' );
                return;
            }
        }

        $btn.on('click', function () {
            if ( ! confirm( 'Import all eMAG offers and match them to WooCommerce by SKU? This may take a few minutes for large catalogues.' ) ) {
                return;
            }

            $btn.prop('disabled', true);
            $spinner.css('visibility', 'visible');
            $progress.show();
            $result.hide();
            $log.show().empty();
            $bar.css({ width: '5%', background: '#2271b1' });
            $barText.text('Starting...');

            logLine('Starting eMAG offer import...');

            // Poll progress every 2s while the long-running request runs.
            var pollTimer = setInterval(function () {
                $.post(skyemagAdmin.ajaxUrl, {
                    action: 'skyemag_bootstrap_progress',
                    nonce:  progressNonce
                }, function (resp) {
                    if ( ! resp || ! resp.success || ! resp.data ) { return; }
                    applyProgress( resp.data );
                    if ( resp.data.phase === 'done' || resp.data.phase === 'error' ) {
                        clearInterval( pollTimer );
                    }
                });
            }, 2000);

            $.ajax({
                url:     skyemagAdmin.ajaxUrl,
                method:  'POST',
                data:    { action: 'skyemag_run_bootstrap_ajax', nonce: importNonce },
                timeout: 600000,
                success: function (resp) {
                    clearInterval( pollTimer );
                    $spinner.css('visibility', 'hidden');
                    $btn.prop('disabled', false);

                    logLine('Response: success=' + !!resp.success);

                    if ( resp.success ) {
                        var s = (resp.data && resp.data.stats) || resp.data || {};
                        logLine('Done: matched=' + (s.matched || 0) + ', unmatched=' + (s.unmatched || 0) + ', skipped=' + (s.skipped || 0));

                        $bar.css('width', '100%');
                        $barText.text('Done!');
                        $status.text('');
                        $result.html(
                            '<div class="notice notice-success inline" style="margin:0"><p>' +
                            ((resp.data && resp.data.message) ||
                                ('Import complete: ' + (s.matched || 0) + ' matched, ' +
                                 (s.unmatched || 0) + ' unmatched eMAG offers, ' +
                                 (s.skipped || 0) + ' unmapped WC products.')) +
                            '</p></div>'
                        ).show();
                    } else {
                        var msg = (resp.data && resp.data.message) ? resp.data.message : 'Unknown error';
                        logLine('ERROR: ' + msg);
                        $bar.css({ width: '100%', background: '#dc3545' });
                        $barText.text('Error');
                        $result.html(
                            '<div class="notice notice-error inline" style="margin:0"><p>' + msg + '</p></div>'
                        ).show();
                    }
                },
                error: function (xhr, textStatus) {
                    clearInterval( pollTimer );
                    $spinner.css('visibility', 'hidden');
                    $btn.prop('disabled', false);
                    var hint = textStatus || ('HTTP ' + xhr.status);
                    logLine('AJAX ERROR: ' + hint);
                    $bar.css({ width: '100%', background: '#dc3545' });
                    $barText.text('Error');
                    $result.html(
                        '<div class="notice notice-error inline" style="margin:0"><p>Request failed: ' + hint + '</p></div>'
                    ).show();
                }
            });
        });
    });

    // ── Family Map ─────────────────────────────────────────────────────
    $(function () {
        var $catSelect = $('#skyemag-fammap-category');
        var $container = $('#skyemag-fammap-container');
        var $title     = $('#skyemag-fammap-title');
        var $tbody     = $('#skyemag-fammap-tbody');
        var $spinner   = $('#skyemag-fammap-spinner');
        var $saveBtn   = $('#skyemag-fammap-save-all');
        var $msg       = $('#skyemag-fammap-message');
        var loadNonce  = ($('#skyemag-fammap-load-nonce').val() || '');
        var saveNonce  = ($('#skyemag-fammap-save-nonce').val() || '');

        if ( ! $catSelect.length || ! loadNonce ) {
            return;
        }

        var $empty = $('#skyemag-fammap-empty');

        $catSelect.on('change', function () {
            var catId = $(this).val();
            if ( ! catId ) {
                $container.hide();
                $empty.show();
                return;
            }
            $empty.hide();

            $spinner.css('visibility', 'visible');
            $container.hide();
            $msg.empty();

            $.post(skyemagAdmin.ajaxUrl, {
                action: 'skyemag_load_families',
                nonce: loadNonce,
                emag_category_id: catId
            }, function (resp) {
                $spinner.css('visibility', 'hidden');
                if ( ! resp.success ) {
                    $msg.html('<div class="notice notice-error inline"><p>' + (resp.data ? resp.data.message : 'Error') + '</p></div>');
                    $container.show();
                    return;
                }

                var d = resp.data;
                $title.text( d.category_name + ' — Family Types (' + d.family_types.length + ')' );
                $tbody.empty();

                if ( d.family_types.length === 0 ) {
                    $tbody.append('<tr><td colspan="3" style="text-align:center;color:#787c82;padding:20px">No family types for this category. Only simple products can be published.</td></tr>');
                    $container.show();
                    return;
                }

                var attrOptions = '<option value="">— None —</option>';
                d.wc_attributes.forEach(function (a) {
                    attrOptions += '<option value="' + a.slug + '">' + a.label + ' [' + a.slug + ']</option>';
                });

                d.family_types.forEach(function (ft) {
                    var charList = ft.characteristics.length > 0
                        ? ft.characteristics.map(function(c) { return '<span style="background:#e8f0fe;padding:1px 6px;border-radius:3px;font-size:11px;margin-right:4px">' + escHtml(c) + '</span>'; }).join('')
                        : '<span style="color:#787c82;font-size:11px">No characteristics</span>';

                    var $row = $('<tr data-ft-id="' + ft.emag_family_type_id + '">' +
                        '<td><strong>' + escHtml(ft.emag_family_name) + '</strong><br><small style="color:#787c82">ID: ' + ft.emag_family_type_id + '</small></td>' +
                        '<td>' + charList + '</td>' +
                        '<td><select class="skyemag-fam-wc-attr" style="width:100%">' + attrOptions + '</select></td>' +
                        '</tr>');

                    if ( ft.wc_attribute ) {
                        $row.find('.skyemag-fam-wc-attr').val( ft.wc_attribute );
                    }

                    $tbody.append( $row );
                });

                $container.show();
            }).fail(function () {
                $spinner.css('visibility', 'hidden');
                $msg.html('<div class="notice notice-error inline"><p>Request failed.</p></div>');
                $container.show();
            });
        });

        $saveBtn.on('click', function () {
            var catId = $catSelect.val();
            if ( ! catId ) return;

            var mappings = [];
            $tbody.find('tr[data-ft-id]').each(function () {
                var $row = $(this);
                mappings.push({
                    emag_family_type_id: $row.data('ft-id'),
                    emag_family_name:    $row.find('td:first strong').text(),
                    wc_attribute:        $row.find('.skyemag-fam-wc-attr').val() || '',
                });
            });

            $saveBtn.prop('disabled', true).text('Saving...');
            $msg.empty();

            $.post(skyemagAdmin.ajaxUrl, {
                action: 'skyemag_save_families',
                nonce: saveNonce,
                emag_category_id: catId,
                mappings: mappings
            }, function (resp) {
                $saveBtn.prop('disabled', false).text('Save All');
                if ( resp.success ) {
                    $msg.html('<div class="notice notice-success inline" style="margin:0"><p>' + resp.data.message + '</p></div>');
                } else {
                    $msg.html('<div class="notice notice-error inline" style="margin:0"><p>' + (resp.data ? resp.data.message : 'Error') + '</p></div>');
                }
            }).fail(function () {
                $saveBtn.prop('disabled', false).text('Save All');
                $msg.html('<div class="notice notice-error inline" style="margin:0"><p>Request failed.</p></div>');
            });
        });

        function escHtml(s) {
            return $('<span>').text(s).html();
        }
    });

    // ── Characteristics Map ──────────────────────────────────────────────
    $(function () {
        var $catSelect  = $('#skyemag-charmap-category');
        var $container  = $('#skyemag-charmap-container');
        var $title      = $('#skyemag-charmap-title');
        var $tbody      = $('#skyemag-charmap-tbody');
        var $spinner    = $('#skyemag-charmap-spinner');
        var $saveBtn    = $('#skyemag-charmap-save-all');
        var $msg        = $('#skyemag-charmap-message');
        var loadNonce   = ($('#skyemag-charmap-load-nonce').val() || '');
        var saveNonce   = ($('#skyemag-charmap-save-nonce').val() || '');

        if ( ! $catSelect.length || ! loadNonce ) {
            return;
        }

        var typeLabels = { 1: 'Numeric', 2: 'Numeric+unit', 11: 'Text', 20: 'Boolean', 30: 'Resolution', 40: 'Volume', 60: 'Size' };

        var $empty = $('#skyemag-charmap-empty');

        // ── Load characteristics when category changes ──────────────
        $catSelect.on('change', function () {
            var catId = $(this).val();
            if ( ! catId ) {
                $container.hide();
                $empty.show();
                return;
            }
            $empty.hide();

            $spinner.css('visibility', 'visible');
            $container.hide();
            $msg.empty();

            $.post(skyemagAdmin.ajaxUrl, {
                action: 'skyemag_load_chars',
                nonce: loadNonce,
                emag_category_id: catId
            }, function (resp) {
                $spinner.css('visibility', 'hidden');

                if ( ! resp.success ) {
                    $msg.html('<div class="notice notice-error inline"><p>' + (resp.data ? resp.data.message : 'Error') + '</p></div>');
                    $container.show();
                    return;
                }

                var d = resp.data;
                $title.text( d.category_name + ' — Characteristics (' + d.characteristics.length + ')' );
                $tbody.empty();

                if ( d.characteristics.length === 0 ) {
                    $tbody.append('<tr><td colspan="4" style="text-align:center;color:#787c82;padding:20px">No characteristics for this category.</td></tr>');
                    $container.show();
                    return;
                }

                // Build attribute dropdown options.
                var attrOptions = '<option value="">— None —</option>';
                d.wc_attributes.forEach(function (a) {
                    attrOptions += '<option value="' + a.slug + '">' + a.label + ' [' + a.slug + ']</option>';
                });

                d.characteristics.forEach(function (c) {
                    var mandatory = c.is_mandatory ? '<span style="color:#dc3545;font-weight:700" title="Mandatory">* </span>' : '';
                    var typeName = typeLabels[c.type_id] || 'Type ' + c.type_id;

                    var $row = $('<tr data-char-id="' + c.emag_char_id + '" data-mandatory="' + c.is_mandatory + '">' +
                        '<td>' + mandatory + '<strong>' + escHtml(c.emag_char_name) + '</strong><br><small style="color:#787c82">ID: ' + c.emag_char_id + '</small></td>' +
                        '<td><select class="skyemag-char-wc-attr" style="width:100%">' + attrOptions + '</select></td>' +
                        '<td><input type="text" class="skyemag-char-default regular-text" placeholder="Default value..." style="width:100%" /></td>' +
                        '<td><span style="font-size:11px;color:#787c82">' + typeName + '</span></td>' +
                        '</tr>');

                    // Set saved values.
                    if ( c.wc_attribute ) {
                        $row.find('.skyemag-char-wc-attr').val( c.wc_attribute );
                    }
                    if ( c.default_value ) {
                        $row.find('.skyemag-char-default').val( c.default_value );
                    }

                    // Highlight mandatory rows.
                    if ( c.is_mandatory ) {
                        $row.css('background', '#fff8f0');
                    }

                    $tbody.append( $row );
                });

                $container.show();
            }).fail(function () {
                $spinner.css('visibility', 'hidden');
                $msg.html('<div class="notice notice-error inline"><p>Request failed.</p></div>');
                $container.show();
            });
        });

        // ── Save all ────────────────────────────────────────────────
        $saveBtn.on('click', function () {
            var catId = $catSelect.val();
            if ( ! catId ) return;

            var mappings = [];
            $tbody.find('tr[data-char-id]').each(function () {
                var $row = $(this);
                mappings.push({
                    emag_char_id:   $row.data('char-id'),
                    emag_char_name: $row.find('td:first strong').text(),
                    wc_attribute:   $row.find('.skyemag-char-wc-attr').val() || '',
                    is_mandatory:   parseInt($row.data('mandatory')) || 0,
                    default_value:  $row.find('.skyemag-char-default').val() || '',
                });
            });

            $saveBtn.prop('disabled', true).text('Saving...');
            $msg.empty();

            $.post(skyemagAdmin.ajaxUrl, {
                action: 'skyemag_save_chars',
                nonce: saveNonce,
                emag_category_id: catId,
                mappings: mappings
            }, function (resp) {
                $saveBtn.prop('disabled', false).text('Save All');
                if ( resp.success ) {
                    $msg.html('<div class="notice notice-success inline" style="margin:0"><p>' + resp.data.message + '</p></div>');
                } else {
                    $msg.html('<div class="notice notice-error inline" style="margin:0"><p>' + (resp.data ? resp.data.message : 'Error') + '</p></div>');
                }
            }).fail(function () {
                $saveBtn.prop('disabled', false).text('Save All');
                $msg.html('<div class="notice notice-error inline" style="margin:0"><p>Request failed.</p></div>');
            });
        });

        function escHtml(s) {
            return $('<span>').text(s).html();
        }
    });

    // ── Category Map ────────────────────────────────────────────────────
    $(function () {
        var $searchInput = $('#skyemag-catmap-emag-search');
        var $hiddenId    = $('#skyemag-catmap-emag-id');
        var $results     = $('#skyemag-catmap-emag-results');
        var $addBtn      = $('#skyemag-catmap-add-btn');
        var $msg         = $('#skyemag-catmap-message');
        var searchNonce  = ($('#skyemag-catmap-search-nonce').val() || '');
        var addNonce     = ($('#skyemag-catmap-add-nonce').val() || '');
        var deleteNonce  = ($('#skyemag-catmap-delete-nonce').val() || '');
        var searchTimer  = null;

        if ( ! $searchInput.length || ! searchNonce ) {
            return;
        }

        // Position results dropdown relative to search input.
        $searchInput.parent().css('position', 'relative');

        // ── eMAG category autocomplete ──────────────────────────────
        $searchInput.on('input', function () {
            var q = $(this).val().trim();
            $hiddenId.val('');
            clearTimeout( searchTimer );

            if ( q.length < 2 ) {
                $results.hide().empty();
                return;
            }

            searchTimer = setTimeout(function () {
                $.post(skyemagAdmin.ajaxUrl, {
                    action: 'skyemag_search_emag_cats',
                    nonce: searchNonce,
                    search: q
                }, function (resp) {
                    $results.empty();
                    if ( ! resp.success || ! resp.data || resp.data.length === 0 ) {
                        $results.append('<div style="padding:8px 12px;color:#787c82;font-size:12px">No categories found</div>');
                        $results.show();
                        return;
                    }

                    resp.data.forEach(function (cat) {
                        var $item = $('<div>')
                            .css({ padding: '6px 12px', cursor: 'pointer', fontSize: '12px', borderBottom: '1px solid #f0f0f1' })
                            .text( cat.name + ' [' + cat.emag_category_id + ']' )
                            .data('id', cat.emag_category_id)
                            .data('name', cat.name)
                            .on('mouseenter', function () { $(this).css('background', '#f0f6fc'); })
                            .on('mouseleave', function () { $(this).css('background', '#fff'); })
                            .on('click', function () {
                                $searchInput.val( cat.name );
                                $hiddenId.val( cat.emag_category_id );
                                $results.hide();
                            });
                        $results.append( $item );
                    });
                    $results.show();
                });
            }, 300);
        });

        // Close dropdown on outside click.
        $(document).on('click', function (e) {
            if ( ! $(e.target).closest('#skyemag-catmap-emag-search, #skyemag-catmap-emag-results').length ) {
                $results.hide();
            }
        });

        // ── Add mapping ─────────────────────────────────────────────
        $addBtn.on('click', function () {
            var wcId   = $('#skyemag-catmap-wc').val();
            var emagId = $hiddenId.val();

            if ( ! wcId || ! emagId ) {
                $msg.html('<span style="color:#b32d2e">Please select both a WooCommerce and eMAG category.</span>');
                return;
            }

            $addBtn.prop('disabled', true);

            $.post(skyemagAdmin.ajaxUrl, {
                action: 'skyemag_catmap_add',
                nonce: addNonce,
                wc_category_id: wcId,
                emag_category_id: emagId
            }, function (resp) {
                $addBtn.prop('disabled', false);
                if ( resp.success ) {
                    $msg.html('<span style="color:#00a32a">Mapping saved! Reloading...</span>');
                    setTimeout(function () { location.reload(); }, 800);
                } else {
                    $msg.html('<span style="color:#b32d2e">' + (resp.data ? resp.data.message : 'Error') + '</span>');
                }
            }).fail(function () {
                $addBtn.prop('disabled', false);
                $msg.html('<span style="color:#b32d2e">Request failed.</span>');
            });
        });

        // ── Delete mapping ──────────────────────────────────────────
        $(document).on('click', '.skyemag-catmap-delete', function () {
            var $btn = $(this);
            var id   = $btn.data('id');

            if ( ! confirm( 'Delete this mapping?' ) ) {
                return;
            }

            $btn.prop('disabled', true);

            $.post(skyemagAdmin.ajaxUrl, {
                action: 'skyemag_catmap_delete',
                nonce: deleteNonce,
                mapping_id: id
            }, function (resp) {
                if ( resp.success ) {
                    $btn.closest('tr').fadeOut(300, function () { $(this).remove(); });
                } else {
                    $btn.prop('disabled', false);
                    alert( resp.data ? resp.data.message : 'Error' );
                }
            }).fail(function () {
                $btn.prop('disabled', false);
                alert('Request failed.');
            });
        });
    });

    // ── Helpers ───────────────────────────────────────────────────────────
    function showNotice( message, type ) {
        var $notice = $('<div class="notice notice-' + type + ' is-dismissible"><p></p><button type="button" class="notice-dismiss"></button></div>');
        $notice.find('p').text( message );
        $notice.find('.notice-dismiss').on('click', function () { $notice.remove(); });
        $('.skyemag-products-wrap h1, .skyemag-settings h1').first().after( $notice );
    }

    // ── AWB meta box handlers ──────────────────────────────────────────────
    $( document ).on( 'click', '.skyemag-awb-issue-btn', function ( e ) {
        e.preventDefault();
        var $btn   = $( this );
        if ( $btn.is( ':disabled' ) ) return;
        if ( ! window.confirm( 'Issue AWB for this order? eMAG will set the order status to finalized.' ) ) return;

        var wcOrderId = $btn.data( 'wc-order-id' );
        var nonce     = $btn.data( 'nonce' );
        var $box      = $btn.closest( '.skyemag-awb-box' );
        var $status   = $box.find( '.skyemag-awb-status' );

        $btn.prop( 'disabled', true );
        $status.text( 'Issuing AWB…' ).css( 'color', '#2271b1' );

        $.post( ajaxUrl, {
            action:      'skyemag_awb_issue',
            nonce:       nonce,
            wc_order_id: wcOrderId
        }, function ( r ) {
            if ( r.success ) {
                $status.text( 'AWB ' + r.data.awb_emag_id + ' issued via ' + r.data.courier_name + '. Reloading…' ).css( 'color', '#00a32a' );
                setTimeout( function () { window.location.reload(); }, 800 );
            } else {
                $status.text( r.data.message ).css( 'color', '#d63638' );
                $btn.prop( 'disabled', false );
            }
        } ).fail( function () {
            $status.text( 'Network error. Try again.' ).css( 'color', '#d63638' );
            $btn.prop( 'disabled', false );
        } );
    } );

    $( document ).on( 'click', '.skyemag-awb-other-toggle', function ( e ) {
        e.preventDefault();
        $( this ).siblings( '.skyemag-awb-format-list' ).toggle();
    } );

    $( document ).on( 'click', '.skyemag-awb-print-fmt', function ( e ) {
        // Print link itself opens in new tab — also fire the set-default-format AJAX
        // so the chosen format becomes the new default (last-used auto-save).
        var $a       = $( this );
        var format   = $a.data( 'format' );
        var setNonce = $a.data( 'setfmt-nonce' );
        $.post( ajaxUrl, {
            action: 'skyemag_awb_set_default_format',
            nonce:  setNonce,
            format: format
        } );
    } );

    $( document ).on( 'click', '.skyemag-awb-refresh-btn', function ( e ) {
        e.preventDefault();
        var $btn      = $( this );
        var wcOrderId = $btn.data( 'wc-order-id' );
        var nonce     = $btn.data( 'nonce' );
        var $box      = $btn.closest( '.skyemag-awb-box' );
        var $status   = $box.find( '.skyemag-awb-status' );

        $btn.prop( 'disabled', true );
        $status.text( 'Refreshing…' ).css( 'color', '#2271b1' );

        $.post( ajaxUrl, {
            action:      'skyemag_awb_refresh_status',
            nonce:       nonce,
            wc_order_id: wcOrderId
        }, function ( r ) {
            if ( r.success ) {
                $status.text( 'Refreshed. Reloading…' ).css( 'color', '#00a32a' );
                setTimeout( function () { window.location.reload(); }, 600 );
            } else {
                $status.text( r.data.message ).css( 'color', '#d63638' );
                $btn.prop( 'disabled', false );
            }
        } ).fail( function () {
            $status.text( 'Network error.' ).css( 'color', '#d63638' );
            $btn.prop( 'disabled', false );
        } );
    } );

    $( document ).on( 'click', '.skyemag-awb-refresh-couriers', function ( e ) {
        e.preventDefault();
        var $btn    = $( this );
        var nonce   = $btn.data( 'nonce' );
        var $status = $btn.siblings( '.skyemag-awb-refresh-couriers-status' );
        $btn.prop( 'disabled', true );
        $status.text( 'Refreshing…' ).css( 'color', '#2271b1' );
        $.post( ajaxUrl, { action: 'skyemag_awb_refresh_couriers', nonce: nonce }, function ( r ) {
            if ( r.success ) {
                $status.text( r.data.count + ' couriers cached. Reloading…' ).css( 'color', '#00a32a' );
                setTimeout( function () { window.location.reload(); }, 600 );
            } else {
                $status.text( r.data.message ).css( 'color', '#d63638' );
                $btn.prop( 'disabled', false );
            }
        } );
    } );

    $( document ).on( 'click', '.skyemag-awb-refresh-addresses', function ( e ) {
        e.preventDefault();
        var $btn    = $( this );
        var nonce   = $btn.data( 'nonce' );
        var $status = $btn.siblings( '.skyemag-awb-refresh-addresses-status' );
        $btn.prop( 'disabled', true );
        $status.text( 'Refreshing…' ).css( 'color', '#2271b1' );
        $.post( ajaxUrl, { action: 'skyemag_awb_refresh_addresses', nonce: nonce }, function ( r ) {
            if ( r.success ) {
                $status.text( r.data.count + ' addresses cached. Reloading…' ).css( 'color', '#00a32a' );
                setTimeout( function () { window.location.reload(); }, 600 );
            } else {
                $status.text( r.data.message ).css( 'color', '#d63638' );
                $btn.prop( 'disabled', false );
            }
        } );
    } );

    // Setup-wizard "skipped" notice — dismissal handler.
    // The notice is rendered server-side by SettingsPage when the seller
    // clicked "Skip" in the wizard. When they click the WP-native dismiss
    // (the X), POST to admin-ajax with the dismiss nonce so the per-user
    // dismissed flag persists. Static handler — does nothing if the notice
    // is not on the page.
    $( document ).on( 'click', '[data-skyemag-skipped-notice] .notice-dismiss', function () {
        if ( ! window.skyemagAdmin || ! window.skyemagAdmin.wizardDismissNonce ) {
            return;
        }
        var data = new FormData();
        data.append( 'action', 'skyemag_setup_dismiss_notice' );
        data.append( 'nonce',  window.skyemagAdmin.wizardDismissNonce );
        fetch( window.skyemagAdmin.ajaxUrl, {
            method: 'POST',
            credentials: 'same-origin',
            body: data
        } );
    } );

    // ── 3.8.0 SkyEmagSyncProgress ──────────────────────────────────────
    // Drives both UIs:
    //   • Settings page: an inline section (#skyemag-sync-progress-wrap)
    //     pre-rendered in PHP; this module shows/hides it and updates it.
    //   • Products page: a modal overlay built on the fly the first time
    //     the user fires a bulk Sync selected now. Modal blurs the page
    //     and exposes the same progress bar / counters / log / Cancel.
    //
    // State machine: idle → running → (cancelled | complete | failed).
    // While running, a 1500 ms poll calls skyemag_sync_progress and we
    // update the DOM. We never start a second poll loop — pollTimer is
    // cleared on every transition out of running.
    var SkyEmagSyncProgress = (function () {
        var pollTimer   = null;
        var activeSyncId = '';
        var activeContext = '';   // 'inline' | 'modal'
        var $modal       = null;

        function i18n( key, fallback ) {
            if ( skyemagAdmin && skyemagAdmin.i18n && skyemagAdmin.i18n[ key ] ) {
                return skyemagAdmin.i18n[ key ];
            }
            return fallback;
        }

        function formatEta( seconds ) {
            seconds = parseInt( seconds, 10 ) || 0;
            if ( seconds <= 0 ) { return '—'; }
            if ( seconds < 60 ) { return seconds + 's'; }
            var m = Math.floor( seconds / 60 );
            var s = seconds % 60;
            return m + ':' + ( s < 10 ? '0' + s : s );
        }

        function init() {
            // Settings page button — fires a full sync.
            $( document ).on( 'click', '#skyemag-sync-now-btn', function () {
                var $btn = $( this ).prop( 'disabled', true );
                var $status = $( '#skyemag-sync-now-status' )
                    .css( 'color', '' )
                    .text( i18n( 'syncStarting', 'Starting sync…' ) );

                $.post( ajaxUrl, {
                    action: 'skyemag_sync_start',
                    nonce: $( '#skyemag-sync-start-nonce' ).val() || skyemagAdmin.syncStartNonce
                }, function ( r ) {
                    if ( ! r.success ) {
                        var msg = ( r.data && r.data.message ) ? r.data.message : i18n( 'error', 'Error' );
                        $status.css( 'color', '#d63638' ).text( msg );
                        $btn.prop( 'disabled', false );
                        return;
                    }
                    if ( r.data.already_running ) {
                        $status.css( 'color', '#996800' ).text( 'Sync already running. Reattaching to its progress.' );
                    } else {
                        $status.css( 'color', '#027200' ).text(
                            ( i18n( 'syncQueuedFmt', 'Sync queued: %1$d products in %2$d batches.' ) )
                                .replace( '%1$d', r.data.total_products )
                                .replace( '%2$d', r.data.total_batches )
                        );
                    }
                    openInline( r.data.sync_id );
                } ).fail( function () {
                    $status.css( 'color', '#d63638' ).text( i18n( 'error', 'Error' ) );
                    $btn.prop( 'disabled', false );
                } );
            } );

            // Settings page Cancel button. Modal Cancel handler is bound
            // inside renderModal so the closure captures sync_id directly.
            $( document ).on( 'click', '#skyemag-sync-cancel-btn', function () {
                if ( ! activeSyncId ) { return; }
                if ( ! confirm( i18n( 'syncConfirmCancel', 'Cancel the running sync?' ) ) ) { return; }
                cancel( activeSyncId );
            } );
        }

        function openInline( syncId ) {
            activeSyncId   = syncId;
            activeContext  = 'inline';
            $( '#skyemag-sync-progress-wrap' ).show();
            $( '#skyemag-sync-bar' ).css( 'width', '0%' );
            $( '#skyemag-sync-bar-text' ).text( '0 / 0' );
            $( '#skyemag-sync-counters' ).text( '' );
            $( '#skyemag-sync-log' ).empty();
            startPolling();
        }

        function openModal( data ) {
            activeSyncId  = data.sync_id;
            activeContext = 'modal';
            ensureModal();
            $modal.find( '.skyemag-sync-modal-title' ).text( i18n( 'syncInProgress', 'Sync in progress' ) );
            $modal.find( '.skyemag-sync-modal-bar' ).css( 'width', '0%' );
            $modal.find( '.skyemag-sync-modal-bar-text' ).text(
                '0 / ' + ( data.total_products || 0 )
            );
            $modal.find( '.skyemag-sync-modal-counters' ).text( '' );
            $modal.find( '.skyemag-sync-modal-log' ).empty();
            $modal.css( 'display', 'flex' );
            $( 'body' ).addClass( 'skyemag-sync-modal-open' );
            startPolling();
        }

        function ensureModal() {
            if ( $modal && document.body.contains( $modal[ 0 ] ) ) { return; }
            $modal = $(
                '<div class="skyemag-sync-modal-backdrop" style="display:none">' +
                  '<div class="skyemag-sync-modal" role="dialog" aria-labelledby="skyemag-sync-modal-title">' +
                    '<div class="skyemag-sync-modal-header">' +
                      '<h2 class="skyemag-sync-modal-title" id="skyemag-sync-modal-title"></h2>' +
                      '<span class="skyemag-sync-modal-eta"></span>' +
                    '</div>' +
                    '<div class="skyemag-sync-modal-bar-wrap">' +
                      '<div class="skyemag-sync-modal-bar"></div>' +
                      '<span class="skyemag-sync-modal-bar-text"></span>' +
                    '</div>' +
                    '<p class="skyemag-sync-modal-counters"></p>' +
                    '<div class="skyemag-sync-modal-log"></div>' +
                    '<div class="skyemag-sync-modal-actions">' +
                      '<button type="button" class="button button-secondary skyemag-sync-modal-cancel" style="color:#d63638;"></button>' +
                      '<button type="button" class="button button-primary skyemag-sync-modal-close" style="display:none;"></button>' +
                    '</div>' +
                  '</div>' +
                '</div>'
            );
            $( 'body' ).append( $modal );
            $modal.find( '.skyemag-sync-modal-cancel' ).text( i18n( 'syncCancel', 'Cancel' ) );
            $modal.find( '.skyemag-sync-modal-close' ).text( i18n( 'close', 'Close' ) );

            $modal.find( '.skyemag-sync-modal-cancel' ).on( 'click', function () {
                if ( ! activeSyncId ) { return; }
                if ( ! confirm( i18n( 'syncConfirmCancel', 'Cancel the running sync?' ) ) ) { return; }
                cancel( activeSyncId );
            } );
            $modal.find( '.skyemag-sync-modal-close' ).on( 'click', closeModal );
        }

        function closeModal() {
            if ( $modal ) { $modal.css( 'display', 'none' ); }
            $( 'body' ).removeClass( 'skyemag-sync-modal-open' );
            // Reload the products list on close so freshly synced rows
            // reflect their new badges/prices.
            if ( $( '.skyemag-products-wrap' ).length ) {
                setTimeout( function () { window.location.reload(); }, 400 );
            }
        }

        function startPolling() {
            stopPolling();
            tick(); // immediate fetch for responsiveness
            pollTimer = setInterval( tick, 1500 );
        }

        function stopPolling() {
            if ( pollTimer ) {
                clearInterval( pollTimer );
                pollTimer = null;
            }
        }

        function tick() {
            $.post( ajaxUrl, {
                action: 'skyemag_sync_progress',
                nonce:  skyemagAdmin.syncProgressNonce
            }, function ( r ) {
                if ( ! r.success || ! r.data ) { return; }
                if ( r.data.state === 'idle' ) {
                    stopPolling();
                    return;
                }
                renderState( r.data );
                if ( r.data.state === 'complete' || r.data.state === 'cancelled' || r.data.state === 'failed' ) {
                    stopPolling();
                    onFinished( r.data );
                }
            } );
        }

        function renderState( s ) {
            var total     = parseInt( s.total, 10 ) || 0;
            var processed = parseInt( s.processed, 10 ) || 0;
            var pct       = total > 0 ? Math.round( ( processed / total ) * 100 ) : 0;
            var eta       = formatEta( s.eta_seconds );
            var counters  = ( i18n( 'syncSummaryFmt', '%1$d synced, %2$d skipped, %3$d failed.' ) )
                .replace( '%1$d', parseInt( s.synced, 10 ) || 0 )
                .replace( '%2$d', parseInt( s.skipped, 10 ) || 0 )
                .replace( '%3$d', parseInt( s.failed, 10 ) || 0 );
            var logHTML = '';
            if ( s.recent_log && s.recent_log.length ) {
                logHTML = s.recent_log.slice().reverse().map( function ( entry ) {
                    var ts = new Date( ( entry.time || 0 ) * 1000 ).toLocaleTimeString();
                    return '[' + ts + '] ' + entry.msg;
                } ).join( '\n' );
            }

            if ( activeContext === 'inline' ) {
                $( '#skyemag-sync-bar' ).css( 'width', pct + '%' );
                $( '#skyemag-sync-bar-text' ).text( processed + ' / ' + total + ' (' + pct + '%)' );
                $( '#skyemag-sync-counters' ).text( counters );
                $( '#skyemag-sync-progress-eta' ).text( i18n( 'syncETA', 'ETA' ) + ': ' + eta );
                $( '#skyemag-sync-log' ).text( logHTML );
                $( '#skyemag-sync-log' ).scrollTop( $( '#skyemag-sync-log' )[ 0 ].scrollHeight );
            } else if ( activeContext === 'modal' && $modal ) {
                $modal.find( '.skyemag-sync-modal-bar' ).css( 'width', pct + '%' );
                $modal.find( '.skyemag-sync-modal-bar-text' ).text( processed + ' / ' + total + ' (' + pct + '%)' );
                $modal.find( '.skyemag-sync-modal-counters' ).text( counters );
                $modal.find( '.skyemag-sync-modal-eta' ).text( i18n( 'syncETA', 'ETA' ) + ': ' + eta );
                $modal.find( '.skyemag-sync-modal-log' ).text( logHTML );
                var logEl = $modal.find( '.skyemag-sync-modal-log' )[ 0 ];
                if ( logEl ) { logEl.scrollTop = logEl.scrollHeight; }
            }
        }

        function onFinished( s ) {
            var label;
            if ( s.state === 'complete' )  { label = i18n( 'syncComplete', 'Sync complete' ); }
            else if ( s.state === 'cancelled' ) { label = i18n( 'syncCancelled', 'Sync cancelled' ); }
            else                            { label = i18n( 'error', 'Sync failed' ); }

            if ( activeContext === 'inline' ) {
                $( '#skyemag-sync-progress-title' ).text( label );
                $( '#skyemag-sync-cancel-btn' ).hide();
                $( '#skyemag-sync-now-btn' ).prop( 'disabled', false );
                $( '#skyemag-sync-now-status' )
                    .css( 'color', s.state === 'complete' ? '#027200' : '#646970' )
                    .text( label );
            } else if ( activeContext === 'modal' && $modal ) {
                $modal.find( '.skyemag-sync-modal-title' ).text( label );
                $modal.find( '.skyemag-sync-modal-cancel' ).hide();
                $modal.find( '.skyemag-sync-modal-close' ).show();
            }
        }

        function cancel( syncId ) {
            $.post( ajaxUrl, {
                action:  'skyemag_sync_cancel',
                nonce:   skyemagAdmin.syncCancelNonce,
                sync_id: syncId
            } ).always( function () {
                tick();
            } );
        }

        return {
            init:       init,
            openInline: openInline,
            openModal:  openModal
        };
    }());

}(jQuery));
