<?php
declare(strict_types=1);

use Hyva\Theme\Model\ViewModelRegistry;
use Hyva\Theme\ViewModel\SwatchRenderer;
use Magento\Framework\Escaper;
use Magento\Swatches\Block\Product\Renderer\Listing\Configurable;
use Magento\Swatches\ViewModel\Product\Renderer\Configurable as ConfigurableViewModel;

// phpcs:disable Generic.Files.LineLength.TooLong

/** @var Configurable $block */
/** @var Escaper $escaper */
/** @var ViewModelRegistry $viewModels */

/** @var ConfigurableViewModel $configurableViewModel */
$configurableViewModel = $viewModels->require(ConfigurableViewModel::class);

$product = $block->getProduct();
$productId = $product->getId();

$attributes = $block->decorateArray($block->getAllowAttributes());

/** @var SwatchRenderer $swatchRendererViewModel */
$swatchRendererViewModel = $viewModels->require(SwatchRenderer::class);
$layout = $block->getLayout();
$swatchItemBlock = $layout->getBlock('product.swatch.item');
$swatchItemBlock->setData('product_id', $productId);
?>
<?php if ($product->isSaleable() && count($attributes)): ?>

    <script>
        function initConfigurableSwatchOptions_<?= (int) $productId ?>() {
            const configurableOptionsComponent = initConfigurableOptions(
                '<?= (int) $productId ?>',
                <?= /* @noEscape */ $block->getJsonConfig() ?>
            );
            const swatchOptionsComponent = initSwatchOptions(<?= /* @noEscape */ $block->getJsonSwatchConfig() ?>);

            return Object.assign(
                configurableOptionsComponent,
                swatchOptionsComponent,
                {
                    mediaCallback: "<?= $escaper->escapeJs($escaper->escapeUrl($block->getMediaCallback())) ?>",
                    changeOption(optionId, value, skipUpdateGallery) {
                        if (value === '') {
                            this.selectedValues = this.removeAttrFromSelection(this.selectedValues, optionId)
                        } else {
                            this.selectedValues[optionId] = value;
                        }
                        this.findSimpleIndex();
                        this.findAllowedAttributeOptions();
                        this.updatePrices();
                        setTimeout(() => {
                            this.updatePrices();
                        },300)
                        !skipUpdateGallery && this.updateGallery();

                        const candidates = this.findProductIdsForPartialSelection(this.selectedValues);

                        <?php /* The skuCandidates property is not set if the Magento_Inventory (MSI) modules are disabled. */ ?>
                        window.dispatchEvent(new CustomEvent('listing-configurable-selection-changed', {
                            detail: {
                                productId: this.productId,
                                optionId,
                                value,
                                productIndex: this.productIndex,
                                selectedValues: this.selectedValues,
                                candidates: candidates,
                                skuCandidates: Object.values(candidates).map(id => this.optionConfig.sku?.[id] ?? null).filter(Boolean),
                            }
                        }));
                    },
                    updateGallery() {
                        if (!this.productIndex) {
                            return;
                        }

                        fetch(`${this.mediaCallback}?product_id=${this.productIndex}&isAjax=true`, {
                                method: 'GET',
                                headers: {
                                    'Content-Type': 'application/json',
                                    'X-Requested-With': 'XMLHttpRequest'
                                }
                            }
                        ).then(response => {
                                return response.json()
                            }
                        ).then(data => {
                            if (data.errors) {
                                // non critical failure only console logged
                                console.warn(data.errors);
                            } else {
                                const image = data && data.medium;

                                image && window.dispatchEvent(
                                    new CustomEvent(
                                        "update-gallery-<?= (int)$productId ?>",
                                        {detail: image}
                                    )
                                );
                            }
                        }).catch(error => {
                            console.warn(error)
                        });
                    },
                    preselectQuerystringItems() {
                        // pre-select option like ?size=167
                        const urlQueryParams = new URLSearchParams(window.location.search.replace('?', ''));
                        Object.values(this.optionConfig.attributes).map(attribute => {
                            // Don't update images on load, since PLPs already set the main image to the selected options
                            const skipUpdateGallery = true;
                            urlQueryParams.get(attribute.code) &&
                            this.changeOption(attribute.id, urlQueryParams.get(attribute.code), skipUpdateGallery);
                        });
                    },
                    mouseDown: false,
                    startX: 0,
                    maxScroll: 0,
                    scrollLeft: null,
                    slider: null,
                    scrollEvents: {
                        ['@mousedown'](e) {
                            this.slider = e.target.closest('.snap');
                            if (!this.slider) {
                                return;
                            }
                            this.maxScroll = this.slider.scrollWidth - this.slider.offsetWidth;
                            this.startX = e.pageX - this.slider.offsetLeft;
                            this.scrollLeft = this.slider.scrollLeft;
                            this.mouseDown = true;
                        },
                        ['@mouseout.self']() {
                            this.mouseDown = false;
                        },
                        ['@mouseup']() {
                            this.mouseDown = false;
                        },
                        ['@mousemove'](e) {
                            e.preventDefault();
                            if (!this.mouseDown) {
                                return;
                            }
                            const x = e.pageX - this.slider.offsetLeft;
                            const scroll = x - this.startX;
                            const scrollLeft = this.scrollLeft - scroll;

                            if (scrollLeft > this.maxScroll) {
                                this.slider.scrollLeft = this.maxScroll;
                                return
                            }
                            this.slider.scrollLeft = this.scrollLeft - scroll;
                        },
                        ['@onselectstart']() {
                            return false;
                        }
                    },
                    resizeEvent() {
                        Array.from(this.$root.querySelectorAll('.snap')).forEach(slider => {
                            slider.scrollLeft = 0;
                        })
                    }
                }
            );
        }

    </script>

<div x-data="initConfigurableSwatchOptions_<?= (int) $productId ?>()"
     x-defer="intersect"
     x-init="findAllowedAttributeOptions(); initShowSwatchesIntersect();"
     @private-content-loaded.window="onGetCartData($event.detail.data)"
     @resize.window="resizeEvent()"
     class="mb-2 relative"
>
    <div>
        <?php foreach ($attributes as $attribute): ?>
            <?php $attributeId = $attribute->getAttributeId(); ?>
            <?php $productAttribute = $attribute->getProductAttribute();  ?>
            <?php if ($swatchRendererViewModel->isSwatchAttribute($productAttribute)): ?>
                <div class="swatch-attribute border-t last:border-b border-container <?= $escaper->escapeHtmlAttr($productAttribute->getAttributeCode()) ?>">
                    <div class="w-full overflow-x-hidden swatch-attribute-options min-h-14">
                        <template x-if="showSwatches">
                            <div class="flex flex-nowrap w-full overflow-auto snap items-center py-1"
                                id="attribute-label-<?= $escaper->escapeHtmlAttr($productId . '-' . $attributeId) ?>"
                                role="radiogroup"
                                x-bind="scrollEvents"
                                aria-label="<?= $escaper->escapeHtml($productAttribute->getStoreLabel()) ?>"
                            >
                                <template x-for="(item, index) in optionConfig.attributes[<?= (int) $attributeId ?>].options"
                                          :key="item.id"
                                >
                                    <?= /* @noEscape */ $swatchItemBlock->setData('attribute_id', $attributeId)->toHtml(); ?>
                                </template>
                            </div>
                        </template>
                    </div>
                </div>
            <?php endif; ?>
        <?php endforeach; ?>
    </div>
    <?php if ($configurableViewModel->getShowSwatchTooltip()): ?>
        <?= /* @noEscape */ $block->getBlockHtml('product.swatch.tooltip') ?>
    <?php endif; ?>
</div>
<?php endif; ?>
