<?php
use Magento\Framework\Escaper;
use Magento\Framework\View\Element\Template;

/** @var Template $block */
/** @var Escaper $escaper */
?>
<script>
function initConfigurableOptions(productId, optionConfig) {
    function findPathParam(key) {
        const baseUrl = (BASE_URL.substr(0, 2) === '//' ? 'http:' : '') + BASE_URL;
        const baseUrlParts = (new URL(baseUrl)).pathname.replace(/\/$/, '').split('/');
        const pathParts = window.location.pathname.split('/').slice(baseUrlParts.length + 3);
        for (let i = 0; i < pathParts.length; i += 2) {
            if (pathParts[i] === key && pathParts.length > i) {
                return pathParts[i + 1];
            }
        }
        return null;
    }

    return {
        optionConfig,
        productId,
        itemId: (new URLSearchParams(window.location.search)).get('id') || findPathParam('id'),
        allowedAttributeOptions: [],
        selectedValues: {},
        productIndex: 0,

        init() {
            const currentUrl = window.location.href;
            const queryStringUrl = new URL(currentUrl);
            const currentqueryStringUrl = queryStringUrl.origin + queryStringUrl.pathname;
            const urls = this.optionConfig.productUrls;
            let foundKey = null;

            for (const key in urls) {
                if (urls.hasOwnProperty(key) && urls[key] === currentqueryStringUrl) {
                    foundKey = key;
                    break;
                }
            }

            if (foundKey && this.optionConfig.childOptions.hasOwnProperty(foundKey)) {
                this.optionConfig.defaultValues = this.optionConfig.childOptions[foundKey];
            }

            if (typeof this.optionConfig.defaultValues === 'object') {
                this.selectedValues = Object.fromEntries(
                    Object.entries(this.optionConfig.defaultValues).map(([attrId, val]) => [attrId, val + ''])
                );
            }

            this.findSimpleIndex();
            this.findAllowedAttributeOptions();
            this.updatePrices();
            this.updateGallery();
            if (this.productIndex) {
                this.replaceData(this.productIndex);
            }
            if (this.optionConfig.showQty) {
                this.updateQty();
            }

            this.onGetCartData(window.cartData || {});
        },

        optionIsActive(attributeId, optionId) {
            return !!this.getAllowedAttributeOptions(attributeId).find(o => o.id === optionId);
        },

        optionIsEnabled(attributeId, optionId) {
            for (const productId in this.optionConfig.index) {
                if (this.optionConfig.index[productId][attributeId] === optionId) {
                    return true;
                }
            }
            return false;
        },

        findSimpleIndex() {
            this.productIndex = this.calculateSimpleIndexForPartialSelection(this.selectedValues);
        },

        calculateSimpleIndexForPartialSelection(selectedValues) {
            if (Object.keys(selectedValues).length === 0) return 0;
            let productIndexIds = Object.keys(this.optionConfig.index);
            Object.keys(this.optionConfig.attributes).forEach(attribute => {
                const productsWithAttributeMatch = selectedValues[attribute]
                    ? productIndexIds.filter(idx => this.optionConfig.index[idx][attribute] === selectedValues[attribute])
                    : [];
                productIndexIds = productsWithAttributeMatch.length ? productsWithAttributeMatch : productIndexIds;
            });
            return productIndexIds[0] || 0;
        },

        calculateSimpleIndexForFullSelection(selectedValues) {
            const productIndexes = this.optionConfig.index;
            return Object.keys(productIndexes).find(productIndex => {
                const candidate = productIndexes[productIndex];
                for (const productOption in candidate) {
                    if (!selectedValues[productOption] || selectedValues[productOption] !== candidate[productOption]) {
                        return false;
                    }
                }
                return productIndex;
            });
        },

        findAllowedAttributeOptions() {
            this.allowedAttributeOptions = this.calculateAllowedAttributeOptions(this.selectedValues);
        },

        calculateAllowedAttributeOptions(selectedValues) {
            const allAttributes = this.optionConfig.attributes;
            const sorted = Object.values(allAttributes).sort((a, b) => a.position - b.position);
            const withoutAttr = attrId =>
                Object.keys(selectedValues).reduce((acc, id) => {
                    if (id !== attrId) acc[id] = selectedValues[id];
                    return acc;
                }, {});
            const allowed = [];
            sorted.forEach(attribute => {
                const availableIndexes = this.calculateAvailableProductIndexes(withoutAttr(attribute.id));
                allowed[attribute.id] = allAttributes[attribute.id].options.filter(option =>
                    option.products.some(product => availableIndexes.includes(product))
                );
            });
            return allowed;
        },

        calculateAvailableProductIndexes(selectedOptions) {
            if (Object.keys(selectedOptions).length === 0) {
                return Object.keys(this.optionConfig.index);
            }
            const selectedIds = Object.keys(selectedOptions);
            if (Object.values(this.optionConfig.salable || {}).length) {
                const selectedOptionIndexes = selectedIds.map(attrId => {
                    const optionValue = selectedOptions[attrId];
                    return (this.optionConfig.salable[attrId] && this.optionConfig.salable[attrId][optionValue]) || [];
                });
                return selectedOptionIndexes.reduce((acc, optionIndexes) => acc.filter(i => optionIndexes.includes(i)));
            } else {
                const productIndexes = this.optionConfig.index;
                return Object.keys(productIndexes).filter(index =>
                    selectedIds.find(attrId => productIndexes[index][attrId] === `${selectedOptions[attrId]}`)
                );
            }
        },

        findAttributeByOptionId(optionId) {
            for (const attributeId in this.optionConfig.attributes) {
                const opts = this.optionConfig.attributes[attributeId].options || [];
                if (opts.find(option => option.id === optionId)) {
                    return attributeId;
                }
            }
        },

        getAllowedAttributeOptions(attributeId) {
            return this.allowedAttributeOptions[attributeId] || [];
        },

        getAllAttributeOptions(attributeId) {
            return (this.optionConfig.attributes[attributeId] && this.optionConfig.attributes[attributeId].options) || [];
        },

        getProductIdsForOption(option) {
            const attributeId = this.findAttributeByOptionId(option.id);
            const allOptions = this.optionConfig.attributes[attributeId];
            const opt = (allOptions && allOptions.options || []).find(o => o.id === option.id);
            return opt && opt.products ? opt.products : [];
        },

        findProductIdsForPartialSelection(optionSelection) {
            return Object.values(optionSelection).reduce((candidates, optionId) => {
                const newCandidates = this.getProductIdsForOption({ id: optionId });
                return candidates === null ? newCandidates : candidates.filter(id => newCandidates.includes(id));
            }, null) || [];
        },

        findCheapestProductForPartialSelection(optionSelection) {
            const candidates = this.findProductIdsForPartialSelection(optionSelection);
            return candidates.reduce((cheapest, simpleIdx) => {
                if (!this.optionConfig.optionPrices[cheapest]) return simpleIdx;
                const knownPrice = this.optionConfig.optionPrices[cheapest].finalPrice.amount;
                return knownPrice > this.optionConfig.optionPrices[simpleIdx].finalPrice.amount ? simpleIdx : cheapest;
            }, 0);
        },

        findProductIdToUseForOptionPrice(option) {
            const attributeId = this.findAttributeByOptionId(option.id);
            const optionSelection = { ...this.selectedValues, [attributeId]: option.id };
            const match = this.calculateSimpleIndexForFullSelection(optionSelection);
            return match || this.findCheapestProductForPartialSelection(optionSelection);
        },

        getAttributeOptionLabel(option) {
            const optionProduct = this.findProductIdToUseForOptionPrice(option);
            if ((!optionProduct) || (optionProduct === this.productIndex)) return option.label;
            const currentPrice = this.getOptionPriceAdjustmentBasePrice();
            if (this.optionConfig.optionPrices[optionProduct]) {
                const optionPrice = this.optionConfig.optionPrices[optionProduct].finalPrice.amount;
                if (optionPrice !== currentPrice) {
                    return option.label + ' ' + hyva.formatPrice(optionPrice - currentPrice, true);
                }
            }
            return option.label;
        },

        getOptionPriceAdjustmentBasePrice() {
            if (this.optionConfig.optionPrices[this.productIndex]) {
                return this.optionConfig.optionPrices[this.productIndex].finalPrice.amount;
            }
            const cheapest = this.findCheapestProductForPartialSelection(this.selectedValues);
            return this.optionConfig.optionPrices[cheapest]
                ? this.optionConfig.optionPrices[cheapest].finalPrice.amount
                : this.optionConfig.prices.finalPrice.amount;
        },

        clearOptionIfActive(optionId, value) {
            if (this.selectedValues[optionId] === value) {
                this.blurLabel()
                this.changeOption(optionId, '');
            }
        },

        changeOption(optionId, value) {
            if (value === '') {
                const newSelection = {};
                Object.keys(this.selectedValues).forEach(opt => {
                    if (opt !== optionId) newSelection[opt] = this.selectedValues[opt];
                });
                this.selectedValues = newSelection;
            } else {
                this.selectedValues[optionId] = value;
            }
            this.findSimpleIndex();
            this.findAllowedAttributeOptions();
            this.updatePrices();
            this.updateGallery();
            this.updateInfo();
            window.dispatchEvent(new CustomEvent('configurable-selection-changed', {
                detail: {
                    productId: this.productId,
                    optionId,
                    value,
                    productIndex: this.productIndex,
                    selectedValues: this.selectedValues,
                    candidates: this.findProductIdsForPartialSelection(this.selectedValues)
                }
            }));
        },

        replaceData(simpleProductId) {
            if (!this.optionConfig.replaceUrl || !simpleProductId) return;
            const pageUrl = BASE_URL + 'hyvasimpleconfigurable/index/getchildproductdata';
            fetch(pageUrl + '?product_id=' + simpleProductId, { method: 'GET', headers: { 'X-Requested-With': 'XMLHttpRequest' } })
                .then(res => {
                    if (res.ok) return res.json();
                    throw new Error('Network response was not ok');
                })
                .then(response => {
                    if (response.success) {
                        Object.entries(response.data).forEach(([key, item]) => {
                            const el = document.querySelector(item.selector);
                            if (el) {
                                if (item.selector.includes('meta')) el.setAttribute('content', item.value);
                                else if (item.selector.includes('canonical')) el.setAttribute('href', item.value);
                                else el.innerHTML = item.value;
                            }
                        });
                        if (response.product_url) {
                            const queryString = window.location.search;
                            let title = document.querySelector('div h1 .base')?.textContent || '';
                            if (response.data.name) title = response.data.name.value;
                            const newUrl = queryString ? response.product_url + queryString : response.product_url;
                            history.replaceState(null, title, newUrl);
                            const encodedUrl = btoa(response.product_url);
                            const form = document.querySelector('.product-info-main #product_addtocart_form');
                            if (form) {
                                let actionUrl = form.getAttribute('action');
                                if (actionUrl && actionUrl.includes('uenc/')) {
                                    try {
                                        const updatedUrl = actionUrl.replace(/uenc\/[^\/]+/, 'uenc/' + encodeURIComponent(encodedUrl));
                                        form.setAttribute('action', updatedUrl);
                                    } catch (error) {
                                        console.error('Error updating form action:', error);
                                    }
                                }
                            }
                        }
                    } else {
                        console.error('Error:', response.message);
                    }
                })
                .catch(error => {
                    console.error('AJAX error:', error);
                });
        },

        updateInfo() {
            if (this.productIndex) {
                this.replaceData(this.productIndex);
            }
            if (this.optionConfig.showQty) this.updateQty();
        },

        updateQty() {
            const qtyClass = 'div span.product-qty';
            const simpleId = this.productIndex;
            const page_url = BASE_URL + 'simpleconfigurable/index/ajaxrequest/';
            const formKey = hyva.getFormKey();
            fetch(page_url, {
                headers: { "content-type": "application/x-www-form-urlencoded; charset=UTF-8" },
                body: "form_key=" + formKey + "&id=" + simpleId + "&uenc=" + hyva.getUenc(),
                method: "POST", mode: "cors", credentials: "include"
            }).then(res => res.ok ? res.json() : null)
              .then(response => {
                if (response && response.status === 'success') {
                    const match = response.success_message.match(/\d+/);
                    if (match) {
                        const qty = parseInt(match[0]);
                        if (!isNaN(qty) && qty >= 0) {
                            const qtyDiv = document.querySelector('div.product-qty-div');
                            const qtyEl = document.querySelector(qtyClass);
                            if (qtyDiv && qtyEl) {
                                qtyDiv.classList.remove("hidden");
                                qtyEl.innerHTML = qty;
                            }
                        }
                    }
                }
            });
        },

        calculateIsMinimalPrice() {
            return Object.values(this.selectedValues).filter(v => !!v).length < Object.keys(this.optionConfig.attributes).length;
        },

        updatePrices() {
            const value = this.productIndex ? this.optionConfig.optionPrices[this.productIndex] : this.optionConfig.prices;
            window.dispatchEvent(new CustomEvent("update-prices-" + this.productId, {
                detail: Object.assign(value, { isMinimalPrice: this.calculateIsMinimalPrice() })
            }));
        },

        updateGallery() {
            if (this.productIndex) {
                const images = this.optionConfig.images[this.productIndex];
                images && window.dispatchEvent(new CustomEvent("update-gallery", { detail: this.sortImagesByPosition(images) }));
            } else {
                window.dispatchEvent(new Event("reset-gallery"));
            }
        },

        sortImagesByPosition(images) {
            return images.sort((x, y) => parseInt(x.position) - parseInt(y.position));
        },

        onGetCartData(data) {
            this.preselectCartItems(data);
            this.preselectQuerystringItems();
            this.preselectLocationHashItems();
        },

        preselectCartItems(data) {
            const cartItem = data?.cart?.items?.find(item => item.item_id === this.itemId && item.product_id === this.productId);
            if (cartItem?.options?.length) {
                cartItem.options.forEach(option => this.changeOption(option.option_id, option.option_value));
            }
        },

        preselectQuerystringItems() {
            const urlQueryParams = new URLSearchParams(window.location.search.replace('?',''));
            Object.values(this.optionConfig.attributes).forEach(attribute => {
                const val = urlQueryParams.get(attribute.code);
                if (val) this.changeOption(attribute.id, val);
            });
        },

        preselectLocationHashItems() {
            const urlHashParams = new URLSearchParams(window.location.hash.replace('#',''));
            Object.values(this.optionConfig.attributes).forEach(attribute => {
                const val = urlHashParams.get(attribute.id);
                if (val) this.changeOption(attribute.id, val);
            });
        }
    }
}
</script>
