<?php
/*
 * Copyright Magmodules.eu. All rights reserved.
 * See COPYING.txt for license details.
 */

use Magento\Framework\Escaper;
use Mollie\Payment\Block\Applepay\Shortcut\Button;

/** @var Escaper $escaper */
/** @var Button $block */

?>
<script>
    function prepareMollieApplePayMinicart() {
        const objectToFormData = (object, prefix = null, formDataObject = null) => {
            const formData = formDataObject || new FormData();
            Object.keys(object).forEach(key => {
                const value = object[key];
                const name = prefix ? `${prefix}[${key}]` : key;
                if (value instanceof Object) {
                    objectToFormData(value, name, formData);
                } else {
                    formData.append(name, value);
                }
            });

            return new URLSearchParams(formData).toString();
        };

        return {
            totalAmount: 0,

            init() {
                // Normally we would use private-content-loaded to get this information, but this component is
                // rendered after this event has been dispatched. So get the information from the browser storage.
                const browserStorage = hyva.getBrowserStorage();
                if (browserStorage) {
                    const cacheStorage = browserStorage.getItem('mage-cache-storage');
                    const cart = JSON.parse(cacheStorage).cart;

                    this.totalAmount = cart.subtotalAmount;
                }

                window.addEventListener('private-content-loaded', event => {
                    this.totalAmount = event.detail.data.cart.subtotalAmount
                })
            },

            isLoading(value) {
                // This loader lives outside the cart in view/frontend/templates/applepay/loader.phtml
                const eventName = value ? 'mollie-applepay-loading-start' : 'mollie-applepay-loading-stop';
                window.dispatchEvent(new CustomEvent(eventName, {}))
            },

            pay() {
                const amount = this.totalAmount;
                let countryCode, postalCode, shippingMethods, selectedShippingMethod, quoteTotals;

                const request = {
                    countryCode: "<?= $escaper->escapeJs($block->getStoreCountry()); ?>",
                    currencyCode: "<?= $escaper->escapeJs($block->getStoreCurrency()); ?>",
                    supportedNetworks: <?= /* @noEscape */ json_encode($block->getSupportedNetworks()); ?>,
                    merchantCapabilities: ['supports3DS'],
                    total: {
                        label: "<?= $escaper->escapeJs($block->getStoreName()); ?>",
                        amount: amount
                    },
                    shippingType: 'shipping',
                    requiredBillingContactFields: [
                        'postalAddress',
                        'name',
                        'email',
                        'phone'
                    ],
                    requiredShippingContactFields: [
                        'postalAddress',
                        'name',
                        'email',
                        'phone'
                    ]
                }

                let session = new ApplePaySession(3, request);

                const getTotal = () => {
                    const total = quoteTotals.find(item => item.code === 'grand_total') || quoteTotals[quoteTotals.length - 1];

                    total.label = "<?= $escaper->escapeJs($block->getStoreName()); ?>";

                    const payload = { total };
                    window.dispatchEvent(new CustomEvent('mollie-applepay-total', {
                        detail: payload,
                    }));

                    return payload.total;
                };

                const getLineItems = () => {
                    let totals = [...quoteTotals];
                    totals = totals.filter(item => item.code !== 'grand_total');

                    const payload = { lineItems: totals };
                    window.dispatchEvent(new CustomEvent('mollie-applepay-lineitems', {
                        detail: payload,
                    }));

                    return payload.lineItems;
                };

                const handleAjaxError = (message) => {
                    this.isLoading(false);
                    session.abort();

                    dispatchMessages([
                        {
                            text: message,
                            type: 'error'
                        }
                    ]);
                };

                session.onpaymentmethodselected = () => {
                    session.completePaymentMethodSelection(getTotal(), []);
                };

                session.onshippingcontactselected = (event) => {
                    countryCode = event.shippingContact.countryCode;
                    postalCode = event.shippingContact.postalCode;

                    fetch(`${BASE_URL}mollie/applePay/shippingMethods?form_key=${hyva.getFormKey()}`, {
                        method: 'POST',
                        headers: {
                            'content-type': 'application/x-www-form-urlencoded; charset=UTF-8',
                        },
                        body: 'countryCode=' + event.shippingContact.countryCode +
                            '&postalCode=' + event.shippingContact.postalCode
                    })
                        .then(async (response) => {
                            if (!response.ok) {
                                const data = await response.json();
                                if (data.message) {
                                    throw new Error(data.message);
                                }

                                throw new Error('Network response was not ok');
                            }
                            return response.json();
                        })
                        .then(result => {
                            shippingMethods = result.shipping_methods;
                            selectedShippingMethod = result.shipping_methods[0];
                            quoteTotals = result.totals;

                            session.completeShippingContactSelection(
                                ApplePaySession.STATUS_SUCCESS,
                                result.shipping_methods,
                                getTotal(),
                                getLineItems()
                            );
                        })
                        .catch(error => handleAjaxError(error));
                };

                session.onshippingmethodselected = (event) => {
                    selectedShippingMethod = event.shippingMethod;

                    fetch(`${BASE_URL}mollie/applePay/shippingMethods?form_key=${hyva.getFormKey()}`, {
                        method: 'POST',
                        headers: {
                            'content-type': 'application/x-www-form-urlencoded; charset=UTF-8',
                        },
                        body: objectToFormData({
                            shippingMethod: selectedShippingMethod,
                            countryCode: countryCode,
                            postalCode: postalCode
                        })
                    })
                        .then(async (response) => {
                            if (!response.ok) {
                                const data = await response.json();
                                if (data.message) {
                                    throw new Error(data.message);
                                }

                                throw new Error('Network response was not ok');
                            }
                            return response.json();
                        })
                        .then(result => {
                            quoteTotals = result.totals;

                            session.completeShippingMethodSelection(
                                ApplePaySession.STATUS_SUCCESS,
                                getTotal(),
                                getLineItems()
                            );
                        })
                        .catch(error => handleAjaxError(error));
                };

                session.onpaymentauthorized = (event) => {
                    fetch(`${BASE_URL}mollie/applePay/placeOrder?form_key=${hyva.getFormKey()}`, {
                        method: 'POST',
                        headers: {
                            'content-type': 'application/x-www-form-urlencoded; charset=UTF-8',
                        },
                        body: objectToFormData({
                            shippingMethod: selectedShippingMethod,
                            billingAddress: event.payment.billingContact,
                            shippingAddress: event.payment.shippingContact,
                            applePayPaymentToken: JSON.stringify(event.payment.token)
                        })
                    })
                        .then(async (response) => {
                            if (!response.ok) {
                                const data = await response.json();
                                if (data.message) {
                                    throw new Error(data.message);
                                }

                                throw new Error('Network response was not ok');
                            }
                            return response.json();
                        })
                        .then(result => {
                            if (!session) {
                                console.warn('Payment canceled');
                                return;
                            }

                            if (result.error) {
                                handleAjaxError(result.error_message);
                                return;
                            }

                            if (!result.url) {
                                handleAjaxError('Something went wrong, please try again later.');
                                return;
                            }

                            session.completePayment(ApplePaySession.STATUS_SUCCESS);

                            location.href = result.url;
                        })
                        .catch(error => handleAjaxError(error));
                };

                session.onvalidatemerchant = (event) => {
                    fetch(
                        `${BASE_URL}mollie/checkout/applePayValidation?form_key=${hyva.getFormKey()}`,
                        {
                            method: 'POST',
                            headers: {
                                'content-type': 'application/x-www-form-urlencoded; charset=UTF-8',
                            },
                            body: objectToFormData({validationURL: event.validationURL}),
                        }
                    )
                        .then((response) => {
                            if (!response.ok) {
                                throw new Error('Merchant validation failed');
                            }

                            return response.json()
                        })
                        .then((result) => session.completeMerchantValidation(result))
                        .catch(error => handleAjaxError(error));
                };

                session.oncancel = () => {
                    this.isLoading(false);
                    session = null;
                }

                this.isLoading(true);
                session.begin();
            }
        }
    }

    window.addEventListener(
        'alpine:init',
        () => Alpine.data('prepareMollieApplePayMinicart', prepareMollieApplePayMinicart),
        {once: true}
    )
</script>
<?php isset($hyvaCsp) && $hyvaCsp->registerInlineScript() ?>
