/**
 * aieo/product-variations-gallery — view script.
 *
 * Listens for the WC variation-form events (`found_variation`,
 * `reset_data`) and IF a per-variation image set is present in the
 * inlined JSON payload, swaps the WC gallery's main <img> src in place.
 *
 * What this is NOT:
 *   - A new gallery widget. The WC product-image-gallery DOM stays
 *     exactly as it is — zoom, lightbox, thumbnail strip all keep
 *     working through their existing handlers.
 *   - A replacement for the swatches runtime. The variation-form is
 *     still wired by AIEO_DMM_Swatches_Runtime; we just listen for
 *     the standard WC events it fires.
 *
 * Phase 2 (next session) is the actual block-rendered gallery. This
 * Phase 1 bridge is the smallest diff that fixes the stacked-gallery
 * bug AND ships a JSON contract the next phase can reuse.
 */
(function () {
    'use strict';

    function findGalleryRoot(form) {
        // The WC variation form lives inside `.product` in classic +
        // most block themes. Walk up to the product root and look for
        // the gallery there. Fall back to first match in the document
        // for layouts that put the form OUTSIDE `.product` (some
        // theme-builder plugins do).
        var product = form.closest('.product') || form.closest('[data-block-name="woocommerce/single-product"]');
        var gallery = product
            ? product.querySelector('.woocommerce-product-gallery, .wp-block-woocommerce-product-image-gallery')
            : null;
        return gallery || document.querySelector('.woocommerce-product-gallery, .wp-block-woocommerce-product-image-gallery');
    }

    function findPayload(form) {
        // Bridge nodes can sit anywhere on the page (template-part or
        // pattern). Locate by the product root's data-product-id when
        // present, fall back to the first bridge.
        var product = form.closest('.product') || form.closest('[data-block-name="woocommerce/single-product"]');
        var pid = product && product.getAttribute('data-product-id');
        var bridge = null;
        if (pid) {
            bridge = document.querySelector('.aieo-pdp-vg-bridge[data-product-id="' + pid + '"]');
        }
        if (!bridge) {
            bridge = document.querySelector('.aieo-pdp-vg-bridge[data-aieo-pdp-vg="1"]');
        }
        if (!bridge) { return null; }
        var node = bridge.querySelector('[data-aieo-pdp-vg-data]');
        if (!node) { return null; }
        try { return JSON.parse(node.textContent || '{}'); }
        catch (_e) { return null; }
    }

    function swapGalleryImage(gallery, url) {
        if (!gallery || !url) { return; }
        // The WC gallery wraps every slide in `.woocommerce-product-gallery__image`.
        // We only mutate the FIRST slide's <img> + its surrounding <a> href —
        // additional slides stay as-is so the thumbnail strip + zoom
        // overlay continue to point at the parent product's marketing
        // shots (intentional: the variation image takes the hero slot;
        // brand collateral stays accessible via the thumbs).
        var firstSlide = gallery.querySelector('.woocommerce-product-gallery__image, [data-thumb], li');
        if (!firstSlide) { return; }
        var img = firstSlide.querySelector('img');
        if (img) {
            img.setAttribute('src', url);
            // Update srcset to suppress fallback to the old responsive set.
            // Browsers ignore an empty srcset and fall back to src.
            img.removeAttribute('srcset');
            img.setAttribute('data-large_image', url);
        }
        var a = firstSlide.querySelector('a');
        if (a) { a.setAttribute('href', url); }
        // Notify any listeners (custom theme zoom plugins etc.) that the
        // image changed. The standard WC custom event is `wc_gallery_changed`.
        try { gallery.dispatchEvent(new CustomEvent('wc_gallery_changed', { bubbles: true })); } catch (_e) {}
    }

    function detachLegacyHandlers(form, gallery) {
        // OM PPE's variations-gallery JS binds to the form using a
        // jQuery event namespace `.omPPEVariationsGallery` and creates
        // SIBLING `<div class="om-ppe-variant-gallery-{id}">` nodes
        // beside the WC gallery. That sibling-creation is the source
        // of the stacked-galleries bug. With this bridge in place we
        // own the variation→image swap, so:
        //   1. detach OM's namespaced jQuery handlers,
        //   2. remove any siblings it managed to inject before our
        //      view.js loaded (in race conditions where OM's JS
        //      enqueues earlier).
        if (window.jQuery) {
            window.jQuery(form).off('.omPPEVariationsGallery');
        }
        if (gallery && gallery.parentElement) {
            gallery.parentElement
                .querySelectorAll('[class*="om-ppe-variant-gallery-"]')
                .forEach(function (el) { el.remove(); });
            // Also clear OM's "hidden" marker on the original — it sets
            // `om-ppe-gallery-hidden` to display:none when its sibling
            // is the active one. Now that the sibling is gone the
            // original needs to come back.
            gallery.classList.remove('om-ppe-gallery-hidden');
        }
    }

    function bindForm(form) {
        if (form.dataset.aieoPdpVgBound === '1') { return; }
        form.dataset.aieoPdpVgBound = '1';

        var payload = findPayload(form);
        if (!payload || !payload.variations) { return; }
        var gallery = findGalleryRoot(form);
        if (!gallery) { return; }

        detachLegacyHandlers(form, gallery);

        // jQuery path — what the WC variation form has used since
        // forever. We piggyback rather than replacing.
        if (window.jQuery) {
            window.jQuery(form).on('found_variation.aieoPdpVg', function (_e, variation) {
                if (!variation || !variation.variation_id) { return; }
                var images = payload.variations[String(variation.variation_id)] || [];
                if (images.length) {
                    swapGalleryImage(gallery, images[0]);
                }
            });
            window.jQuery(form).on('reset_data.aieoPdpVg', function () {
                if (payload.reset_image_url) {
                    swapGalleryImage(gallery, payload.reset_image_url);
                }
            });
        }

        // IAPI path — when the swatches runtime is in IAPI mode it
        // dispatches a `aieo:variation:selected` CustomEvent on the
        // form so non-jQuery listeners can react. (Mirror in the swatches
        // IAPI module — currently emits via the existing jQuery shim, so
        // both branches fire today; keeping this listener in the bridge
        // means we won't have to revisit when the runtime drops jQuery.)
        form.addEventListener('aieo:variation:selected', function (e) {
            var vid = e && e.detail && e.detail.variation_id;
            if (!vid) { return; }
            var images = payload.variations[String(vid)] || [];
            if (images.length) {
                swapGalleryImage(gallery, images[0]);
            }
        });
    }

    function init() {
        // Standard variations form — one per page.
        document.querySelectorAll('.variations_form').forEach(bindForm);
    }

    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', init);
    } else {
        init();
    }

    // Re-bind if the form is re-rendered (theme switchers, AJAX product
    // refresh — uncommon but cheap to defend against).
    var mo = new MutationObserver(function () {
        document.querySelectorAll('.variations_form').forEach(bindForm);
    });
    mo.observe(document.body, { childList: true, subtree: true });
})();
