import Vue from 'vue';
import { ready, slideDown, slideUp, slideFadeToggle } from '@site/js/utils/dom.js';
import { showHideMenus } from '@site_scripts/mtc_menu.js';

/**
 * Product page (vanilla front-end copy).
 *
 * Used by every `/item/...` page. Contains:
 *   - The `<product-options>` Vue component (strength + size selection,
 *     price display, mobile-overlay open/close).
 *   - The `<product-cta-box>` Vue component (sticky "buy now" sidebar
 *     that syncs prices via EventBus).
 *   - DOM glue at the bottom of the file for the item-back button,
 *     description accordion, item-strengths / sizes change events,
 *     mobile doctor items slide-toggle, product side tabs, and the
 *     sticky product nav.
 *
 * Previously used the Waypoints scroll plugin for sticky-nav and tab
 * scroll-spy; that has been replaced with IntersectionObserver here.
 * The CSS sticky-kit ("stick_in_parent") has been replaced with
 * `position: sticky` toggled via inline style.
 */

// ---- helpers --------------------------------------------------------------

function smoothScrollTo(top, duration = 1200) {
    // Match the legacy 200ms pre-delay then animate.
    window.setTimeout(() => {
        window.scrollTo({ top, behavior: 'smooth' });
    }, 200);
}

function elementTop(el) {
    if (!el) return 0;
    return el.getBoundingClientRect().top + window.scrollY;
}

let stickyNavObserver = null;
let tabSectionObserver = null;

function disconnectStickyObservers() {
    stickyNavObserver?.disconnect();
    stickyNavObserver = null;
    tabSectionObserver?.disconnect();
    tabSectionObserver = null;
}

// ---- Vue: <product-options> ----------------------------------------------

Vue.component('productOptions', {
    props: [
        'item_strengths',
        'selected_item',
        'assessment_complete',
        'item_warning',
        'product_overlay_enabled',
    ],
    data() {
        return {
            strengths: [],
            selectedStrengthIndex: 0,
            selectedSizeIndex: 0,
            selectedStrength: false,
            selectedSize: false,
            price: 0,
            salePrice: 0,
            savingPrice: 0,
            useSelects: true,
            item: false,
            saleActive: false,
            stock: 0,
            loading: true,
            mobileMenuActive: false,
            mobileMenuTimer: null,
            mobileView: false,
            has_assessment_form: false,

            displayPriceString: '£0.00',
            displaySalePriceString: '£0.00',
            displaySavingPriceString: '£0.00',

            // true → show a mobile overlay to select options
            // false → show the options directly on the page at mobile
            mobileOverlayEnabled: false,
        };
    },
    created() {
        if (typeof this.product_overlay_enabled !== 'undefined') {
            this.mobileOverlayEnabled = this.product_overlay_enabled;
        }
        if (typeof this.item_strengths !== 'undefined') {
            this.strengths = this.item_strengths;
        }
        if (typeof this.selected_item !== 'undefined') {
            this.item = this.selected_item;
            this.stock = this.item.stock;
        }
        this.has_assessment_form = !this.assessment_complete;

        this.$nextTick(() => {
            window.EventBus.$emit('updatePriceData', this.$data);
        });
    },

    mounted() {
        this.radiosRequireButton();
        this.triggerSelects();
        this.isMobileView();

        this._onResize = () => {
            this.radiosRequireButton();
            this.triggerSelects();
            this.toggleMobileMenu(true);
            this.isMobileView();
        };
        window.addEventListener('resize', this._onResize);

        this.$nextTick(() => {
            this.loading = false;
            window.EventBus.$emit('priceDataReady', true);
        });

        this.setSelectedStrength();

        // Sticky product images — replaces the previous jquery-sticky-kit
        // wiring with CSS `position: sticky` + a resize watcher to toggle
        // it on/off at the same 980px breakpoint the kit used.
        if (document.querySelector('.productSticky')) {
            this.$nextTick(() => {
                const stickyImages = document.querySelector('.productSticky .itemImages');
                const navigationOffset = 146;

                const applySticky = () => {
                    if (!stickyImages) return;
                    if (window.innerWidth > 980) {
                        stickyImages.style.position = 'sticky';
                        stickyImages.style.top = `${navigationOffset}px`;
                    } else {
                        stickyImages.style.position = '';
                        stickyImages.style.top = '';
                    }
                };
                applySticky();
                this._onProductStickyResize = applySticky;
                window.addEventListener('resize', this._onProductStickyResize);
            });
        }

        this.$nextTick(() => {
            window.mtcOverlay('.js_overlayTrigger');
        });

        if (this.mobileOverlayEnabled) {
            document.body.classList.add('mobileOverlayEnabled');
        } else {
            document.body.classList.add('mobileOverlayDisabled');
        }
    },

    beforeDestroy() {
        if (this._onResize) window.removeEventListener('resize', this._onResize);
        if (this._onProductStickyResize) window.removeEventListener('resize', this._onProductStickyResize);
    },

    computed: {
        displayPrice() {
            let prefix = '';
            if (this.has_assessment_form) {
                prefix = '<span class="fromPrefix">From</span>';
            }
            let p = '';
            if (this.saleIsActive()) {
                p = prefix + ' £' + this.formatPrice(this.sale_price);
                if (this.price > this.sale_price) {
                    this.savingPrice = this.price - this.sale_price;
                    this.displaySavingPriceString = ' £' + this.formatPrice(this.savingPrice);
                } else {
                    this.savingPrice = 0;
                    this.displaySavingPriceString = ' £' + this.formatPrice(this.savingPrice);
                }
            } else {
                p = prefix + ' £' + this.formatPrice(this.price);
                this.savingPrice = 0;
                this.displaySavingPriceString = ' £' + this.formatPrice(this.savingPrice);
            }
            this.displayPriceString = p;
            return p;
        },

        displaySalePrice() {
            const p = this.saleIsActive() ? '£' + this.formatPrice(this.price) : '£0.00';
            this.displaySalePriceString = p;
            return p;
        },
    },

    methods: {
        scrollToOptions() {
            if (this.redirectTo) {
                window.location = this.redirectTo;
                return;
            }

            const options = document.querySelector('.itemOptions');
            if (!options) return;

            let barOffset = 0;
            const sectionNav = document.getElementById('itemSectionNav');
            if (sectionNav && sectionNav.offsetParent !== null) {
                barOffset = sectionNav.offsetHeight + 16;
            }

            smoothScrollTo(elementTop(options) - barOffset, 1200);
        },

        formatPrice(price) {
            if (!price) return '0.00';
            // Truncate to 2 dp without rounding — matches the legacy
            // toFixed(3).slice(0,-1) trick.
            return parseFloat(price).toFixed(3).slice(0, -1);
        },

        displaySizePrice(size) {
            const prefix = this.has_assessment_form ? '<span class="fromPrefix">From</span>' : '';
            if (this.sizeSaleIsActive(size)) {
                return prefix + ' £' + this.formatPrice(size.sale_price);
            }
            return prefix + ' £' + this.formatPrice(size.price);
        },

        displaySizeSalePrice(size) {
            if (this.sizeSaleIsActive(size)) {
                return '£' + this.formatPrice(size.price);
            }
            return '£0.00';
        },

        displayStrengthPrice(index) {
            let strength = this.selectedStrength;
            if (typeof index !== 'undefined') {
                strength = this.strengths[index];
            }
            const prefix = this.has_assessment_form ? '<span class="fromPrefix">From</span>' : '';

            if (typeof strength.sizes[0] !== 'undefined') {
                const size = strength.sizes[0];
                if (this.strengthSaleIsActive(strength)) {
                    return prefix + ' £' + this.formatPrice(size.sale_price);
                }
                return prefix + ' £' + this.formatPrice(size.price);
            }
            return prefix + ' £' + this.formatPrice(this.item.price);
        },

        displayStrengthSalePrice(index) {
            let strength = this.selectedStrength;
            if (typeof index !== 'undefined' && typeof this.strengths[index] !== 'undefined') {
                strength = this.strengths[index];
            }
            if (this.strengthSaleIsActive(strength) && typeof strength.sizes[0] !== 'undefined') {
                return '£' + this.formatPrice(strength.sizes[0].price);
            }
            return '£0.00';
        },

        isMobileView() {
            if (!this.mobileOverlayEnabled) return false;
            this.mobileView = window.innerWidth <= 980;
            return undefined;
        },

        toggleMobileMenu(close) {
            window.clearTimeout(this.mobileMenuTimer);

            if (this.mobileMenuActive || close) {
                this.mobileMenuActive = false;
                this.mobileMenuTimer = window.setTimeout(() => {
                    const siteInner = document.querySelector('.siteInnerWrapper');
                    const sectionNav = document.getElementById('itemSectionNav');
                    if (siteInner) siteInner.style.zIndex = '3';
                    if (sectionNav) sectionNav.style.zIndex = '9999999';
                }, 400);
            } else {
                this.mobileMenuActive = true;
                this.mobileMenuTimer = window.setTimeout(() => {
                    const siteInner = document.querySelector('.siteInnerWrapper');
                    const sectionNav = document.getElementById('itemSectionNav');
                    if (siteInner) siteInner.style.zIndex = '999999';
                    if (sectionNav) sectionNav.style.zIndex = '4';
                }, 0);
            }
        },

        updatePrices() {
            const size = this.selectedSize;
            const price = size.price;
            const salePrice = size.sale_price;

            this.stock = size.stock;
            this.price = price;
            this.sale_price = salePrice;

            this.$nextTick(() => {
                window.EventBus.$emit('updatePriceData', this.$data);
            });
        },

        saleIsActive() {
            this.saleActive = this.sale_price < this.price && this.sale_price > 0;
            return this.saleActive;
        },

        sizeSaleIsActive(size) {
            const salePrice = parseFloat(size.sale_price);
            const price = parseFloat(size.price);
            return salePrice < price && salePrice > 0;
        },

        strengthSaleIsActive(inputStrength) {
            const strength = typeof inputStrength !== 'undefined' ? inputStrength : this.selectedStrength;
            if (!strength) return false;
            const size = strength.sizes[0];
            if (!size) return false;
            const salePrice = parseFloat(size.sale_price);
            const price = parseFloat(size.price);
            return salePrice < price && salePrice > 0;
        },

        triggerSelects() {
            if (!this.mobileOverlayEnabled) {
                this.useSelects = true;
                return;
            }
            this.useSelects = window.innerWidth <= 980;
        },

        setSelectedStrength() {
            if (this.strengths) {
                this.selectedStrength = this.strengths[this.selectedStrengthIndex];
            }
            this.setSelectedQuantity();
        },

        setSelectedQuantity(index) {
            this.selectedSizeIndex = typeof index !== 'undefined' ? index : 0;
            if (typeof this.selectedStrength !== 'undefined' && this.selectedStrength
                && Object.prototype.hasOwnProperty.call(this.selectedStrength, 'sizes')) {
                this.selectedSize = this.selectedStrength.sizes[this.selectedSizeIndex];
            }
            this.updatePrices();
        },

        // Check if a radio "reveal" button is needed (more than one row of options).
        radiosRequireButton() {
            document.querySelectorAll('.itemOptions .selectionRows').forEach((row) => {
                const list = row.querySelector('.buttonList');
                if (!list) return;
                const reveal = row.querySelector('.reveal');
                const radioReveal = row.querySelector('.radioReveal');
                const firstItem = list.querySelector('li');
                if (!firstItem) return;

                const targetHeight = list.offsetHeight - 8;
                const labelHeight = firstItem.offsetHeight;

                if (targetHeight > labelHeight) {
                    if (reveal) reveal.style.display = '';
                    if (radioReveal) {
                        radioReveal.style.height = `${labelHeight}px`;
                        radioReveal.classList.remove('open');
                    }
                } else {
                    if (reveal) reveal.style.display = 'none';
                    if (radioReveal) radioReveal.style.height = 'auto';
                }
            });
        },
    },
});

// ---- Vue: <product-cta-box> ----------------------------------------------

Vue.component('product-cta-box', {
    props: [
        'selected_item',
        'assessment_complete',
        'item_name',
    ],
    data() {
        return {
            item: false,
            saleActive: false,
            stock: 0,
            loading: true,
            has_assessment_form: false,

            savingPrice: 0,
            price: 0,
            salePrice: 0,

            displaySavingPriceString: '£0.00',
            displayPriceString: '£0.00',
            displaySalePriceString: '£0.00',

            navPricingReady: false,
        };
    },
    created() {
        if (typeof this.selected_item !== 'undefined') {
            this.item = this.selected_item;
            this.stock = this.item.stock;
        }
        this.has_assessment_form = !this.assessment_complete;

        window.EventBus.$on('updatePriceData', (data) => {
            this.updateData(data);
            this.loading = false;
            // No Waypoint.refreshAll() — IntersectionObserver self-updates.
        });

        window.EventBus.$on('priceDataReady', (isReady) => {
            this.navPricingReady = isReady;
        });
    },

    methods: {
        updateData(data) {
            Object.keys(this.$data).forEach((key) => {
                if (key !== 'navPricingReady') {
                    this.$data[key] = null;
                }
            });
            Object.entries(data).forEach((entry) => Vue.set(this.$data, entry[0], entry[1]));
        },

        scrollToOptions() {
            const options = document.querySelector('.itemOptions');
            if (!options) return;
            smoothScrollTo(elementTop(options), 1200);
        },
    },
});

// ---- DOM glue at document ready ------------------------------------------

ready(() => {

    // Image zoom — vanilla (see core/js/plugins/mtc_zoom.js). Guard prevents
    // double-init when the .zoom container already exists.
    const zoomTargets = document.querySelectorAll('.enableZoom');
    const zoomAlreadyInited = document.querySelector('.enableZoom .zoom');
    if (!zoomAlreadyInited && zoomTargets.length) {
        window.mtcZoom('.enableZoom', {
            hideMessageOnLaunch: true,
            paddingOffset: 0,
            message: '<i class="far fa-search-plus"></i>',
        });
    }

    // Item back button.
    document.querySelectorAll('.itemBackButton').forEach((btn) => {
        btn.addEventListener('click', (event) => {
            event.preventDefault();
            window.history.back();
        });
    });

    // Description accordion.
    if (document.querySelector('.accordionWrapper')) {
        document.querySelectorAll('.accordionContent').forEach((c) => {
            c.style.display = 'none';
            c.classList.remove('accordionContentOpen');
        });
        document.querySelectorAll('.accordionOpen .accordionContent').forEach((c) => {
            c.style.display = '';
            c.classList.add('accordionContentOpen');
        });

        document.querySelectorAll('.accordionHeading').forEach((heading) => {
            heading.addEventListener('click', () => {
                document.querySelectorAll('.accordionContentWrap').forEach((w) => w.classList.remove('accordionOpen'));
                document.querySelectorAll('.accordionHeading').forEach((h) => h.classList.remove('accordionHeadingOpen'));

                // Slide up any other open content within the same accordion wrapper.
                const wrapper = heading.closest('.accordionWrapper');
                wrapper?.querySelectorAll('.accordionContent').forEach((c) => {
                    if (c.offsetHeight > 0) slideUp(c);
                });

                const next = heading.nextElementSibling;
                const isHidden = !next || next.offsetParent === null;

                if (isHidden && next) {
                    heading.classList.add('accordionHeadingOpen');
                    slideDown(next);
                    // Wait until the slide animation might be done before
                    // tagging the parent open (matches legacy callback).
                    window.setTimeout(() => {
                        heading.parentElement?.classList.add('accordionOpen');
                    }, 320);
                }
            });
        });
    }

    // Colour-linked items dropdown.
    document.body.addEventListener('change', (event) => {
        const select = event.target instanceof Element ? event.target.closest('#colourLinkedItems') : null;
        if (!select) return;
        const opt = select.options[select.selectedIndex];
        const link = opt?.dataset?.link;
        if (link) {
            window.location.href = link;
        }
    });

    // Item strengths / sizes wiring.
    const itemStrengths = document.querySelectorAll('.itemStrengths');
    if (itemStrengths.length) {
        const onStrengthsChange = (event) => {
            const selectedSize = document.getElementById('selectedSize');
            if (selectedSize) selectedSize.value = '';
            document.querySelectorAll('.sizeQuantities').forEach((q) => { q.style.display = 'none'; });
            const target = document.getElementById('sizeQuantities_' + event.target.value);
            if (target) target.style.display = '';
            document.querySelectorAll('.itemSizes').forEach((sel) => {
                sel.value = '';
                sel.dispatchEvent(new CustomEvent('chosen:updated'));
            });
        };
        const onSizesChange = (event) => {
            const selectedSize = document.getElementById('selectedSize');
            if (selectedSize) selectedSize.value = event.target.value;
        };
        itemStrengths.forEach((s) => s.addEventListener('change', onStrengthsChange));
        // Initial trigger to seed selectedSize from current strength.
        itemStrengths[0]?.dispatchEvent(new Event('change'));
        document.querySelectorAll('.itemSizes').forEach((sel) => {
            sel.addEventListener('change', onSizesChange);
            sel.dispatchEvent(new Event('change'));
            sel.dispatchEvent(new CustomEvent('chosen:updated'));
        });
    }

    // Strengths → cascades to first sizes in the matching .sizeQuantities row.
    document.querySelectorAll('.itemStrengths').forEach((s) => {
        s.addEventListener('change', (event) => {
            const wrap = document.getElementById('sizeQuantities_' + event.target.value);
            wrap?.querySelectorAll('.itemSizes').forEach((sel) => {
                sel.dispatchEvent(new Event('change'));
            });
        });
    });

    // Sizes → update the displayed price in .addToBasketWrap .itemPriceWrap.
    document.querySelectorAll('.itemSizes').forEach((sel) => {
        sel.addEventListener('change', (event) => {
            const selected = event.target.options?.[event.target.selectedIndex];
            if (!selected) return;
            let productPrice = parseFloat(selected.dataset.price);
            const salePrice = parseFloat(selected.dataset.salePrice);
            if (!Number.isNaN(salePrice) && salePrice > 0) {
                productPrice = salePrice;
            }
            if (!Number.isNaN(productPrice)) {
                document.querySelectorAll('.addToBasketWrap .itemPriceWrap').forEach((wrap) => {
                    wrap.innerHTML = `<span class="priceNow">&pound;${productPrice.toFixed(2)}</span>`;
                });
            }
        });
    });

    // Re-fire change on the first strengths select to seed initial state.
    itemStrengths[0]?.dispatchEvent(new Event('change'));

    // Mobile doctor items trigger — slide-fade the inner form.
    document.querySelectorAll('.mobileDoctorItemTrigger .button').forEach((btn) => {
        btn.addEventListener('click', (event) => {
            event.preventDefault();
            btn.closest('.buttonWrapper')?.classList.add('optionsOpen');
            const innerForm = document.querySelector('.innerDoctorWrap .innerForm');
            if (!innerForm) return;
            slideFadeToggle(innerForm);

            // Settle handler — mirrors the post-animation logic from the
            // legacy slideFadeToggle callback.
            window.setTimeout(() => {
                const wrap = document.querySelector('.innerDoctorWrap .buttonWrapper');
                if (wrap?.classList.contains('optionsOpen')) {
                    innerForm.style.overflow = 'visible';
                }
                const isVisible = innerForm.offsetParent !== null && getComputedStyle(innerForm).display !== 'none';
                document.body.classList.toggle('productFlyoutOpen', isVisible);
            }, 350);
        });
    });

    // Close mobile sidebar window.
    document.querySelectorAll('.innerDoctorWrap .close').forEach((closeBtn) => {
        closeBtn.addEventListener('click', (event) => {
            event.preventDefault();
            const buttonWrapper = document.querySelector('.innerDoctorWrap .buttonWrapper');
            if (!buttonWrapper?.classList.contains('optionsOpen')) return;
            document.querySelectorAll('.optionsOpen').forEach((el) => el.classList.remove('optionsOpen'));
            const innerForm = document.querySelector('.innerDoctorWrap .innerForm');
            if (innerForm) slideFadeToggle(innerForm);
            document.body.classList.remove('productFlyoutOpen');
        });
    });

    // Side tabs and product tabs — vanilla Tabs.
    window.mtcTabs('.js_sideTabs');

    if (document.querySelector('.js_product_tabs')) {
        window.mtcTabs('.js_product_tabs', {
            onInit() {
                const firstProductTabs = document.querySelector('.js_product_tabs');
                const mobileTitle = firstProductTabs?.dataset.mobileTitle;
                if (mobileTitle && mobileTitle.length > 0) {
                    document.querySelectorAll('.tabsNav').forEach((nav) => {
                        const heading = document.createElement('h3');
                        heading.className = 'mobileTabsTitle';
                        heading.textContent = mobileTitle;
                        nav.prepend(heading);
                    });
                    showHideMenus('.mobileTabsTitle', 800);
                }
            },
            afterChange(elementId) {
                if (window.innerWidth <= 800) {
                    const target = document.querySelector(`.tabContent[data-tab-id="${elementId}"]`);
                    if (target) {
                        window.scrollTo({ top: elementTop(target), behavior: 'smooth' });
                    }
                }
            },
        });
    }

    productSidebar();

    // Sticky section nav + scroll-spy.
    const itemSectionNav = document.getElementById('itemSectionNav');
    if (itemSectionNav) {
        stickyProductNav();

        const sectionSelect = document.querySelector('.itemSectionSelect');
        if (sectionSelect) {
            sectionSelect.addEventListener('change', () => {
                if (sectionSelect.classList.contains('noScroll')) return;
                const val = sectionSelect.value;
                if (val && val.length) {
                    const link = document.querySelector(`.sectionNav a[href="${val}"]`);
                    link?.click();
                }
            });
        }
    }
});

// Resize handler — re-run the sidebar / sticky-nav / mobile menu sync.
window.addEventListener('resize', window.debouncer(() => {
    productSidebar();
    stickyProductNav();

    if (document.querySelector('.mobileTabsTitle')) {
        showHideMenus('.mobileTabsTitle', 800);
    }
    if (document.querySelector('.sidebarTabs .sectionTitle')) {
        showHideMenus('.sidebarTabs .sectionTitle', 700);
    }
}));

// ---- bottom helpers ------------------------------------------------------

function productSidebar() {
    const innerDoctorWrap = document.querySelector('.innerDoctorWrap');
    if (!innerDoctorWrap) return;

    const innerForm = innerDoctorWrap.querySelector('.innerForm');
    const siteWrapper = document.querySelector('.siteWrapper');

    if (window.innerWidth > window.breakpoints.product_small) {
        document.body.classList.remove('mobileProductOptionsSet');

        if (innerForm && (innerForm.offsetParent === null || getComputedStyle(innerForm).display === 'none')) {
            innerForm.style.display = '';
            document.querySelectorAll('.optionsOpen').forEach((el) => el.classList.remove('optionsOpen'));
            innerDoctorWrap.style.overflow = 'visible';
            if (siteWrapper) siteWrapper.style.paddingBottom = '0';
        }
    } else {
        if (!document.body.classList.contains('mobileProductOptionsSet')) {
            document.body.classList.add('mobileProductOptionsSet');
            if (innerForm) innerForm.style.display = 'none';
            document.querySelectorAll('.optionsOpen').forEach((el) => el.classList.remove('optionsOpen'));
        }
        if (siteWrapper) {
            siteWrapper.style.paddingBottom = `${innerDoctorWrap.offsetHeight}px`;
        }
    }
}

function stickyProductNav() {
    const productTabs = document.getElementById('productTabs');
    if (!productTabs) return;

    const nav = document.getElementById('itemSectionNav');
    if (!nav) return;

    const navLinks = nav.querySelectorAll('.sectionNav > ul > li a');
    const stickyNavOffset = nav.offsetHeight;

    // Disconnect any previous observers so resize doesn't stack them.
    disconnectStickyObservers();
    nav.classList.remove('isVisible');

    // Determine the target element and pixel offset.
    // Both flyout and mobile breakpoints want the same behaviour — pin
    // the offset to the sticky header — so collapse the duplicated blocks.
    let target = productTabs;
    let topOffset = 193;
    const breakpoint = Math.max(
        window.breakpoints.flyout || 0,
        window.breakpoints.mobile || 0,
    );
    if (window.innerWidth <= breakpoint) {
        const header = document.getElementById('header');
        topOffset = 0 - (header?.offsetHeight || 0);
        target = header || productTabs;
    }

    // Sticky nav observer — show the nav once `target` scrolls past the
    // configured top offset (mirrors waypoint(direction='down')).
    stickyNavObserver = new IntersectionObserver(([entry]) => {
        // `entry.boundingClientRect.top < topOffset` ≈ scrolling past it.
        const rect = entry.boundingClientRect;
        if (rect.top <= topOffset) {
            nav.classList.add('isVisible');
        } else {
            nav.classList.remove('isVisible');
        }
    }, {
        // Shrink the root from the top by topOffset so the threshold lines
        // up with where the legacy waypoint fired.
        rootMargin: `${-topOffset}px 0px 0px 0px`,
        threshold: [0, 1],
    });
    stickyNavObserver.observe(target);

    // Tab-section scroll-spy — highlight the matching nav link as each
    // section crosses the top of the viewport.
    const tabSections = document.querySelectorAll('.itemTabSection');
    if (!tabSections.length) return;

    tabSectionObserver = new IntersectionObserver((entries) => {
        entries.forEach((entry) => {
            if (!entry.isIntersecting) return;
            const sectionId = entry.target.id;
            const link = document.querySelector(`a[href="#${sectionId}"]`);
            if (link) {
                navLinks.forEach((l) => l.classList.remove('active'));
                link.classList.add('active');
            }
            const sectionSelect = document.querySelector('.itemSectionSelect');
            if (sectionSelect) {
                sectionSelect.classList.add('noScroll');
                sectionSelect.value = `#${sectionId}`;
                sectionSelect.dispatchEvent(new CustomEvent('chosen:updated'));
                sectionSelect.classList.remove('noScroll');
            }
        });
    }, {
        rootMargin: `${-stickyNavOffset}px 0px 0px 0px`,
        threshold: [0.1],
    });
    tabSections.forEach((section) => tabSectionObserver.observe(section));
}

// ---- after-ready misc ----------------------------------------------------

ready(() => {
    document.querySelectorAll('.js-link').forEach((link) => {
        link.addEventListener('click', (event) => {
            event.preventDefault();
            const url = link.dataset.url;
            if (url) window.location.href = url;
        });
    });
});

/*
 * Product description read-more toggle.
 * Runs after Vue mounts (vue:mounted event dispatched from app.js).
 */
document.addEventListener('vue:mounted', () => {
    document.querySelectorAll('.js_itemDescriptionToggle').forEach((toggle) => {
        const content = toggle.parentElement.querySelector('.itemDescription__content');
        if (!content) return;

        if (content.scrollHeight <= content.clientHeight + 1) {
            toggle.style.display = 'none';
            return;
        }

        const gradientClass = 'itemDescription__content--gradient';
        content.classList.add(gradientClass);
        toggle.style.display = '';

        toggle.addEventListener('click', () => {
            const isCollapsed = content.classList.contains(gradientClass);
            if (isCollapsed) {
                content.style.maxHeight = `${content.scrollHeight}px`;
                content.classList.remove(gradientClass);
                toggle.textContent = 'Read less';
            } else {
                content.style.maxHeight = '';
                content.classList.add(gradientClass);
                toggle.textContent = 'Read more';
            }
        });
    });
});
