<?php
declare(strict_types=1);

/**
 * Copyright © MageWorx. All rights reserved.
 * See https://www.mageworx.com/terms-and-conditions for license details.
 */

use Hyva\Theme\Model\ViewModelRegistry;
use Hyva\Theme\ViewModel\ProductPage;
use Hyva\Theme\ViewModel\ProductPrice;
use Magento\Catalog\Pricing\Price\FinalPrice;
use Magento\Catalog\Pricing\Price\RegularPrice;
use Magento\Catalog\Pricing\Price\TierPrice;
use Magento\Framework\Escaper;
use Hyva\Theme\ViewModel\HeroiconsOutline;

/** @var HeroiconsOutline $heroicons */
/** @var Escaper $escaper */
/** @var ViewModelRegistry $viewModels */

$heroicons = $viewModels->require(HeroiconsOutline::class);

/**
 * @var \Hyva\MageWorxAdvancedProductOptions\Block\Product $block
 */
$product        = $block->getProduct();
$productType    = $product->getTypeId();
$productId      = $product->getId();
$productSku     = $product->getSku();
$optionTypeData = $block->getOptionTypeData($product);
$specialPrice   = $block->getSpecialPrice($product);
$regularPrice   = $block->getRegularPrice($product);
$storeId        = $block->getStoreId();
$apoSettings    = $block->getApoSystemSettings();
$isAvailable    = $product->isAvailable();

/** @var \Magento\Catalog\Block\Product\View\Gallery $galleryBlock */
$galleryBlock = $block->getLayout()->getBlockSingleton('Magento\Catalog\Block\Product\View\Gallery');
$width        = $galleryBlock->getImageAttribute('product_page_image_small', 'width');
$height       = $galleryBlock->getImageAttribute('product_page_image_small', 'height');

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

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

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

<?php if ($product->getOptions()): ?>
    <script>
        "use strict"
        const pathname = window.location.pathname;
        const regex = /checkout\/cart\/configure\/id\/(\d+)\/product_id\/(\d+)/;
        const matches = pathname.match(regex);

        const cartItemInfo = {};

        if (matches) {
            cartItemInfo.cartItemId = matches[1];
            cartItemInfo.productId = matches[2];
        }

        const initialFinalPriceExclTax = <?= /** @noEscape */ $productPriceViewModel->getPriceValueExclTax(FinalPrice::PRICE_CODE, $product) ?>;
        const initialFinalPriceInclTax = <?= /** @noEscape */ $productPriceViewModel->getPriceValueInclTax(FinalPrice::PRICE_CODE, $product) ?>;
        const initialRegularPriceExclTax = <?= /** @noEscape */ $productPriceViewModel->getPriceValueExclTax(RegularPrice::PRICE_CODE, $product) ?>;
        const initialRegularPriceInclTax = <?= /** @noEscape */ $productPriceViewModel->getPriceValueInclTax(RegularPrice::PRICE_CODE, $product) ?>;

        const getDataByMethodHOF = (method) => {
            return async (graphqlFunc, backendFunc) => {
                if (method === 'GRAPHQL') {
                    return await graphqlFunc();
                } else if (method === 'BACKEND') {
                    return await backendFunc();
                }
            }
        }
        const getDataByMethod = getDataByMethodHOF('<?= $block->getInitUsingGraphql() ? "GRAPHQL" : "BACKEND" ?>');

        function initApo() {
            const isShowPriceLabel = <?= ($product->canConfigure() && is_int($product->getPrice())) ? 'true' : 'false' ?>;
            const initialShowRegularPriceLabel = <?= ($finalPrice < $regularPrice) ? 'true' : 'false' ?>;

            let $priceLabel = null;

            if (isShowPriceLabel) {
                $priceLabel = document.createElement('span');
                $priceLabel.className = 'price-label block';
                $priceLabel.innerText = '<?= $escaper->escapeHtml(__('As low as')) ?>';
            }

            const togglePriceLabel = (isShow) => {
                if ($priceLabel) {
                    if (isShow) $priceLabel.style.visibility = 'visible';
                    else $priceLabel.style.visibility = 'hidden';
                }
            }

            return {
                initilize() {
                    <?php if (!$block->getInitUsingGraphql()): ?>
                        this.advancedProductOptionsSettings = <?= json_encode($block->getOptionsSettings()); ?>;
                        this.productExtendConfig = <?= json_encode($block->getProductExtendConfig()); ?>;
                        this.swatchMediaData = <?= json_encode($block->getSwatchMediaData()); ?>;
                        this.productOptions = <?= json_encode($block->getProductOptions()); ?>;
                        this.extendedOptionsConfig = JSON.parse(this.productOptions.extended_options_config);
                    <?php endif; ?>

                    this.swatchSkuLinkedProductsData = <?= json_encode($block->getSwatchSkuLinkedProductsData()); ?>;

                    this.PRODUCT_TYPE = {
                        'CONFIGURABLE': 'configurable',
                        'SIMPLE': 'simple',
                    }
                    this.productType = '<?= $productType ?>';
                    this.productId = <?= $productId ?>;

                    if (this.productType === this.PRODUCT_TYPE.CONFIGURABLE) {
                        if (typeof this.productPricesConfig === "undefined") {
                            this.productPricesConfig = {
                                final_price_excl_tax: initialFinalPriceExclTax,
                                final_price_incl_tax: initialFinalPriceInclTax,
                                regular_price_excl_tax: initialRegularPriceExclTax,
                                regular_price_incl_tax: initialRegularPriceInclTax,
                                is_show_old_price: initialFinalPriceInclTax !== initialRegularPriceInclTax,
                            }
                        }
                    }

                    this.isProductAvailable = +'<?= $isAvailable ?>' === 1 ? true : false;
                    if (!this.isProductAvailable) return;

                    const {
                        is_enabled_customize_and_add_to_cart_button: isEnabledCustomizeButton
                    } = JSON.parse('<?= $apoSettings ?>');

                    this.galleryWidth = "<?= $escaper->escapeHtml($width) ?>";
                    this.galleryHeight = "<?= $escaper->escapeHtml($height) ?>";

                    this.optionsConfig = <?= /* @noEscape */ $block->getJsonConfig() ?>;

                    this.storeId = <?= $storeId ?>;
                    this.optionTypeData = '<?= $optionTypeData ?>' && JSON.parse('<?= $optionTypeData ?>');

                    this.specialPrice = '<?= $specialPrice; ?>';
                    this.regularPrice = '<?= $regularPrice; ?>';

                    this.productSku = "<?= $productSku; ?>";
                    this.qty = 1;

                    if (this.productType === this.PRODUCT_TYPE.CONFIGURABLE) {
                        const $priceBlock = document.querySelector('.price-box.price-final_price');
                        const $priceArea = $priceBlock.parentNode;
                        const $price = document.querySelector(`#product-price-${this.productId}`);
                        const priceAriaLabel = $priceArea.getAttribute('aria-label');
                        $priceArea.style.visibility = 'hidden';

                        const $apoPriceBlock = document.createElement('div');
                        $apoPriceBlock.setAttribute('aria-label', priceAriaLabel);
                        $apoPriceBlock.classList.add('price-box', 'price-final_price');

                        const $oldPrice = document.createElement('div');
                        const $apoPrice = document.createElement('div');

                        $apoPrice.classList.add('price-wrapper', 'title-font', 'font-medium', 'text-2xl', 'text-gray-900');
                        $oldPrice.classList.add('price-wrapper', 'title-font', 'font-regular', 'text-xl', 'text-gray-900', 'line-through');

                        const $exclPrice = document.createElement('div');
                        $exclPrice.classList.add('price-excl-taxinline-block');

                        const $oldExclPrice = document.createElement('div');
                        $oldExclPrice.classList.add('old-price-excl-tax', 'line-through');

                        $priceArea.parentNode.insertBefore($apoPriceBlock, $priceArea);

                        $apoPriceBlock.append($oldPrice);
                        $apoPriceBlock.append($oldExclPrice);

                        $apoPriceBlock.append($priceLabel);
                        if (!initialShowRegularPriceLabel) togglePriceLabel(false);

                        $apoPriceBlock.append($apoPrice);
                        $apoPriceBlock.append($exclPrice);

                        this.$price = $apoPrice;
                        this.$priceExcl = $exclPrice;
                        this.$oldPrice = $oldPrice;
                        this.$oldPriceExcl = $oldExclPrice;
                    } else {
                        this.$price = document.querySelector(`.final-price #product-price-${this.productId}`);
                        this.$priceExcl = document.querySelector(`.price-container .final-price-excl-tax`);
                        this.$oldPrice = document.querySelector(`.old-price #product-price-${this.productId}`);
                        this.$oldPriceExcl = document.querySelector('.price-container .old-price-excl-tax');
                        if (this.$oldPriceExcl) this.$oldPriceExcl.classList.add('line-through');
                    }

                    this.$qty = document.getElementById('qty[' + this.productId + ']');
                    this.$addToCart = document.getElementById('product-addtocart-button');
                    const $addToCartWrapper = this.$addToCart?.parentElement;
                    const $priceAddToCartWrapper = $addToCartWrapper?.parentElement;
                    const $formArea = $priceAddToCartWrapper?.parentElement;

                    this.isShowAddPrice = false;
                    this.$addPrice = null;

                    const $mwApo = document.getElementById('mw-apo-block');

                    $formArea?.insertBefore($mwApo, $priceAddToCartWrapper);

                    this.$addToCart.style.visibility = 'hidden';
                    this.$qty.style.visibility = 'hidden';

                    this.VALUES_TYPE = {
                        SINGLE: 'single value', // radio, select, text, date, file
                        MULTI: 'multi values', // checkbox, multi select
                    }

                    this.OPTIONS_TYPE = {
                        SELECT: 'select option', // radio, select, checkbox, multi select
                        CUSTOM: 'custom option' // text, date, file
                    }

                    this.apoStore = {
                        selected_options: [],
                        hidden_options: [],
                        hidden_values: [],
                        optionsMap: {}, // option_id: index_in_array / for find option by id in alpine array
                        optionValuesMap: {}, // option_type_id: { optionIndex, valuesPropName, valueIndex } / for find value by id in alpine array
                    }

                    this.config = {};

                    /*
                        if product is opened by link to edit cart item
                    */
                    if (cartItemInfo.cartItemId && cartItemInfo.productId) {
                        const {
                            cartItemId,
                            productId,
                        } = cartItemInfo;

                        if (this.productId === +productId) {
                            this.isEditingCartItem = !this.isEmpty(+cartItemId);
                            this.startLoading();
                        }
                    }

                    const searchParams = new URLSearchParams(window.location.search);
                    const apoParams = searchParams.get('config');
                    this.linkParams = apoParams;

                    if ((this.linkParams || !isEnabledCustomizeButton) && !this.isEditingCartItem) {
                        this.fetchApo();
                    }

                    if (this.isEditingCartItem && this.cartItems) {
                        this.getOptionsFromCartItem(this.cartItems);
                        this.stopLoading();
                        this.fetchApo();
                    }
                },
                fetchApo() {
                    this.initialFetch();
                },
                initialFinalPrice: <?= (float)$finalPrice ?>,
                regularPriceKey: '<?= $displayTax ? 'oldPrice' : 'baseOldPrice' ?>',
                activeProductsPriceData: false,
                calculatedFinalPrice: false,
                isProductAvailable: false,
                cartItemId: null,
                calculatePriceLabelVisibility() {
                    const showRegularPriceLabel =
                        (this.calculatedFinalPrice === this.activeProductsPriceData[this.regularPriceKey].amount) &&
                        this.activeProductsPriceData.isMinimalPrice;

                    togglePriceLabel(showRegularPriceLabel);
                },
                recalulateCustomizableProductPrices() {
                    const {
                        basePrice,
                        finalPrice,
                        baseOldPrice,
                        oldPrice,
                    } = this.activeProductsPriceData;

                    const {
                        final_price_excl_tax,
                        final_price_incl_tax,
                        regular_price_excl_tax,
                        regular_price_incl_tax,
                    } = this.productPricesConfig;

                    if (
                        basePrice.amount !== final_price_excl_tax ||
                        finalPrice.amount !== final_price_incl_tax ||
                        baseOldPrice.amount !== regular_price_excl_tax ||
                        oldPrice.amount !== regular_price_incl_tax
                    ) {
                        this.productPricesConfig = {
                            final_price_excl_tax: basePrice.amount,
                            final_price_incl_tax: finalPrice.amount,
                            regular_price_excl_tax: baseOldPrice.amount,
                            regular_price_incl_tax: oldPrice.amount,
                            is_show_old_price: oldPrice.amount !== finalPrice.amount,
                        }

                        if (finalPrice.amount === oldPrice.amount) {
                            this.$oldPrice.style.display = 'none';
                        } else {
                            this.$oldPrice.style.display = 'block';
                        }

                        if (this.isInitialized) this.calcFinalPrice(this.formatCurrentOptions());
                    }
                },
                getOptionsFromCartItem(items) {
                    if (items && items.length > 0) {
                        const currentItem = items.find((item) => item.item_id === cartItemInfo.cartItemId);

                        if (currentItem && currentItem.options) {
                            this.curentItemOptions = currentItem.options;
                        }
                    }
                },
                TOGGLE: {
                    FALSE: '0',
                    TRUE: '1',
                },
                isEditingCartItem: false,
                eventListeners: {
                    ['@update-prices-<?= $productId ?>.window'](event) {
                        this.activeProductsPriceData = event.detail;
                        this.recalulateCustomizableProductPrices();
                        this.calculatePriceLabelVisibility();
                    },
                    ['@update-product-final-price.window'](event) {
                        this.calculatedFinalPrice = event.detail;
                    },
                    ['@private-content-loaded.window'](event) {
                        const items = event.detail?.data?.cart?.items;
                        this.cartItems = items;

                        if(this.isEditingCartItem) {
                            this.getOptionsFromCartItem(this.cartItems);
                            this.stopLoading();
                            this.fetchApo();
                        }
                    },
                }
            }
        }
    </script>

    <?= $block->getChildHtml('mageworx.apo.product.js.queries') ?>
    <?= $block->getChildHtml('mageworx.apo.product.js.swatch_images') ?>
    <?= $block->getChildHtml('mageworx.apo.product.js.product_price') ?>
    <?= $block->getChildHtml('mageworx.apo.product.js.options_helpers') ?>
    <?= $block->getChildHtml('mageworx.apo.product.js.load_options') ?>
    <?= $block->getChildHtml('mageworx.apo.product.js.general_helpers') ?>
    <?= $block->getChildHtml('mageworx.apo.product.js.fetch_configs') ?>
    <?= $block->getChildHtml('mageworx.apo.product.js.dependency') ?>
    <?= $block->getChildHtml('mageworx.apo.product.js.custom_validate') ?>
    <?= $block->getChildHtml('mageworx.apo.product.js.change_field') ?>

    <div x-cloak class="my-4" id="mw-apo-block" x-init="$nextTick(() => { initilize() })" x-bind="eventListeners"
         x-data="{...initApo(), ...apoQueries(), ...apoSwatchImages(), ...apoProductPrice(), ...apoOptionsHelpers(), ...apoLoadOptions(), ...apoGeneralHelpers(), ...apoFetchConfigs(), ...apoDependency(), ...apoCustomValidate(), ...apoChangeField()}">
        <template x-if="!isInitialized && !isLoading && isProductAvailable">
            <button class="btn btn-primary my-4" @click="fetchApo()" x-show="!isEditingCartItem">
                <?= $escaper->escapeHtml(__('Customize and add to cart')); ?>
            </button>
        </template>
        <span x-show="!isInitialized && isLoading">
            <div class="h-full flex gap-x-4 items-center justify-center mb-4">
                <div style="border-top-color:transparent"
                    class="w-12 h-12 border-4 border-primary border-solid rounded-full animate-spin"></div>
            </div>
        </span>

        <template x-if="options.length > 0">
            <div class="grid grid-cols-2 border-t border-gray-300 gap-x-7">
                <?= $block->getChildHtml('mageworx.apo.product.title') ?>
                <?= $block->getChildHtml('mageworx.apo.product.additional_price') ?>
                <template x-for="option in options">
                    <div>
                        <?= $block->getChildHtml('mageworx.apo.product.form.date_option') ?>
                        <?= $block->getChildHtml('mageworx.apo.product.form.dropdown_option') ?>
                        <?= $block->getChildHtml('mageworx.apo.product.form.file_option') ?>
                        <?= $block->getChildHtml('mageworx.apo.product.form.multi_option') ?>
                        <?= $block->getChildHtml('mageworx.apo.product.form.radio_option') ?>
                        <?= $block->getChildHtml('mageworx.apo.product.form.text_option') ?>
                        <?= $block->getChildHtml('mageworx.apo.product.form.textarea_option') ?>
                        <template>
                        </template>
                        <!-- CHECKBOX OPTION as full-width (col-span-2) -->



                    </div>

                </template>
                <template x-for="option in options">
                    <div class="col-span-2 w-full">
                        <?= $block->getChildHtml('mageworx.apo.product.form.checkbox_option') ?>
                    </div>
                </template>
                <?= $block->getChildHtml('mageworx.apo.product.shareable_link') ?>
            </div>
            <template x-for="option in options">

            </template>
        </template>
    </div>
<?php endif; ?>
