/**
 * AIEO Box Now AJAX throttle (client-side).
 *
 * Box Now's blocks JS (`box-now-delivery-blocks.js`) subscribes to
 * `wp.data.subscribe()` and calls `updateLockerDetails()` on every
 * redux state change → that POSTs to `admin-ajax.php` with action
 * `bndp_set_boxnow_locker`. WC blocks fires hundreds of state changes
 * per second on hydration, so the browser hammers admin-ajax with
 * dozens of identical requests, and the upstream rate limiter
 * responds with 429 (Too Many Requests). Eventually 504s when the
 * limiter holds connections open.
 *
 * Box Now's plugin has no rate-limiting and we can't modify its files
 * (plugin updates would overwrite). The cleanest non-invasive fix is
 * to wrap `window.fetch` and short-circuit duplicate calls within a
 * short window.
 *
 * Logic:
 *   - Match POSTs to admin-ajax.php with body containing
 *     `action=bndp_set_boxnow_locker`.
 *   - Extract the locker_id.
 *   - If the same locker_id was sent in the last ~2.5s, return a
 *     fake successful Response without hitting the network.
 *   - Otherwise pass through.
 *
 * Idempotent because Box Now's handler (when it does run, via the
 * first call in the burst) just stores locker_id in WC session — it's
 * the same locker_id every time so subsequent stores are a no-op.
 *
 * Loads on every cart/checkout page where Box Now's blocks JS would
 * also load, with priority that ensures our wrapper installs before
 * Box Now starts firing.
 *
 * @package ai-eshop-optimizer
 * @since 5.3
 */
(function () {
    'use strict';

    if (typeof window === 'undefined' || !window.fetch) { return; }
    if (window.__aieoBoxNowThrottleInstalled) { return; }
    window.__aieoBoxNowThrottleInstalled = true;

    var TARGET_ACTION = 'action=bndp_set_boxnow_locker';
    var WINDOW_MS = 2500;
    var lastByLocker = {}; // { locker_id: timestamp_ms }

    function extractLockerId(body) {
        if (!body) { return ''; }
        var match = String(body).match(/(?:^|&)locker_id=([^&]*)/);
        return match ? decodeURIComponent(match[1]) : '';
    }

    function fakeSuccessResponse() {
        // Match Box Now's handler shape — it returns
        // `wp_send_json_success(...)` which is `{success:true, data:...}`.
        var body = JSON.stringify({ success: true, data: { throttled: 'client' } });
        return new Response(body, {
            status: 200,
            headers: { 'Content-Type': 'application/json' }
        });
    }

    var originalFetch = window.fetch.bind(window);

    window.fetch = function (input, init) {
        try {
            var url = '';
            var body = '';
            var method = '';

            if (typeof input === 'string') {
                url = input;
            } else if (input && typeof input.url === 'string') {
                url = input.url;
                if (input.method) { method = String(input.method).toUpperCase(); }
            }
            if (init) {
                if (init.method) { method = String(init.method).toUpperCase(); }
                if (init.body) {
                    body = (typeof init.body === 'string') ? init.body : '';
                }
            }

            var isAdminAjax = url.indexOf('/wp-admin/admin-ajax.php') !== -1;
            var isPost = method === 'POST' || (!method && body); // body-but-no-method ⇒ POST in practice
            var isBoxNow = isAdminAjax && isPost && body.indexOf(TARGET_ACTION) !== -1;

            if (isBoxNow) {
                var locker = extractLockerId(body);
                if (locker) {
                    var now = Date.now();
                    var last = lastByLocker[locker] || 0;
                    if ((now - last) < WINDOW_MS) {
                        // Suppress — within dedupe window.
                        return Promise.resolve(fakeSuccessResponse());
                    }
                    lastByLocker[locker] = now;
                }
            }
        } catch (e) { /* swallow — never break fetch */ }

        return originalFetch(input, init);
    };
})();
