
/* ============================================================
 * PS_LOG — F12 telemetria FLOW (zawsze widoczna, bez debug gate)
 * Wstawiony 2026-05-14, plugin v4.4.1
 * ============================================================ */
window.PS_LOG = window.PS_LOG || function(stage, msg, data){
    if (!window.PS_DEBUG && !(window.parcselectConfig && window.parcselectConfig.debug)) { return; }
    try {
        var ts = new Date().toISOString().substring(11,23);
        var hdr = '%c[PS-FLOW ' + ts + ']%c ' + stage + (msg ? ' %c' + msg : '');
        var s1 = 'background:#1e40af;color:#fff;padding:2px 6px;border-radius:3px;font-weight:bold';
        var s2 = 'color:#1e40af;font-weight:bold;padding-left:4px';
        var s3 = 'color:#374151';
        if (data !== undefined) {
            console.groupCollapsed(hdr, s1, s2, s3);
            try { console.log('data:', data); } catch(_){}
            try { console.log('href:', location.pathname); } catch(_){}
            console.groupEnd();
        } else {
            console.log(hdr, s1, s2, s3);
        }
    } catch(_){}
};
/**
 * Parcel Selector — WooCommerce Bridge v4.4.9
 *
 * Connects both map engines (ANUNAKI and Classic) to WooCommerce checkout.
 * - Listens for locker selection events from either map engine
 * - Sends selection to WordPress AJAX (ps_save_selection)
 * - Updates the checkout UI (selected locker card)
 * - Opens the correct map engine when "Select locker" button is clicked
 *
 * Events listened:
 *   'anunaki-point-selected'  — fired by ANUNAKI engine (detail: {name, address, city, country})
 *   'inpost-point-selected'   — fired by Classic/INTRO_1 engine (detail: {point:{...}, country})
 *
 * @package ParcelSelector
 */
/* global parcselectConfig, AnunakiPopup */
;(function ($) {
    'use strict';

    var cfg = window.parcselectConfig || {};
    window._ps_page_load_time = Date.now();
    window.PS_LOG('INIT', 'plugin loaded', {version: '4.4.9', mapEngine: cfg.mapEngine, country: cfg.defaultCountry, hasNonce: !!cfg.nonce, ajaxUrl: cfg.ajaxUrl});
    var _lastMethod = '';   // tracks last selected shipping rate in WC Blocks

    // =========================================================================
    // LAYER 6: Diagnostic Logging (F12 Console) — only when debug enabled
    // =========================================================================
    function printDiagnostics() {
        if (!cfg.debug) return;

        var statusIcon = '✅';
        var statusText = 'FREE — Unlimited';
        var pointsIcon = '✅';
        var pointsText = 'ładowane z API / Pluginu';

        var logStyle = "color: #ff6600; font-weight: bold;";
        console.log("%c=========================================", logStyle);
        console.log("%c🔌 ParcelSelector v4.4.9 — STATUS", logStyle);
        console.log("%c=========================================", logStyle);
        console.log("%s Licencja: %s", statusIcon, statusText);
        console.log("%s Punkty paczkomatów: %s", pointsIcon, pointsText);
        console.log("🌍 Silnik mapy: %s", cfg.mapEngine);
        console.log("🗺️ Kraj domyślny: %s", cfg.defaultCountry);
        console.log("%c=========================================", logStyle);

        if (cfg.diagnostics) {
            var backendLogStyle = "color: #8b5cf6; font-weight: bold;"; // Purple
            var descStyle = "color: #a78bfa; font-style: italic;"; // Lighter purple for descriptions

            console.log("%c=========================================", backendLogStyle);
            console.log("%c🧠 ZAAWANSOWANY KONTEKST BACKENDU (Odczyt z serwera dla AI i Współpracowników)", backendLogStyle);
            console.log("%c=========================================", backendLogStyle);

            var valStyle = "color:#ea580c; font-weight:bold;";
            var supported = ['PL'];
            var cartCountry = (cfg.diagnostics.customerShippingCountry || '').toUpperCase();
            var countryOk = cartCountry === '' || supported.indexOf(cartCountry) !== -1;
            var countryStyle = countryOk ? valStyle : "color:#dc2626; font-weight:bold;";

            console.log("%c🌎 Kraj klienta w koszyku: %c" + cfg.diagnostics.customerShippingCountry, backendLogStyle, countryStyle);
            if (!countryOk) {
                console.warn("⚠️ UWAGA: Kraj '" + cartCountry + "' NIE jest obsługiwany. Obsługiwane kraje: " + supported.join(', ') + ". Zmień adres wysyłki.");
            }
            console.log("%c   ↳ Znaczenie: Metoda 'Paczkomat InPost' może być przypisana przez administratora w WooCommerce tylko do wybranych krajów. Jeśli tutaj klient wybrał np. Niemcy, a admin odpalił paczkomaty tylko dla Polski — InPost ZNIKNIE z koszyka.", descStyle);

            console.log("%c📦 Aktywność wtyczki w Ustawieniach Wysyłki WC: %c" + cfg.diagnostics.isMethodGloballyEnabled, backendLogStyle, valStyle);
            console.log("%c   ↳ Znaczenie: Jeśli tu jest wartość 'no', to ktoś wszedł w Ustawienia -> Wysyłka w WooCommerce i całkowicie globalnie wyłączył naszą bramkę wysyłania (metodę parcselect_inpost_paczkomat). Dlatego w ogóle się nie wczyta.", descStyle);

            console.log("%c⚖️ Waga zawartości koszyka: %c" + cfg.diagnostics.cartWeight + " kg", backendLogStyle, valStyle);
            console.log("%c   ↳ Znaczenie: Paczki mają swoje limity gabarytowe. InPost zazwyczaj przyjmuje do ok. 25 kg. Jeśli koszyk waży ponad dozwolony limit gabarytu C, metoda celowo i słusznie zniknie z listy doręczeń.", descStyle);

            console.log("%c💰 Wartość zawartości koszyka: %c" + cfg.diagnostics.cartTotal, backendLogStyle, valStyle);
            console.log("%c   ↳ Znaczenie: Pomocne przy diagnozowaniu 'Darmowej Dostawy' ukrywającej inne metody płatne wysyłki.", descStyle);

            console.log("%c🧩 Aktywne zderzające się pluginy wysyłkowe (Conflicts): %c" + (Array.isArray(cfg.diagnostics.activeConflictingPlugins) ? cfg.diagnostics.activeConflictingPlugins.join(', ') : cfg.diagnostics.activeConflictingPlugins), backendLogStyle, valStyle);
            console.log("%c   ↳ Znaczenie: 'none' oznacza, że jest bezpiecznie. Jeśli pojawią się tu nazwy systemów ('Table Rate', 'Flexible Shipping'), to one przejmują nadzór nad wysyłkami i to w NICH klient musi skonfigurować nasz InPost. Inaczej nadpiszą natywnego InPosta i nic się nie pokaże.", descStyle);

            console.log("%c🗺️ Ilość stref WC posiadających włączony InPost: %c" + cfg.diagnostics.assignedZonesCount, backendLogStyle, valStyle);
            console.log("%c   ↳ Znaczenie: '0' oznacza, że plugin jest włączony, ale żaden kraj w sklepie nie oberwał obsługi paczkomatów! Sklep NIE BĘDZIE sprzedawać na Paczkomaty, jeśli admin nie wejdzie w Strefy Wysyłki WooCommerce i nie kliknie 'Dodaj: InPost Parcel Locker'.", descStyle);

            if (cfg.diagnostics.geoPreloadTriggered) {
                console.log("%c🌍 [Warstwa 13]: Wykryto PUSTY koszyk. Geolokalizacja wymusiła domyślny kraj dla sesji!", "color: #10b981; font-weight: bold;");
                console.log("%c   ↳ Znaczenie: Twoja strona Kasy (Checkout) nie podawała kraju klienta na starcie (częste w Multistep). Wymusiliśmy ustawienie kraju, aby WooCommerce mógł od razu naliczyć stawkę InPost i pokazać przycisk.", descStyle);
            }

            console.log("%c=========================================", backendLogStyle);
        }

        // License always active in free version.

        // Dodatkowa diagnoza czy w ogóle mamy na stronie kontener z opcjami wysyłki
        // Uruchamiamy z drobnym opoznieniem by dać czas JS/React na zbudowanie DOM.
        setTimeout(function() {
            var $inpostInput = $('input[type="radio"][value*="parcselect_inpost_paczkomat"]');
            var $shippingMethods = $('.shipping_method, .wc-block-components-shipping-rates-control');

            if ($shippingMethods.length === 0) {
                 console.log("%c🔍 [Diagnostyka DOM]: Nie wykryto żadnego formularza z metodami wysyłki (może to nie jest sekcja koszyka lub motyw je ukrywa).", logStyle);
                 return;
            }

            if ($inpostInput.length > 0) {
                console.log("%c🔍 [Diagnostyka DOM]: Wykryto opcję 'Paczkomat InPost' w koszyku. Przycisk wyboru punktu powinien zostać podpięty.", logStyle);
                if ($('.ps-selector-widget').length > 0) {
                    console.log("%c✅ [Diagnostyka DOM]: Interfejs przycisku został skutecznie wyrenderowany.", "color: #16a34a; font-weight: bold;");
                } else {
                    console.log("%c⚠️ [Diagnostyka DOM]: Interfejs przycisku JESZCZE nie został wstrzyknięty. Upewnij się, że InPost jest zaznaczoną opcją lub zmień stawkę by odświeżyć koszyk.", "color: #ca8a04; font-weight: bold;");
                }
            } else {
                console.log("%c❌ [Diagnostyka DOM]: Nie znaleziono opcji 'parcselect_inpost_paczkomat' wśród dostępnych metod. Jeśli uważasz, że powinna tu być, sprawdź ustawienia 'Stref Wysyłki' w WooCommerce.", "color: #dc2626; font-weight: bold;");
            }
        }, 3000);
        setTimeout(function() {
            var devStyle = "color: #0ea5e9; font-weight: bold;";
            console.log("%c=========================================", devStyle);
            console.log("%c🛠️ FAZA 6: ZABAWKI DEWELOPERSKIE / TESTOWANIE", devStyle);
            console.log("%c=========================================", devStyle);
            console.log("Aby mieć 100% pewności, że Cache sklepu nie psuje testów używaj: %cCTRL + F5 (Windows) / CMD + SHIFT + R (Mac)", "color:#0ea5e9; font-weight:bold; background:#e0f2fe; padding:2px 4px;");

            console.log("Wypróbuj w konsoli poniższe kody, by manualne sprawdzić silniki Map InPost:");
            console.log("%c✅ Mapa 'Anunaki' (Szybka, API Geopoint): %cwindow.AnunakiPopup.open('pl');", "color:inherit;", "color:#4ade80; font-family:monospace; background:#064e3b; padding:2px;");
            console.log("%c✅ Mapa 'Classic' (WP GEOWIDGET): %cdocument.dispatchEvent(new CustomEvent('inpost-open-map', {detail:{country:'pl'}}));", "color:inherit;", "color:#4ade80; font-family:monospace; background:#064e3b; padding:2px;");
            console.log("%c=========================================", devStyle);
        }, 2000);
    }

    // Print diagnostics on load (only when PS_DEBUG is enabled or cfg.debug is true)
    if (window.PS_DEBUG || cfg.debug) printDiagnostics();

    // =========================================================================
    // LAYER 2: Session Persistence (LocalStorage Fallback)
    // =========================================================================
    function psGetPersistedLocker() {
        try {
            var data = localStorage.getItem('parcselect_selected_locker');
            return data ? JSON.parse(data) : null;
        } catch (e) { return null; }
    }

    function psPersistLocker(locker) {
        try {
            localStorage.setItem('parcselect_selected_locker', JSON.stringify(locker));
        } catch (e) {}
    }

    // =========================================================================
    // Open map button click handler
    // =========================================================================

    $(document).on('click', '.ps-open-map', function (e) {
        e.preventDefault();
        window.PS_LOG('MAP_OPEN_CLICK', 'user kliknal .ps-open-map', {target: e.currentTarget && e.currentTarget.className});
        var engine  = $(this).data('engine') || cfg.mapEngine || 'anunaki';
        var country = $(this).data('country') || cfg.defaultCountry || 'pl';

        if ('anunaki' === engine && window.AnunakiPopup) {
            window.AnunakiPopup.open(country);
        } else if ('classic' === engine) {
            document.dispatchEvent(new CustomEvent('inpost-open-map', { detail: { country: country } }));
        } else {
            if (window.AnunakiPopup) window.AnunakiPopup.open(country);
            else document.dispatchEvent(new CustomEvent('inpost-open-map', { detail: { country: country } }));
        }
    });

    function psReportCrash(error, context) {
        if (!cfg.ajaxUrl) return;
        $.post(cfg.ajaxUrl, {
            action: 'parcselect_report_crash',
            nonce: cfg.nonce,
            error: error,
            context: context,
            engine: cfg.mapEngine
        });
    }

    // Manual fallback toggle — "Can't see the map? Enter ID manually"
    $(document).on('click', '.ps-toggle-manual', function(e) {
        e.preventDefault();
        var $link    = $(this);
        var $wrapper = $link.closest('.ps-manual-fallback').find('.ps-manual-input-wrapper');
        var isOpen   = $wrapper.is(':visible');
        $wrapper.slideToggle(200);
        var showLabel = $link.data('label-show') || $link.text();
        var hideLabel = $link.data('label-hide') || $link.text();
        $link.text(isOpen ? showLabel : hideLabel);
        if (!isOpen) $link.closest('.ps-manual-fallback').find('.ps-manual-id').focus();
    });

    $(document).on('click', '.ps-save-manual', function() {
        var $btn = $(this);
        var $input = $btn.siblings('.ps-manual-id');
        var $msg = $btn.closest('.ps-manual-input-wrapper').find('.ps-manual-msg');
        var id = $input.val().trim().toUpperCase();

        if (!id) {
            $msg.text(cfg.i18n && cfg.i18n.manualEmpty ? cfg.i18n.manualEmpty : 'Please enter a locker ID.').show();
            return;
        }
        if (id.length < 3) {
            $msg.text(cfg.i18n && cfg.i18n.manualTooShort ? cfg.i18n.manualTooShort : 'ID is too short.').show();
            return;
        }
        $msg.hide();

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

        psSaveSelection({
            name: id,
            address: '',
            city: '',
            post_code: '',
            country: cfg.defaultCountry || 'pl',
            is_custom_pickup: 0
        });

        // If user manually entered ID, the map might be broken
        psReportCrash('Manual fallback used for ID: ' + id, 'ManualFallback');
    });

    // Detect Map Load Failures
    setTimeout(function() {
        if (cfg.mapEngine === 'anunaki' && !window.AnunakiPopup) {
            psReportCrash('AnunakiPopup not found after 5s', 'InitTimeout');
        }
    }, 5000);

    // =========================================================================
    // Map engine event listeners
    // =========================================================================

    document.addEventListener('anunaki-point-selected', function (e) {
        var point = e.detail;
        window.PS_LOG('POINT_SELECTED_ANUNAKI', point && point.name ? point.name : '(empty)', point);
        if (!point || !point.name) return;
        // FIX cart classic 2026-05-14: natychmiastowy update widget na cart przed AJAX response
        try {
            if ($('body').hasClass('woocommerce-cart') || $('.woocommerce-cart-form').length) {
                var $w = $('.ps-selector-widget');
                if ($w.length) {
                    var _quickLocker = { name: point.name, address: point.address || '', city: point.city || '', country: point.country || cfg.defaultCountry || 'pl', post_code: point.postCode || point.post_code || '' };
                    $w.html(psRenderLockerHtml(_quickLocker));
                    $('.ps-manual-fallback').hide();
                }
            }
        } catch(e2) {}
        // Country MUST come from point data (PHP enforces it in ps_ajax_get_points).
        // If still missing, derive from map's current country context — never hardcode 'pl'.
        var pointCountry = point.country || (window.AnunakiPopup && window.AnunakiPopup._currentCountry) || cfg.defaultCountry || '';
        if (!pointCountry) {
            console.warn('[PS] Point ' + point.name + ' has no country! Check API data.');
        }
        psSaveSelection({
            name:             point.name,
            address:          point.address  || '',
            city:             point.city     || '',
            post_code:        point.postCode || point.post_code || '',
            country:          pointCountry,
            carrier:          point.carrier  || '',
            is_custom_pickup: point.status === 'custom_pickup' ? 1 : 0,
            selection_time:   point.selection_time || 0,
            device_type:      point.device_type || (window.PS_MOBILE ? window.PS_MOBILE.deviceType() : 'Desktop PC')
        });
    });

    document.addEventListener('inpost-point-selected', function (e) {
        var d = e.detail || {};
        var p = d.point  || {};
        window.PS_LOG('POINT_SELECTED_INPOST', p && p.name ? p.name : '(empty)', {detail: d, point: p});
        var ad = p.address_details || {};
        if (!p.name) return;
        psSaveSelection({
            name:             p.name,
            address:          ad.street  || p.address  || '',
            city:             ad.city    || p.city     || '',
            post_code:        ad.post_code || p.post_code || '',
            country:          d.country || p.country || (window.AnunakiPopup && window.AnunakiPopup._currentCountry) || cfg.defaultCountry || '',
            carrier:          p.carrier  || d.carrier  || '',
            is_custom_pickup: p._isCustomPickup ? 1 : 0,
            selection_time:   d.selection_time || 0,
            device_type:      d.device_type || (window.PS_MOBILE ? window.PS_MOBILE.deviceType() : 'Desktop PC')
        });
    });

    // =========================================================================
    // Core: send selection to WordPress AJAX and update UI
    // =========================================================================

    function psSaveSelection(locker) {
        window.PS_LOG('SAVE_REQUEST', 'POST parcselect_save_selection', locker);
        psPersistLocker(locker);
        // WC Blocks: update widget immediately (no PHP fragment mechanism)
        // Classic: widget updated by WC AJAX fragment after update_checkout (avoids flicker)
        if ($('.wc-block-checkout').length) {
            injectBlocksWidget(psRenderWidgetHtml());
        }

        $.post(cfg.ajaxUrl || '/wp-admin/admin-ajax.php', {
            action:             'parcselect_save_selection',
            nonce:              cfg.nonce || '',
            locker_name:        locker.name,
            locker_address:     locker.address,
            locker_city:        locker.city,
            locker_post_code:   locker.post_code,
            locker_country:     locker.country,
            locker_carrier:     locker.carrier || '',
            is_custom_pickup:   locker.is_custom_pickup || 0,
            selection_time:     locker.selection_time || 0,
            device_type:        locker.device_type || '',
            total_time:         Math.round((Date.now() - (window._ps_page_load_time || Date.now())) / 1000)
        })
        .done(function (response) {
            window.PS_LOG('SAVE_RESPONSE', response && response.success ? 'success' : 'fail', response);
            $('.ps-save-manual').prop('disabled', false).text(cfg.i18n && cfg.i18n.manualConfirm ? cfg.i18n.manualConfirm : 'Confirm');
            if (response && response.success) {
                if ($('form.checkout').length) $(document.body).trigger('update_checkout');
                // FIX cart classic 2026-05-14: bezposrednia podmiana widget bo /cart/ nie triggeruje update_checkout
                else if ($('body').hasClass('woocommerce-cart') || $('.woocommerce-cart-form').length) {
                    var $w_cart = $('.ps-selector-widget');
                    if ($w_cart.length && locker && locker.name) {
                        $w_cart.html(psRenderLockerHtml(locker));
                    }
                    // FIX UX 2026-05-14: hide manual fallback panel gdy paczkomat juz wybrany
                    $('.ps-manual-fallback').hide();
                }
                if (window.wp && wp.data && wp.data.dispatch && wp.data.select('wc/store/checkout')) {
                    var countryCode = (locker.country || 'pl').toLowerCase();
                    var countryName = (cfg.countryNames && cfg.countryNames[countryCode]) ? cfg.countryNames[countryCode] : countryCode.toUpperCase();
                    psSetExtensionData('parcel_selector', {
                        point: {
                            name: String(locker.name || ''),
                            address: String(locker.address || ''),
                            city: String(locker.city || ''),
                            post_code: String(locker.post_code || ''),
                            country: String(locker.country || ''),
                            country_name: String(countryName),
                            is_selected: true,
                            is_custom_pickup: !!locker.is_custom_pickup
                        }
                    });
                }
            }
        })
        .fail(function (jqXHR, textStatus) {
            window.PS_LOG('SAVE_FAIL', textStatus + ' HTTP=' + (jqXHR && jqXHR.status), {status: jqXHR && jqXHR.status, responseText: jqXHR && jqXHR.responseText && jqXHR.responseText.substring(0,500)});
            $('.ps-save-manual').prop('disabled', false).text(cfg.i18n && cfg.i18n.manualConfirm ? cfg.i18n.manualConfirm : 'Confirm');
            if (window.PS_DEBUG) {
                console.error('[PS] AJAX save_selection failed:', textStatus, jqXHR.status);
            }
        });
    }

    function psSetExtensionData(namespace, data) {
        if (!window.wp || !wp.data || !wp.data.dispatch) return;
        var checkout = wp.data.dispatch('wc/store/checkout');
        if (!checkout) return;
        if (checkout.setExtensionData) checkout.setExtensionData(namespace, data);
        else if (checkout.__internalSetExtensionData) checkout.__internalSetExtensionData(namespace, data);
    }

    function psRenderLockerHtml(locker) {
        if (!locker || !locker.name) return '';
        var countryLine = '';
        if (locker.country) {
            var country = (locker.country).toLowerCase();
            var countryName = (cfg.countryNames && cfg.countryNames[country]) ? cfg.countryNames[country] : country.toUpperCase();
            var flagCountry = country === 'uk' ? 'gb' : country;
            var flag = flagCountry.length === 2 ? flagCountry.toUpperCase().replace(/./g, function(char) { return String.fromCodePoint(char.charCodeAt(0) + 127397); }) : '';
            countryLine = '<p style="margin:6px 0 0;font-size:12px;color:#666;display:flex;align-items:center;gap:4px;"><span>' + flag + '</span> ' + psEsc(countryName) + '</p>';
        }
        var addressLine = (locker.address && locker.address !== 'Manual Entry') ? '<p style="margin:1px 0;font-size:12px;color:#444;">' + psEsc(locker.address) + '</p>' : '';
        var cityLine    = (locker.city && locker.city !== 'Manual Entry') ? '<p style="margin:1px 0;font-size:12px;color:#444;">' + psEsc(locker.city) + '</p>' : '';

        return '<div class="ps-selected-locker" style="background:#f0fdf4;border:1px solid #86efac;border-radius:10px;padding:14px 16px;">' +
            '<p style="margin:0 0 4px;font-weight:700;color:#166534;font-size:14px;">&#x2705; ' + psEsc(locker.name) + '</p>' +
            addressLine + cityLine + countryLine +
            '<button type="button" class="ps-open-map ps-change-locker button" data-engine="' + psEsc(cfg.mapEngine || 'anunaki') + '" data-country="' + psEsc(locker.country || 'pl') + '" style="margin-top:8px;width:100%;height:36px;font-size:12px;">&#x1F504; ' + psEsc((cfg.i18n && cfg.i18n.changeLocker) || 'Change locker') + '</button>' +
            '</div>';
    }

    function psEsc(str) {
        var d = document.createElement('div');
        d.textContent = str || '';
        return d.innerHTML;
    }

    function psDebug(msg) {
        if (cfg.debug) console.log('[ParcelSelector] ' + msg);
    }

    // =========================================================================
    // WC Blocks: widget HTML builder and injection helper
    // =========================================================================

    function psRenderWidgetHtml() {
        var persisted = psGetPersistedLocker();
        var engine = psEsc(cfg.mapEngine || 'anunaki');
        // Detect customer's actual shipping country from WC Blocks store
        var country = cfg.defaultCountry || 'pl';
        if (window.wp && wp.data) {
            var store = wp.data.select('wc/store/cart');
            if (store && store.getCartData) {
                var cartData = store.getCartData();
                if (cartData && cartData.shippingAddress && cartData.shippingAddress.country) {
                    country = cartData.shippingAddress.country.toLowerCase() || country;
                }
            }
        }
        var safeCountry = psEsc(country);
        var label = psEsc((cfg.i18n && cfg.i18n.selectLocker) || 'Wybierz Paczkomat');
        var inner = (persisted && persisted.name)
            ? psRenderLockerHtml(persisted)
            : '<button type="button" class="ps-open-map button alt" data-engine="' + engine + '" data-country="' + safeCountry + '">&#x1F4CD; ' + label + '</button>';
        return '<div class="ps-selector-widget" style="margin:12px 0;">' + inner + '</div>';
    }

    /**
     * Inject widget as sibling AFTER .wc-block-components-shipping-rates-control
     * (outside React tree — React will NOT remove it on re-render)
     */
    function injectBlocksWidget(html) {
        var $ratesContainer = $('.wc-block-components-shipping-rates-control').last();
        if (!$ratesContainer.length) return false;
        var $anchor = $ratesContainer.next('.ps-blocks-widget-anchor');
        if (!$anchor.length) {
            $anchor = $('<div class="ps-blocks-widget-anchor" style="margin-top:12px;"></div>');
            $ratesContainer.after($anchor);
        }
        $anchor.html(html);
        return true;
    }

    // =========================================================================
    // Optimized Watchdog: MutationObserver (Replacement for setInterval)
    // =========================================================================
    var watchdogObserver = null;

    function initOptimizedWatchdog() {
        if (watchdogObserver) return;

        watchdogObserver = new MutationObserver(function(mutations) {
            if (!$('form.checkout').length && !$('.wc-block-checkout').length) return;

            // Classic checkout: restore widget before place-order
            if ($('form.checkout').length) {
                var $radio = $('input[type="radio"][name^="shipping_method"]:checked');
                var isInpost = $radio.length && $radio.val().indexOf('parcselect_inpost_paczkomat') !== -1;

                if (isInpost && $('.ps-selector-widget').length === 0) {
                    // Debounce 150ms — widget may temporarily disappear during WC AJAX fragment update
                    clearTimeout(window._ps_watchdog_timer);
                    window._ps_watchdog_timer = setTimeout(function() {
                        var $r = $('input[type="radio"][name^="shipping_method"]:checked');
                        if (!$r.length || $r.val().indexOf('parcselect_inpost_paczkomat') === -1) return;
                        if ($('.ps-selector-widget').length > 0) return;
                        psDebug('WATCHDOG: Restoring missing widget (Classic).');
                        var $target = $('#place_order').closest('.place-order');
                        if (!$target.length) $target = $('form.checkout');
                        var persisted = psGetPersistedLocker();
                        var $w = $('<div class="ps-selector-widget" style="margin:20px 0;"></div>');
                        if (persisted) {
                            $w.html(psRenderLockerHtml(persisted));
                        } else {
                            $w.html('<button type="button" class="ps-open-map button alt" data-engine="' + psEsc(cfg.mapEngine) + '" data-country="' + psEsc(cfg.defaultCountry) + '">&#x1F4CD; ' + psEsc(cfg.i18n && cfg.i18n.selectLocker ? cfg.i18n.selectLocker : 'Select pickup point') + '</button>');
                        }
                        $target.before($w);
                    }, 150);
                }
            }

            // WC Blocks: restore anchor widget if InPost was last selected and anchor disappeared
            if ($('.wc-block-checkout').length) {
                if (_lastMethod.indexOf('parcselect_inpost_paczkomat') !== -1 && !$('.ps-blocks-widget-anchor').length) {
                    psDebug('WATCHDOG: Restoring missing widget (Blocks).');
                    injectBlocksWidget(psRenderWidgetHtml());
                }
            }
        });

        watchdogObserver.observe(document.body, { childList: true, subtree: true });
    }

    // =========================================================================
    // LAYER 7: WC Blocks store subscriber
    // Fires on every cart store change; injects/removes widget based on selected rate
    // =========================================================================
    function initWcBlocksSubscriber() {
        if (!window.wp || !wp.data || !wp.data.subscribe) return;
        var store = wp.data.select('wc/store/cart');
        if (!store) return;

        wp.data.subscribe(function() {
            var cartData = store.getCartData ? store.getCartData() : null;
            if (!cartData || !cartData.shippingRates || !cartData.shippingRates[0]) return;

            var rates = cartData.shippingRates[0].shipping_rates;
            if (!rates) return;

            var cur = '';
            for (var i = 0; i < rates.length; i++) {
                if (rates[i].selected) { cur = rates[i].rate_id; break; }
            }

            var isPs = cur.indexOf('parcselect_inpost_paczkomat') !== -1;
            var widgetExists = !!$('.ps-blocks-widget-anchor').length;

            // Skip if nothing changed
            if (cur === _lastMethod && (!isPs || widgetExists)) return;
            _lastMethod = cur;

            if (!isPs) {
                $('.ps-blocks-widget-anchor').remove();
                return;
            }

            injectBlocksWidget(psRenderWidgetHtml());
        });
    }

    // =========================================================================
    // LAYER 3/4/5: Init
    // =========================================================================

    $(document.body).on('updated_checkout', function() {
        window.PS_LOG('WC_UPDATED_CHECKOUT', 'WooCommerce odswiezyl checkout');
        var $radio = $('input[type="radio"][value*="parcselect_inpost_paczkomat"]');
        var $widget = $('.ps-selector-widget');
        if ($radio.length && $widget.length) {
            if ($radio.is(':checked')) $widget.show();
            else $widget.hide();
        }
    });

    window.addEventListener('load', function() {
        var persisted = psGetPersistedLocker();
        window.PS_LOG('WINDOW_LOAD', persisted && persisted.name ? 'persisted=' + persisted.name : 'no persisted locker', persisted);
        if (persisted && persisted.name && !$('.ps-selected-locker').length) {
            psDebug('LocalStorage recovery triggered.');
            psSaveSelection(persisted);
            if (persisted) $('.ps-manual-fallback').hide();

            // FIX cart classic 2026-05-14: po WC fragment refresh / updated_cart_totals / updated_wc_div
            // widget moze zostac wymieniony na swiezy template 'Select locker'.
            // Przywracamy stan z localStorage.
            $(document.body).on('wc_fragments_refreshed updated_cart_totals updated_wc_div updated_shipping_method', function(){
                try {
                    var _persist = psGetPersistedLocker();
                    if (_persist && _persist.name) {
                        var $w = $('.ps-selector-widget');
                        if ($w.length && $w.find('.ps-selected-locker').length === 0) {
                            $w.html(psRenderLockerHtml(_persist));
                        }
                        $('.ps-manual-fallback').hide();
                    }
                } catch(e) {}
            });
        }

        initOptimizedWatchdog();
        initWcBlocksSubscriber();
    });

})(jQuery);
