<?php

/**
 * Mageplaza
 *
 * NOTICE OF LICENSE
 *
 * This source file is subject to the Mageplaza.com license that is
 * available through the world-wide-web at this URL:
 * https://www.mageplaza.com/LICENSE.txt
 *
 * DISCLAIMER
 *
 * Do not edit or add to this file if you wish to upgrade this extension to newer
 * version in the future.
 *
 * @category    Mageplaza
 * @package     Mageplaza_FrequentlyBought
 * @copyright   Copyright (c) Mageplaza (https://www.mageplaza.com/)
 * @license     https://www.mageplaza.com/LICENSE.txt
 */

declare(strict_types=1);

use Hyva\Theme\Model\ViewModelRegistry;
use Hyva\Theme\ViewModel\ProductPage;
use Hyva\Theme\ViewModel\ProductPrice;
use Magento\Bundle\Pricing\Price\FinalPrice;
use Magento\Catalog\Pricing\Price\BasePrice;
use Magento\Catalog\Pricing\Price\RegularPrice;

/** @var Magento\Bundle\Block\Catalog\Product\View\Type\Bundle $block */
/** @var ViewModelRegistry $viewModels */
/** @var Magento\Framework\Escaper $escaper */
$product = $block->getProduct();
$stripSelection = $product->getConfigureMode() ? true : false;
$options = $block->decorateArray($block->getOptions($stripSelection));

/** @var ProductPage $productViewModel */
$productViewModel = $viewModels->require(ProductPage::class);

/** @var ProductPrice $productPriceViewModel */
$productPriceViewModel = $viewModels->require(ProductPrice::class);

$displayTax = $productPriceViewModel->displayPriceIncludingTax();

$regularPrice = $productPriceViewModel->getPriceValue(RegularPrice::PRICE_CODE, $product);
$finalPrice = $productPriceViewModel->getPriceValue(FinalPrice::PRICE_CODE, $product);

if ($productPriceViewModel->displayPriceInclAndExclTax()) {
    $basePrice = $productPriceViewModel->getPriceValueExclTax(FinalPrice::PRICE_CODE, $product);
}
?>
<?php if ($product->isSaleable()): ?>
    <div class="flex w-full">
        <?php if (count($options)): ?>
            <script>
                function initBundleOptions(wrapElement) {
                    return {
                        optionConfig: <?= /* @noEscape */ $block->getJsonConfig() ?>,
                        regularPriceKey: '<?= /* @noEscape */ $displayTax ? 'oldPrice' : 'baseOldPrice' ?>',
                        finalPriceKey: '<?= /* @noEscape */ $displayTax ? 'finalPrice' : 'basePrice' ?>',
                        <?php if ($productPriceViewModel->displayPriceInclAndExclTax()): ?>
                        basePriceKey: 'basePrice',
                        <?php endif; ?>
                        productFinalPrice: false,
                        activeSelectOptions: {},
                        selectedOptions: [],
                        getMultiOptionQty(option, optionSelection) {
                            if (option.isMulti) {
                                return optionSelection.qty;
                            }
                            return false;
                        },
                        calculateTotalPrice() {
                            let selectedProductsPerOption = [];

                            for (const [optionId, option] of Object.entries(this.optionConfig.options)) {
                                const optionElement = document.querySelector(`[data-option-id="${optionId}"]`);
                                const qtyElement = document.getElementById('bundle-option-' + optionId + '-qty-input');

                                let selectedOption = selectedProductsPerOption[optionId] || [];

                                if (optionElement) {
                                    if (optionElement.checked || optionElement.selected) {
                                        const optionSelection = option.selections[optionElement.dataset.selectionId];
                                        selectedOption.push({
                                            data: optionSelection,
                                            qty: this.getMultiOptionQty(option, optionSelection) ||
                                                (qtyElement && qtyElement.value) || 1
                                        });
                                    }
                                } else {
                                    for (const [selectionId, selection] of Object.entries(option.selections)) {
                                        const selectionElement = document.querySelector(
                                            `[data-option-id="${optionId}-${selectionId}"]`
                                        );
                                        if (
                                            selectionElement &&
                                            (
                                                selectionElement.checked ||
                                                selectionElement.selected
                                            )
                                        ) {
                                            selectedOption.push({
                                                data: selection,
                                                qty: this.getMultiOptionQty(option, selection) ||
                                                    (qtyElement && qtyElement.value) || 1
                                            });
                                        }
                                    }
                                }

                                selectedProductsPerOption[optionId] = Object.assign(
                                    [],
                                    selectedProductsPerOption[optionId],
                                    selectedOption
                                );
                            }
                            const gatherLowestPriceForOptionProduct = (accPrice, product) => {
                                <?php /* Gather the lowest (normal price | tier price) for the option product/ */ ?>
                                const lowestPrice = product.data.tierPrice.reduce((finalValue, tierPrice) => {
                                    if (product.qty >= tierPrice.price_qty) {
                                        return (tierPrice.prices[this.finalPriceKey].amount < finalValue[this.finalPriceKey].amount)
                                            ? tierPrice.prices
                                            : finalValue;
                                    }
                                    return finalValue;
                                }, product.data.prices);

                                // add the lowest price for qty
                                return {
                                    oldPrice: accPrice.oldPrice + (lowestPrice.oldPrice.amount * product.qty),
                                    finalPrice: accPrice.finalPrice + (lowestPrice[this.finalPriceKey].amount * product.qty),
                                    <?php if ($productPriceViewModel->displayPriceInclAndExclTax()): ?>
                                    basePrice: accPrice.basePrice + (lowestPrice.basePrice.amount * product.qty),
                                    <?php endif; ?>
                                };
                            }

                            this.productFinalPrice = Object.values(selectedProductsPerOption)
                                .reduce(
                                    (totalPrice, option) => {
                                        <?php /* Sum all old, final and base prices for all simple products */ ?>
                                        const totalOptionPrice = Object.values(option).reduce(gatherLowestPriceForOptionProduct, {
                                            oldPrice: 0,
                                            finalPrice: 0,
                                            basePrice: 0,
                                        });
                                        return {
                                            oldPrice: totalPrice.oldPrice + totalOptionPrice.oldPrice,
                                            finalPrice: totalPrice.finalPrice + totalOptionPrice.finalPrice,
                                            <?php if ($productPriceViewModel->displayPriceInclAndExclTax()): ?>
                                            basePrice: totalPrice.basePrice + totalOptionPrice.basePrice,
                                            <?php endif; ?>
                                        }

                                    }, {
                                        oldPrice: 0,
                                        finalPrice: 0,
                                        <?php if ($productPriceViewModel->displayPriceInclAndExclTax()): ?>
                                        basePrice: 0,
                                        <?php endif; ?>
                                    }
                                );

                            this.selectedOptions = Object.keys(selectedProductsPerOption).map((optionId) => {
                                return {
                                    label: this.optionConfig.options[optionId].title,
                                    products: Object.values(selectedProductsPerOption[optionId]).map(product => {
                                        return {
                                            qty: product.qty,
                                            name: product.data.name
                                        }
                                    })
                                }
                            });

                            this.dispatchFinalPrice();
                            this.dispatchOptionSelection();
                        },
                        dispatchFinalPrice() {
                            let checkboxElement = wrapElement.closest('li, tr').querySelector('.item-price');
                            checkboxElement.setAttribute('data-price-amount',this.productFinalPrice.finalPrice);
                            let productId = wrapElement.closest('li,tr').getAttribute('data-mpfbt-popup-product-id');
                            if(productId) {
                                document.querySelector('.item-price.mageplaza-fbt-price-' + productId).setAttribute('data-price-amount', this.productFinalPrice.finalPrice);
                            }
                            window.dispatchEvent(new CustomEvent("reload-price-frequently-bought"));
                        },
                        dispatchOptionSelection() {
                            window.dispatchEvent(new CustomEvent("update-bundle-option-selection", {detail: this.selectedOptions}));
                        },
                        getQtyValue(optionId) {
                            const selectionConfig = this.getSelectionOptionConfig(optionId);

                            return selectionConfig ? selectionConfig.qty : "0";
                        },
                        getSelectionOptionConfig(optionId) {
                            const activeSelectOption = this.activeSelectOptions[optionId];
                            let activeSelectOptionValue = null;

                            if (!activeSelectOption) {
                                return false;
                            }

                            if (typeof activeSelectOption == 'object' && activeSelectOption.length) {
                                activeSelectOptionValue = activeSelectOption[0];
                            } else {
                                activeSelectOptionValue = activeSelectOption;
                            }

                            return this.optionConfig
                                .options[optionId]
                                .selections[activeSelectOptionValue];
                        },
                        getQtyDisabled(optionId) {
                            const selectionConfig = this.getSelectionOptionConfig(optionId);

                            if (!selectionConfig) {
                                return true;
                            }

                            return !selectionConfig || selectionConfig.customQty === "0";
                        },
                        setQtyValue(optionId, value) {
                            const selectionConfig = this.getSelectionOptionConfig(optionId);
                            if (selectionConfig) {
                                selectionConfig.qty = value;
                            }
                        },
                    }
                }
            </script>
            <div x-data="initBundleOptions($el)"
                 x-init="
                    calculateTotalPrice();
                    $nextTick(() => {
                        dispatchFinalPrice();
                        dispatchOptionSelection();
                        $dispatch('set-selected-options', {});
                    })"
                 class="w-full">

                <fieldset class="fieldset-bundle-options min-w-48 mb-8" form="mageplaza-fbt-form">
                    <?php foreach ($options as $option): ?>
                        <?php
                        if (!$option->getSelections()) {
                            continue;
                        } ?>
                        <div class="my-2 pt-4 pb-2 w-full border-t border-container">
                            <label
                                id="option-label-<?= $escaper->escapeHtmlAttr($option->getId()) ?>"
                                class="label text-lg font-semibold"
                            >
                                <?= $escaper->escapeHtml($option->getTitle()) ?>
                            </label>
                            <div class="control mt-2">
                                <div class="nested options-list">

                                    <?= /* @noEscape */ $block->getChildBlock($option->getType())->setProduct($product)->setOption($option)->toHtml(); ?>
                                </div>
                            </div>
                        </div>
                    <?php endforeach; ?>
                </fieldset>
            </div>
        <?php else: ?>
            <p class="empty"><?= $escaper->escapeHtml(__('No options of this product are available.')) ?></p>
        <?php endif; ?>
    </div>
<?php endif; ?>
