<?php
/**
 * Hyvä Themes - https://hyva.io
 * Copyright © Hyvä Themes. All rights reserved.
 * See COPYING.txt for license details.
 */

declare(strict_types=1);

use Hyva\Theme\Model\ViewModelRegistry;
use Hyva\Theme\ViewModel\HyvaCsp;
use Hyva\Theme\ViewModel\Cookie;
use Magento\Framework\Escaper;
use Magento\Framework\View\Element\Template;

/** @var Template $block */
/** @var Escaper $escaper */
/** @var HyvaCsp $hyvaCsp */
/** @var ViewModelRegistry $viewModels */

/** @var Cookie $cookieSettings */
$cookieSettings = $viewModels->require(Cookie::class);

?>
<script>
    {
        const private_content_key = 'mage-cache-storage';
        const private_content_expire_key = 'mage-cache-timeout';
        const private_content_version_key = 'private_content_version';
        const section_data_ids_key = 'section_data_ids';
        const mage_cache_session_id_key = 'mage-cache-sessid';
        const last_visited_store_key = 'last_visited_store';

        const ttl = <?= $cookieSettings->getLifetime() ?: 3600 ?>;

<?php
        /**
         * The `hyva` JS namespace is being set by Hyva_Theme/src/view/frontend/templates/page/js/hyva.phtml
         * and should be included through Hyva_Theme/src/view/frontend/layout/default_hyva.xml
         */
?>
        if (typeof hyva === 'undefined' || (!hyva.getBrowserStorage || !hyva.getCookie || !hyva.setCookie)) {
            console.warn("Hyvä helpers are not loaded yet. Make sure they are included before this script");
        }

        function loadSectionData () {
            const browserStorage = hyva.getBrowserStorage();
            if (!browserStorage) {
                typeof window.dispatchMessages !== "undefined" && window.dispatchMessages(
                    [{
                        type: "warning",
                        text: "<?= $escaper->escapeHtml(__('Please enable LocalStorage in your browser.')) ?>"
                    }]
                );
                return;
            }
            try {
                let isInvalid = false;

<?php
                /**
                 * Usually store switch is made via POST requests, but if this happen on other ways (eg. the customer
                 * changing manually the base url, or landing from search engines on a different store) we need to
                 * request again private contents
                 */
?>
                if (hyva.getCookie(last_visited_store_key) !== CURRENT_STORE_CODE) {
                    isInvalid = true;
                }
                hyva.setCookie(last_visited_store_key, CURRENT_STORE_CODE, false, false);

<?php
                /**
                 * The `mage-cache-sessid` cookie is being unset from backend to
                 * indicate that sectionData is invalidated and needs to be reloaded
                 * in the frontend. So we mark it as invalid, and then re-set the
                 * `mage-cache-sessid` cookie
                 */
?>
                if (!hyva.getCookie(mage_cache_session_id_key)) {
                    isInvalid = true;
                    browserStorage.removeItem(private_content_key);
                    const skipSetDomain = true;
                    const days = false;
                    hyva.setCookie(mage_cache_session_id_key, true, days, skipSetDomain)
                }

                const cookieVersion = hyva.getCookie(private_content_version_key);
                const storageVersion = browserStorage.getItem(private_content_version_key);

                if (cookieVersion && !storageVersion || cookieVersion !== storageVersion) {
                    isInvalid = true;
                }

                const privateContentExpires = browserStorage.getItem(private_content_expire_key);
                if (privateContentExpires && new Date(privateContentExpires) < new Date()) {
                    browserStorage.removeItem(private_content_key);
                }

                if (isInvalid && cookieVersion) {
                    fetchPrivateContent([]);
                } else if (cookieVersion && storageVersion && cookieVersion === storageVersion) {
                    const privateContent = JSON.parse(browserStorage.getItem(private_content_key));
                    if (
                        privateContent &&
                        privateContentExpires &&
                        privateContent.cart &&
                        privateContent.customer
                    ) {
                        dispatchPrivateContent(privateContent);
                    } else {
                        fetchPrivateContent([]);
                    }
                } else {
                    if (document.getElementById('default-section-data')) {
                        const privateContent = JSON.parse(document.getElementById('default-section-data').innerText.trim());
                        dispatchPrivateContent(privateContent);
                    } else {
                        dispatchPrivateContent({});
                    }
                }

            } catch (error) {
                console.warn('Error retrieving Private Content:', error);
            }
        }

        hyva.alpineInitialized(loadSectionData)
        window.addEventListener('reload-customer-section-data', loadSectionData);

<?php
        /**
         * Extension point: custom scripts and modules can use a Proxy to intercept and mutate section data before it is dispatched.
         * Don't do expensive operations during the call. It can be called multiple times on a page.
         */
?>
        window.processSectionDataBeforeDispatch = window.processSectionDataBeforeDispatch || (data => data);

        function dispatchPrivateContent(data) {

            const privateContentEvent = new CustomEvent("private-content-loaded", {
                detail: {
                    data: window.processSectionDataBeforeDispatch(data)
                }
            });
            window.dispatchEvent(privateContentEvent);
        }

<?php
        /**
         * We use 'X-Requested-With': 'XMLHttpRequest' to prevent Magento from clearing the customer session
         * in \Magento\PageCache\Model\DepersonalizeChecker::checkIfDepersonalize
         * Otherwise, \Magento\Tax\Plugin\Checkout\CustomerData\Cart::afterGetSectionData can't add tax to
         * cart items.
         */
?>
        function fetchPrivateContent(sections) {
            fetch(`${BASE_URL}customer/section/load/?sections=${encodeURIComponent(sections.join(','))}`, {
                method: 'GET',
                headers: {
                    'Content-Type': 'application/json',
                    'X-Requested-With': 'XMLHttpRequest'
                }
            })
                .then(response => response.ok && response.json())
                .then(
                    data => {
                        if (data) {
                            try {
                                const browserStorage = hyva.getBrowserStorage();

                                // merge new data preserving non-invalidated sections
                                const oldSectionData = JSON.parse(browserStorage.getItem(private_content_key) || '{}') || {};

                                <?php /** Ensure no checkout data remains after logout (from Luma checkout) */ ?>
                                if ((! data.cart || ! data.cart.cartId) && oldSectionData['checkout-data']) {
                                    delete oldSectionData['checkout-data'];
                                }
                                const newSectionData = Object.assign(oldSectionData, data);

                                dispatchPrivateContent(newSectionData);

                                // don't persist messages, they've been dispatched already
                                if (newSectionData.messages && newSectionData.messages.messages ) {
                                    newSectionData.messages.messages = [];
                                }

                                browserStorage.setItem(private_content_key, JSON.stringify(newSectionData));

                                const expiresAt = new Date(Date.now() + (ttl * 1000)).toISOString();
                                browserStorage.setItem(private_content_expire_key, expiresAt);

                                const newCookieVersion = hyva.getCookie(private_content_version_key);
                                browserStorage.setItem(private_content_version_key, newCookieVersion);

                                // We don't need the section_data_ids in Hyvä, but we store them for compatibility
                                // with Luma Fallback. Otherwise, not all sections are loaded in Luma Checkout
                                hyva.setCookie(
                                    section_data_ids_key,
                                    JSON.stringify(
                                        Object.keys(data).reduce((sectionDataIds, sectionKey) => {
                                            sectionDataIds[sectionKey] = data[sectionKey]['data_id'];
                                            return sectionDataIds;
                                        }, {})
                                    ),
                                    false,
                                    true
                                );
                            } catch (error) {
                                console.warn("Couldn't store privateContent", error);
                            }
                        }
                    }
                )
                .catch(error => {
                    console.warn("Couldn't fetch privateContent", error);
                });
        }
    }
    //# sourceURL=hyva-private-content.js
</script>
<?php $hyvaCsp->registerInlineScript() ?>
