/*!
 * Crafted with ❤ by Salla
 */
import { proxyCustomElement, HTMLElement, createEvent, h, Host } from '@stencil/core/internal/client';
import { a as axios } from './axios.js';

var http = {
    request(method, url, data, successCb = null, errorCb = null) {
        return axios
            .request({url, data, method: method.toLowerCase(), responseType: 'json'})
            .then(successCb)
            .catch(errorCb);
    },

    get(url, successCb = null, errorCb = null, data) {
        // return this.request('get', url, data, successCb, errorCb);
        return axios
            .get(url, {params: data})
            .then(successCb)
            .catch(errorCb);
    },

    post(url, data, successCb = null, errorCb = null) {
        return this.request('post', url, data, successCb, errorCb);
    },

    put(url, data, successCb = null, errorCb = null) {
        return this.request('put', url, data, successCb, errorCb);
    },

    delete(url, data, successCb = null, errorCb = null) {
        return this.request('delete', url, data, successCb, errorCb);
    },

    requestWithSupportAjax(url, payload, method = 'post') {
        return new Promise((resolve, reject) => {
            if (!window?.isLegacyTheme) {
                return this.request(method, url, payload, ({data}) => {
                    return resolve(data);
                }, ({response}) => {
                    return reject(response);
                })
            }

            /**
             * @deprecated to support legacy themes
             */
            $.ajax({
                url: url,
                method: method.toUpperCase(),
                data: payload,
                async: false,
                success: function ({data}) {
                    return resolve(data);
                },
                error: function ({response}) {
                    return reject(response);
                }
            });
        })
    }
};

var DetectOS = {
    options: [],
    header: [navigator.platform, navigator.userAgent, navigator.appVersion, navigator.vendor, window.opera],
    dataos: [
        {name: 'Windows Phone', value: 'Windows Phone', version: 'OS'},
        {name: 'Windows', value: 'Win', version: 'NT'},
        {name: 'iPhone', value: 'iPhone', version: 'OS'},
        {name: 'iPad', value: 'iPad', version: 'OS'},
        {name: 'Kindle', value: 'Silk', version: 'Silk'},
        {name: 'Android', value: 'Android', version: 'Android'},
        {name: 'PlayBook', value: 'PlayBook', version: 'OS'},
        {name: 'BlackBerry', value: 'BlackBerry', version: '/'},
        {name: 'Macintosh', value: 'Mac', version: 'OS X'},
        {name: 'Linux', value: 'Linux', version: 'rv'},
        {name: 'Palm', value: 'Palm', version: 'PalmOS'}
    ],
    databrowser: [
        {name: 'Chrome', value: 'Chrome', version: 'Chrome'},
        {name: 'Firefox', value: 'Firefox', version: 'Firefox'},
        {name: 'Safari', value: 'Safari', version: 'Version'},
        {name: 'Internet Explorer', value: 'MSIE', version: 'MSIE'},
        {name: 'Opera', value: 'Opera', version: 'Opera'},
        {name: 'BlackBerry', value: 'CLDC', version: 'CLDC'},
        {name: 'Mozilla', value: 'Mozilla', version: 'Mozilla'}
    ],
    init: function () {
        var agent = this.header.join(' '),
            os = this.matchItem(agent, this.dataos),
            browser = this.matchItem(agent, this.databrowser);

        return {os: os, browser: browser};
    },
    matchItem: function (string, data) {
        var i = 0,
            j = 0,
            regex,
            regexv,
            match,
            matches,
            version;

        for (i = 0; i < data.length; i += 1) {
            regex = new RegExp(data[i].value, 'i');
            match = regex.test(string);
            if (match) {
                regexv = new RegExp(data[i].version + '[- /:;]([\\d._]+)', 'i');
                matches = string.match(regexv);
                version = '';
                if (matches) {
                    if (matches[1]) {
                        matches = matches[1];
                    }
                }
                if (matches) {
                    matches = matches.split(/[._]+/);
                    for (j = 0; j < matches.length; j += 1) {
                        if (j === 0) {
                            version += matches[j] + '.';
                        } else {
                            version += matches[j];
                        }
                    }
                } else {
                    version = '0';
                }
                return {
                    name: data[i].name,
                    version: parseFloat(version)
                };
            }
        }
        return {name: 'unknown', version: 0};
    }
};

/**
 * @typedef {Object} ApplePayPaymentContact
 * @property {string} phoneNumber
 * @property {string} emailAddress
 * @property {string} givenName
 * @property {string} familyName
 * @property {string} [phoneticGivenName]
 * @property {string} [phoneticFamilyName]
 * @property {string[]} addressLines
 * @property {string} [subLocality]
 * @property {string} locality
 * @property {string} postalCode
 * @property {string} [subAdministrativeArea]
 * @property {string} administrativeArea
 * @property {string} country
 * @property {string} countryCode
 */


/**
 *
 * @param {SallaApplePay} SallaApplePay
 * @param {boolean} isAuthorized
 * @param {ApplePayPaymentContact} shippingContact
 *
 */
async function mutateShippingContact(SallaApplePay, shippingContact, isAuthorized = false) {
  salla.logger.log('🍏 Pay: mutateShippingContact called', shippingContact, isAuthorized);

  if (!SallaApplePay.detail.requiredShippingContactFields || SallaApplePay.detail.requiredShippingContactFields.length == 0) {
    return;
  }

  if (isAuthorized) {
    if (isGuestCheckout()) {

      if (
        !shippingContact.emailAddress ||
        !shippingContact.givenName ||
        !shippingContact.familyName ||
        !shippingContact.phoneNumber
      ) {
  
        salla.logger.warn('🍏 Pay: Guest contact fields are required', shippingContact);
  
        const errors = [];
        if (!shippingContact.emailAddress) {
          errors.push(new window.ApplePayError('shippingContactInvalid', 'emailAddress', 'Email address is required'));
        }

        if (!shippingContact.phoneNumber) {
          errors.push(new window.ApplePayError('shippingContactInvalid', 'phoneNumber', 'Phone number is required'));
        }

        if (!shippingContact.givenName || !shippingContact.familyName) {
          errors.push(new window.ApplePayError('shippingContactInvalid', 'name', 'Name is required'));
        }

        SallaApplePay.session.completePayment({
          status: SallaApplePay.session.STATUS_INVALID_SHIPPING_CONTACT,
          errors: errors
        });

        return;
      }

      await updateGuestContact(SallaApplePay, shippingContact);

    }

    // if authorized and not guest checkout, do nothing address already added
    return;
  }

  if (!SallaApplePay.detail.requiredShippingContactFields.includes('postalAddress')) {
    return;
  }

  return http.post(
    SallaApplePay.detail.shippingContactSelected.url.replace('{id}', SallaApplePay.id),
    {
      'country': shippingContact.country,
      'city': shippingContact.locality,
      'local': shippingContact.subLocality || shippingContact.administrativeArea || shippingContact.locality,
      'description': shippingContact.subAdministrativeArea,
      'street': shippingContact.addressLines?.join(", ") || shippingContact.administrativeArea,
      'country_code': shippingContact.countryCode,
      'postal_code': shippingContact.postalCode,
    },
    async ({ data }) => {
      if (typeof SallaApplePay.detail.shippingContactSelected.onSuccess === 'function') {
        SallaApplePay.detail.shippingContactSelected.onSuccess(data);
      }

      SallaApplePay.address_id = data.data.address_id;
      SallaApplePay.shipping_methods = data.data.shipping_methods;

      if (!SallaApplePay.shipping_methods || (SallaApplePay.shipping_methods && !SallaApplePay.shipping_methods.length)) {
        salla.logger.warn('🍏 Pay: We dont found any supported methods', data);

        SallaApplePay.session.completeShippingContactSelection({
          status: SallaApplePay.session.STATUS_INVALID_SHIPPING_POSTAL_ADDRESS,
          errors: [
            new window.ApplePayError('addressUnserviceable')
          ]
        });

        return
      }

      try {
        await SallaApplePay.selectApplePayShippingMethod(SallaApplePay.shipping_methods[0]);
      } catch (error) {
        salla.logger.warn('Failed set the shipping details to api', error);

        SallaApplePay.session.completeShippingContactSelection({
          status: SallaApplePay.session.STATUS_INVALID_SHIPPING_POSTAL_ADDRESS,
          errors: [
            new window.ApplePayError('addressUnserviceable')
          ]
        });

        return;
      }

      try {
        await SallaApplePay.recalculateTotal();
      } catch (error) {
        salla.logger.warn('🍏 Pay: Failed recalculate total', error);

        SallaApplePay.session.completeShippingContactSelection({
          status: SallaApplePay.session.STATUS_INVALID_SHIPPING_POSTAL_ADDRESS,
          errors: [
            new window.ApplePayError('addressUnserviceable')
          ]
        });

        return;
      }

      const updatedShippingContactSelection = {
        newTotal: SallaApplePay.prepareTotal(),
        newLineItems: SallaApplePay.prepareLineItems(),
        newShippingMethods: SallaApplePay.mappingShippingMethods(SallaApplePay.shipping_methods)
      };

      salla.logger.log('🍏 Pay: completeShippingContactSelection', updatedShippingContactSelection);

      SallaApplePay.session.completeShippingContactSelection(updatedShippingContactSelection);
    },
    ({ response }) => {
      salla.logger.warn('🍏 Pay: Failed add address via api', response);

      if (typeof SallaApplePay.detail.shippingContactSelected.onFailed === 'function') {
        SallaApplePay.detail.shippingContactSelected.onFailed(response);
      }

      // parse 422 errors
      let fields = response?.data?.error?.fields;

      let errors = getApplePayErrors({
        countryCode: fields?.country_code && fields.country_code.length > 0 ? fields.country_code[0] : null,
        locality: fields?.city && fields.city.length > 0 ? fields.city[0] : null,
        country: fields?.country && fields.country.length > 0 ? fields.country[0] : null,
      });

      if (errors.length === 0 && response?.data?.error?.message) {
        errors.push(new window.ApplePayError('shippingContactInvalid', 'locality', response?.data?.error?.message));
      }

      SallaApplePay.session.completeShippingContactSelection({
        newTotal: SallaApplePay.prepareTotal(),
        newLineItems: SallaApplePay.prepareLineItems(),
        status: SallaApplePay.session.STATUS_INVALID_SHIPPING_POSTAL_ADDRESS,
        errors: errors
      });
    }
  );
}

function isGuestCheckout() {
  return salla.config.isGuest() && salla.config.get('store.features').includes('guest-checkout');
}

/**
 * Update guest contact
 *
 * @param {SallaApplePay} SallaApplePay
 * @param {ApplePayPaymentContact} shippingContact
 *
 */
async function updateGuestContact(SallaApplePay, shippingContact) {
  salla.logger.log('🍏 Pay: Updating guest contact', shippingContact);

  return new Promise((resolve, reject) => {
    http.post(
      SallaApplePay.detail.guestContactSelected.url.replace('{id}', SallaApplePay.id),
      {
        'email': shippingContact.emailAddress || null,
        'first_name': shippingContact.givenName || null,
        'last_name': shippingContact.familyName || null,
        'phone_number': shippingContact.phoneNumber || null,
        'country_code': shippingContact.countryCode || null,
      },
      async ({ data }) => {
        if (typeof SallaApplePay.detail.guestContactSelected?.onSuccess === 'function') {
          SallaApplePay.detail.guestContactSelected.onSuccess(data);
        }
        resolve(data);
      },
      ({ response }) => {
        salla.logger.warn('🍏 Pay: Failed to update guest contact via api', response);

        if (typeof SallaApplePay.detail.guestContactSelected?.onFailed === 'function') {
          SallaApplePay.detail.guestContactSelected.onFailed(response);
        }

        // Reject the promise so it can be caught in onPaymentAuthorized
        reject({ response });
      }
    );
  });
}

function getApplePayErrors(fields) {
  return Object.entries(fields)
    .filter(([field, messages]) => messages && messages.length > 0)
    .map(([field, messages]) => new window.ApplePayError('shippingContactInvalid', field, messages[0]));
}

window.Salla = window.Salla || {};
window.Salla.Payments = window.Salla.Payments || {};

/**
 * Full Example
 *
 * Salla.event.createAndDispatch('payments::apple-pay.start-transaction', {
 *                  amount: 1000,
 *                  validateMerchant: {
 *                      url: '{{ route('cp.marketplace.cart.pay', ['cart' => $cart]) }}',
 *                      // onFailed: (response) => {
 *                      //     laravel.ajax.errorHandler(response);
 *                      //     this.onCancel({}, response.data.error.message);
 *                      // },
 *                      // onSuccess: (response) => {
 *                      //     laravel.ajax.successHandler(response);
 *                      // }
 *                  },
 *                  authorized: {
 *                      url: '{{ route('cp.marketplace.cart.confirm', ['cart' => $cart]) }}',
 *                      // onFailed: (response) => {
 *                      //     laravel.ajax.errorHandler(response);
 *                      //     this.onCancel({}, response.data.error.message);
 *                      // },
 *                      // onSuccess: (response) => {
 *                      //     // nothing
 *                      // }
 *                  },
 *                  // onError: function (message) {
 *                  //     laravel.alert(message);
 *                  // }
 *              });
 */
window.SallaApplePay = {
    session: null,
    detail: null,
    address_id: null,
    shipping_methods: [],
    total: undefined,
    request: undefined,
    id: undefined,
    countryCode: null,
    totals: [],
    shippingCompany: null,
    init: function () {
        document.removeEventListener('payments::apple-pay.start-transaction', SallaApplePay.startSession);
        Salla.event.addEventListener('payments::apple-pay.start-transaction', SallaApplePay.startSession);
    },

    initDefault: function () {
        if (!SallaApplePay.detail.onError) {
            SallaApplePay.detail.onError = function (message) {
                salla.notify.error(message);
            };
        }

        if (!SallaApplePay.detail.authorized.onFailed) {
            SallaApplePay.detail.authorized.onFailed = (response) => {
                salla.logger.log(JSON.stringify(response));
                salla.api.handleErrorResponse(response);
                SallaApplePay.onCancel({}, response.data.error.message);
            };
        }

        if (!SallaApplePay.detail.validateMerchant.onFailed) {
            SallaApplePay.detail.validateMerchant.onFailed = (response) => {
                salla.logger.log(JSON.stringify(response));
                salla.api.handleErrorResponse({response});
                SallaApplePay.onCancel({}, response.data.error.message);
            };
        }

        if (!SallaApplePay.detail.authorized.onSuccess) {
            SallaApplePay.detail.authorized.onSuccess = (response) => {
                salla.logger.log(JSON.stringify(response));
                salla.api.handleAfterResponseActions(response);
            };
        }
    },

    prepareLineItems: function () {
        if (!SallaApplePay.detail?.items?.length) {
            SallaApplePay.detail.items = [
                {
                    label: salla.lang.get('pages.cart.items_total'),
                    amount: parseFloat(SallaApplePay.detail.amount).toString()
                }
            ];
        }

        return SallaApplePay.detail.items;
    },

    prepareTotal: function () {
        return {
            // apple ask to use business name
            label: window.location.hostname || 'Salla',
            //label: salla.lang.get('pages.cart.final_total'),
            amount: parseFloat(SallaApplePay.detail.amount).toString()
        }
    },

    isPhysical() {
        return SallaApplePay.detail?.requiredShippingContactFields?.includes('postalAddress');
    },

    startSession: async function (event) {

        SallaApplePay.detail = event.detail || event;

        salla.log('🍏 Pay: payments::apple-pay.start-transaction', SallaApplePay.detail);

        SallaApplePay.initDefault();

        let version = SallaApplePay.getApplePaySessionVersion();
        let supportedNetworks = SallaApplePay.detail.supportedNetworks || ['masterCard', 'visa'];

        if (version === 5) {
            supportedNetworks.push('mada');
        }

        SallaApplePay.request = {
            countryCode: SallaApplePay.detail.countryCode || 'SA',
            supportsCouponCode: true,
            couponCode: '',
            currencyCode: SallaApplePay.detail.currency || 'SAR',
            requiredShippingContactFields: SallaApplePay.detail.requiredShippingContactFields ? SallaApplePay.detail.requiredShippingContactFields : [],
            merchantCapabilities: ['supports3DS'],
            supportedNetworks: supportedNetworks,
            supportedCountries: SallaApplePay.detail.supportedCountries || ['SA'],
            total: SallaApplePay.prepareTotal(),
            shippingContact: SallaApplePay.detail.shippingContact ? SallaApplePay.detail.shippingContact : {},
            shippingMethods: SallaApplePay.detail.shippingMethods && SallaApplePay.detail.shippingMethods.length ? SallaApplePay.mappingShippingMethods(event.detail.shippingMethods) : [],
            lineItems: SallaApplePay.prepareLineItems()
        };

        salla.log('🍏 Pay: init ', SallaApplePay.request);

        // https://developer.apple.com/documentation/apple_pay_on_the_web/applepaypaymentrequest
        SallaApplePay.session = new ApplePaySession(version, SallaApplePay.request);

        SallaApplePay.session.onshippingcontactselected = SallaApplePay.onShippingContactSelected;
        SallaApplePay.session.onshippingmethodselected = SallaApplePay.onShippingMethodSelected;
        SallaApplePay.session.onvalidatemerchant = SallaApplePay.onValidateMerchant;
        SallaApplePay.session.onpaymentauthorized = SallaApplePay.onPaymentAuthorized;
        SallaApplePay.session.oncancel = SallaApplePay.onCancel;
        SallaApplePay.session.oncouponcodechanged = SallaApplePay.onCouponCodeChanged;
        SallaApplePay.session.onpaymentmethodselected = SallaApplePay.onPaymentMethodSelected;

        SallaApplePay.session.begin();
    },
    onPaymentMethodSelected: async (event) => {
        salla.logger.log('🍏 Pay: onPaymentMethodSelected', event);

        // perform recalculate here only if digital product
        // if physical recalculate performed with shipping company
        if (!SallaApplePay.isPhysical()) {
            try {
                await SallaApplePay.recalculateTotal();
    
                const updatedPaymentDetails = {
                    newTotal: SallaApplePay.prepareTotal(),
                    newLineItems: SallaApplePay.prepareLineItems()
                };
    
                salla.logger.log('🍏 Pay: completePaymentMethodSelection', updatedPaymentDetails);

                SallaApplePay.session.completePaymentMethodSelection(updatedPaymentDetails);

            } catch (error) {
                salla.logger.warn('🍏 Pay: Failed recalculate total', error);
    
                SallaApplePay.session.completePaymentMethodSelection({
                    newTotal: SallaApplePay.prepareTotal(),
                    newLineItems: SallaApplePay.prepareLineItems(),
                    status: SallaApplePay.session.STATUS_FAILURE,
                    errors: [new window.ApplePayError("unknown", undefined, error?.response?.data?.error?.message || error?.response?.data?.error?.code || 'Failed to recalculate total')]
                });
            }
            return;
        }

        salla.logger.log('🍏 Pay: completePaymentMethodSelection', {
            newTotal: SallaApplePay.prepareTotal(),
            newLineItems: SallaApplePay.prepareLineItems(),
        });

        SallaApplePay.session.completePaymentMethodSelection({
            newTotal: SallaApplePay.prepareTotal(),
            newLineItems: SallaApplePay.prepareLineItems(),
        });
    },

    onCouponCodeChanged(event) {
        Salla.event.dispatch('payments::apple-pay.coupon.change', event);

        return http.post(SallaApplePay.detail.onCouponCodeChanged.url.replace('{id}', SallaApplePay.id), {
            'coupon': event.couponCode,
            'payment_method': 'apple_pay',
        }, async ({ data }) => {
            if (typeof SallaApplePay.detail.onCouponCodeChanged.onSuccess === 'function') {
                SallaApplePay.detail.onCouponCodeChanged.onSuccess(data);
            }

            salla.log('🍏 Pay: Coupon applied success');

            await SallaApplePay.recalculateTotal();

            SallaApplePay.session.completeCouponCodeChange({
                newTotal: SallaApplePay.prepareTotal(),
                newLineItems: SallaApplePay.prepareLineItems()
            });
        }, async (error) => {
            let response = error?.response;

            Salla.event.dispatch('payments::apple-pay.coupon.failed', response);

            // SallaApplePay.abortSession();
            if (typeof SallaApplePay.detail.onCouponCodeChanged.onFailed === 'function') {
                SallaApplePay.detail.onCouponCodeChanged.onFailed(response);
            }

            await SallaApplePay.recalculateTotal();

            SallaApplePay.session.completeCouponCodeChange({
                newTotal: SallaApplePay.prepareTotal(),
                newLineItems: SallaApplePay.prepareLineItems(),
                errors: [new window.ApplePayError('couponCodeInvalid')]
            });
        });
    },

    onCancel: (event = {}, message = null) => {
        SallaApplePay.detail.onError(message || salla.lang.get('pages.checkout.payment_failed'));
        Salla.event.createAndDispatch('payments::apple-pay.canceled', event);
    },

    /**
     * Confirm payment after authorization.
     *
     * @param event
     */
    onPaymentAuthorized: async (event) => {
        salla.logger.log('🍏 Pay: onPaymentAuthorized', event.payment);

        // update guest details
        try {
            await mutateShippingContact(SallaApplePay, event.payment.shippingContact, true);
        } catch (error) {
            salla.logger.error('🍏 Pay: Failed to update guest contact details', error);
            
            const response = error?.response || error;
            
            // Parse backend errors for shipping contact fields
            const fields = response?.data?.error?.fields || {};
            const errors = [];
            
            // Map backend field errors to Apple Pay contact field errors
            if (fields?.email && fields.email.length > 0) {
                errors.push(new window.ApplePayError('shippingContactInvalid', 'emailAddress', fields.email[0]));
            }

            if (fields?.phone && fields.phone.length > 0) {
                errors.push(new window.ApplePayError('shippingContactInvalid', 'phoneNumber', fields.phone[0]));
            }

            if (fields?.first_name && fields.first_name.length > 0) {
                errors.push(new window.ApplePayError('shippingContactInvalid', 'name', fields.first_name[0]));
            } else if (fields?.last_name && fields.last_name.length > 0) {
                errors.push(new window.ApplePayError('shippingContactInvalid', 'name', fields.last_name[0]));
            }
            
            // If no specific field errors, use general error message
            if (errors.length === 0) {
                const errorMessage = response?.data?.error?.message || response?.data?.error?.code || 'Invalid shipping contact details';
                errors.push(new window.ApplePayError('shippingContactInvalid', 'name', errorMessage));
            }
            
            Salla.event.dispatch('payments::apple-pay.authorized.failed', response);
            
            if (typeof SallaApplePay.detail.authorized.onFailed === 'function') {
                SallaApplePay.detail.authorized.onFailed(response);
            }

            // Complete shipping contact selection with invalid contact status
            SallaApplePay.session.completePayment({
                status: ApplePaySession.STATUS_INVALID_SHIPPING_CONTACT,
                errors: errors
            });

            return;
        }

        Salla.event.dispatch('payments::apple-pay.authorized.init', event);
        http.post(SallaApplePay.detail.authorized.url.replace('{id}', SallaApplePay.id), {
            payment_method: 'apple_pay',
            applepay_token: JSON.stringify(event.payment)
        }, ({ data }) => {
            Salla.event.dispatch('payments::apple-pay.authorized.success', data);

            if (typeof SallaApplePay.detail.authorized.onSuccess === 'function') {
                SallaApplePay.detail.authorized.onSuccess(data);
            }

            SallaApplePay.session.completePayment(ApplePaySession.STATUS_SUCCESS);
        }, (error) => {

            let response = error?.response;

            Salla.event.dispatch('payments::apple-pay.authorized.failed', response);

            if (typeof SallaApplePay.detail.authorized.onFailed === 'function') {
                SallaApplePay.detail.authorized.onFailed(response);
            }

            SallaApplePay.session.completePayment({
                status: ApplePaySession.STATUS_FAILURE,
                errors: [new window.ApplePayError("unknown", undefined, response?.data?.error?.message || response?.data?.error?.code || 'Failed to parse authorized response')]
            });
        });
    },

    /**
     * Validate Submit.
     *
     * @param event
     */
    onValidateMerchant: async (event) => {
        try {
            // Dispatch event to initialize Apple Pay merchant validation
            Salla.event.dispatch('payments::apple-pay.validate-merchant.init', event);

            // Post request to validate merchant
            const { data } = await http.post(SallaApplePay.detail.validateMerchant.url.replace('{id}', SallaApplePay.id), {
                validation_url: event.validationURL
            });

            // Dispatch event on successful merchant validation
            Salla.event.dispatch('payments::apple-pay.validate-merchant.success', data);

            // Define a function to handle the completion of merchant validation
            const completeMerchantValidation = (responseData) => {
                SallaApplePay.session.completeMerchantValidation(responseData);
            };

            // Check if onSuccess function is defined in SallaApplePay.detail.validateMerchant
            if (typeof SallaApplePay.detail.validateMerchant.onSuccess === 'function') {
                // Call onSuccess function and handle response
                const response = await SallaApplePay.detail.validateMerchant.onSuccess(data);
                if (response?.redirect) {
                    // Handle redirect if present
                    window.location = response.redirect;
                    return SallaApplePay.abortValidateMerchant(response);
                }
            }
            completeMerchantValidation(data.data);
        } catch (error) {
            // Handle errors
            console.error(error);
            SallaApplePay.abortValidateMerchant(error?.response);
        }
    },

    abortValidateMerchant: (response = null) => {

        SallaApplePay.abortSession();
        Salla.event.dispatch('payments::apple-pay.validate-merchant.failed', response);

        if (typeof SallaApplePay.detail.validateMerchant.onFailed === 'function') {
            SallaApplePay.detail.validateMerchant.onFailed(response);
        }
    },

    /**
     * Select Shipping Contact
     *
     * @param event
     */
    onShippingContactSelected: async (event) => {
        salla.logger.log('🍏 Pay: onShippingContactSelected', event.shippingContact);

        // create address for shipping calculation
        await mutateShippingContact(SallaApplePay, event.shippingContact);
    },

    /**
     * Select Shipping Method
     *
     * @param event
     *
     */
    onShippingMethodSelected: async (event) => {

        let shipping_ids = event.shippingMethod.identifier.split(',');
        let shippingMethod = {
            ship_id: shipping_ids[0],
            private_ship_id: typeof shipping_ids[1] === 'undefined' ? null : shipping_ids[1],
            type: typeof shipping_ids[2] === 'undefined' ? null : shipping_ids[2],
            route_id: typeof shipping_ids[3] === 'undefined' ? null : shipping_ids[3],
        };

        salla.logger.log('🍏 Pay: onShippingMethodSelected', {
            event,
            previous: SallaApplePay.shippingCompany,
            current: shippingMethod,
        });

        if (SallaApplePay.shouldUpdateShippingCompany(shippingMethod)) {
            try {

                await SallaApplePay.selectApplePayShippingMethod(shippingMethod);
    
                await SallaApplePay.recalculateTotal();
    
            } catch (error) {
                salla.logger.warn('🍏 Pay: Failed set the shipping details to api', error);
    
                // todo :: find a better handling for error without abort session
                SallaApplePay.session.completeShippingMethodSelection({
                    newTotal: SallaApplePay.prepareTotal(),
                    newLineItems: SallaApplePay.prepareLineItems(),
                    status: SallaApplePay.session.STATUS_INVALID_SHIPPING_POSTAL_ADDRESS,
                    errors: [
                      new window.ApplePayError('addressUnserviceable')
                    ]
                });

                return;
            }
        }

        salla.logger.log('🍏 Pay: completeShippingMethodSelection', {
            newTotal: SallaApplePay.prepareTotal(),
            newLineItems: SallaApplePay.prepareLineItems(),
        });

        SallaApplePay.session.completeShippingMethodSelection({
            newTotal: SallaApplePay.prepareTotal(),
            newLineItems: SallaApplePay.prepareLineItems(),
        });
    },


    abortSession: () => {
        if (SallaApplePay.session) {
            SallaApplePay.session.abort();
        }
    },

    shouldUpdateShippingCompany(shippingCompany) {
        return SallaApplePay.shippingCompany?.ship_id != shippingCompany?.ship_id || SallaApplePay.shippingCompany?.private_ship_id != shippingCompany?.private_ship_id
    },

    getApplePaySessionVersion: () => {
        const userAgent = navigator.userAgent || navigator.vendor || window.opera;

        if (userAgent === 'sallapp') {
            return 5;
        }

        // can't handle custom user agent like sallapp
        let detection = DetectOS.init();
        let v = parseFloat(detection.os.version);

        if (detection.os.name === 'Macintosh') {
            if (v < 10.142) {
                return 1;
            }
        } else {
            if (v < 12.11) {
                return 1;
            }
        }

        return 5;
    },

    recalculateTotal: () => {
        salla.logger.log('🍏 Pay: recalculate total');

        return http.get(SallaApplePay.detail.recalculateTotal.url.replace('{id}', SallaApplePay.id), ({ data }) => {
            salla.logger.log('🍏 Pay: recalculate total success', data);
            let cart = data.data.initial_data?.cart || data.data.cart;
            let payments = data.data.initial_data?.payments || data.data.payments;

            salla.logger.log('🍏 Pay: recalculate total success', {
                cart,
                payments
            });

            // todo :: enhance response from backend
            SallaApplePay.detail.amount = payments?.gateways?.applePay?.supportedMultiCurrency ? cart.total_in_customer_currency : cart.total;
            SallaApplePay.detail.items = (cart.totals || cart.items).map((item) => {
                return {
                    label: item.title,
                    amount: (item.amount === 'مجاني' || item.amount === 'Free') ? 0 : item.amount.toString().replace('+', ''),
                };
            });

            // lets remove last element (final total)
            SallaApplePay.detail.items.pop();
            SallaApplePay.totals = SallaApplePay.detail.items;

        }, (error) => {
            salla.logger.warn('🍏 Pay: recalculate total failed', error);

            // general error
            return error?.response?.data?.message;
        });
    },


    selectApplePayShippingMethod: (shippingMethod) => {
        salla.logger.log('🍏 Pay: select shipping method ', shippingMethod);
        SallaApplePay.shippingCompany = shippingMethod;

        const payload = {
            address_id: SallaApplePay.address_id,
            company_id: shippingMethod.ship_id,
            private_company_id: shippingMethod.private_ship_id,
            type: shippingMethod.type || undefined,
            route_id: shippingMethod.route_id || undefined,
            payment_method: 'apple_pay'
        };
        return http.post(SallaApplePay.detail.shippingMethodSelected.url.replace('{id}', SallaApplePay.id), payload, ({ data }) => {
            if (typeof SallaApplePay.detail.shippingMethodSelected.onSuccess === 'function') {
                SallaApplePay.detail.shippingMethodSelected.onSuccess(data);
            }

            // we don't have any data in this request, lets resolve the promise
            return true;
        }, (error) => {
            salla.logger.warn('🍏 Pay: Set shipping method failed', error);

            if (typeof SallaApplePay.detail.shippingMethodSelected.onFailed === 'function') {
                SallaApplePay.detail.shippingMethodSelected.onFailed(error);
            }

            // parse 422 errors
            let response = error?.response?.data?.error;

            // address id is not valid
            if (response?.data?.fields?.address_id) {
                return response?.data?.fields?.address_id[0];
            }

            // general error
            return response?.data?.message;
        });
    },
    mappingShippingMethods: methods => methods.map(method => ({
        'label': method.shipping_title,
        'amount': method.enable_free_shipping ? 0 : method.ship_cost,
        'detail': '',
        'identifier': method.ship_id.toString() + (method.private_ship_id ? ',' + method.private_ship_id.toString() : '') + (method.type ? ',' + method.type : '') + (method.route_id ? ',' + method.route_id : '')
    }))
};

//applePay doesn't allow iframes
// if (window.ApplePaySession && window.self === window.top && ApplePaySession.canMakePayments()) {
if (window.ApplePaySession?.canMakePayments()) {
    SallaApplePay.init();
} else {
    // You can hide the Apple Pay button easy with add data-show-if-apple-pay-supported to element like <div data-show-if-apple-pay-supported>
    document.querySelectorAll('data-show-if-apple-pay-supported').forEach(element => element.style.display = 'none');
}

const sallaQuickBuyCss = ".s-quick-buy-button .s-button-text{display:flex}apple-pay-button{--apple-pay-button-width:100%;--apple-pay-button-height:40px;--apple-pay-button-border-radius:.75rem;--apple-pay-button-box-sizing:content-box}";

const SallaQuickBuy = /*@__PURE__*/ proxyCustomElement(class SallaQuickBuy extends HTMLElement {
    constructor() {
        super();
        this.__registerHost();
        this.validationFailed = createEvent(this, "validationFailed", 7);
        this.requireLogin = createEvent(this, "requireLogin", 7);
        /**
         * Button type.
         *
         * @type {string}
         * @default buy
         **/
        this.type = 'buy';
        /**
         * Product type.
         *
         * @type {string}
         **/
        this.productType = 'product';
        /**
         * Product options, if is empty will get the data from the document.querySelector('salla-product-options[product-id="X"]')
         *
         * @type {object}
         * @default {}
         */
        this.options = {};
        this.quickBuy = salla.lang.get('pages.products.buy_now');
        salla.lang.onLoaded(() => {
            this.quickBuy = salla.lang.get('pages.products.buy_now');
        });
    }
    async quickBuyHandler() {
        // user guest and guest-checkout not enabled
        if (salla.config.isGuest() && !this.isGuestCheckout()) {
            this.requireLogin.emit({ productId: this.productId });
            // todo (low) :: find a way to re-fire the method after success
            let afterLoginEvent = "salla-quick-buy::user.logged-in";
            salla.event.on(afterLoginEvent, () => this.settlePayment());
            salla.api.auth.setAfterLoginEvent(afterLoginEvent);
            return salla.auth.event.dispatch('login::open', { withoutReload: true });
        }
        await this.settlePayment();
    }
    async settlePayment() {
        let optionsElement = document.querySelector(`salla-product-options[product-id="${this.productId}"]`);
        //make sure all the required options are selected
        if (optionsElement && !await optionsElement.reportValidity()) {
            this.validationFailed.emit({ productId: this.productId });
            return salla.error(salla.lang.get('common.messages.required_fields'));
        }
        //use this way to get quantity too
        let data = this.host.getElementSallaData();
        // if the store doesn't have Apple Pay , just create a cart and then redirect to check out page
        if (!this.isApplePayActive) {
            // return salla.product.buyNow(this.productId, data);
            return salla.api.request('checkout/quick-purchase/' + this.productId, data, 'post')
                .then(resp => {
                if (resp.data.redirect) {
                    window.location.href = resp.data.redirect;
                }
                return resp;
            });
        }
        data.is_applepay = true;
        if ('append' in data) {
            data.append('is_applepay', true);
        }
        // noinspection TypeScriptValidateJSTypes
        salla.event.dispatch('payments::apple-pay.start-transaction', {
            amount: this.amount, // 1000
            currency: this.currency || 'SAR', // SAR
            requiredShippingContactFields: this.getRequiredShippingContactFields(),
            shippingMethods: this.isRequireShipping ? [] : undefined,
            supportedNetworks: salla.config.get('store.settings.buy_now.networks'),
            supportedCountries: salla.config.get('store.settings.buy_now.countries'),
            countryCode: salla.config.get('store.store_country') || 'SA',
            validateMerchant: {
                url: this.validateHost ? `${this.validateHost}/checkout/applepay/validate` : salla.url.get('checkout/applepay/validate'),
                onSuccess: (response) => {
                    if (this.applePayOnly && !this.productId) { // the cart is not passes
                        if (!this.cartId) {
                            salla.logger.warn('🍏 Pay: trying to create applePay transaction without cartId/ProductId !');
                            return Promise.resolve(response);
                        }
                        window.SallaApplePay.id = this.cartId;
                        salla.log('🍏 Pay: create checkout success: with id #' + this.cartId);
                        return Promise.resolve(response);
                    }
                    return salla.api.request('checkout/quick-purchase/' + this.productId, typeof data == 'object' ? data : undefined, 'post', {}).then(response => {
                        // if is redirect url returned for any reason, lets redirect the user to check out
                        if (response?.data?.redirect) {
                            salla.log('🍏 Pay: create checkout success: redirect exits, go to checkout page');
                            window.location.href = response.data.redirect.url;
                            return response;
                        }
                        // the cart is not ready to complete apply pay session
                        if (!response?.data?.id) {
                            salla.logger.warn('🍏 Pay: create checkout success: No id, or redirect');
                            return response;
                        }
                        window.SallaApplePay.id = response.data.id;
                        salla.log('🍏 Pay: create checkout success: with id #' + window.SallaApplePay.id);
                    });
                }
            },
            authorized: {
                // submit checkout route
                url: salla.url.get('checkout/{id}/payments/submit'),
                onFailed: (response) => {
                    window.SallaApplePay.onCancel({}, response?.data?.error?.message || response?.data?.error?.code || salla.lang.get('pages.checkout.payment_failed'));
                },
                onSuccess: (response) => {
                    window.location.href = response.redirect.url;
                    salla.log('🍏 Pay: authorized Success:: redirect to thank you page, order placed');
                }
            },
            shippingMethodSelected: this.isRequireShipping ? {
                url: salla.url.get('checkout/{id}/shipping/details'),
            } : undefined,
            shippingContactSelected: this.isRequireShipping ? {
                url: salla.url.get('checkout/{id}/address/add'),
            } : undefined,
            guestContactSelected: this.isGuestCheckout() ? {
                url: salla.url.get('checkout/{id}/customer'),
            } : undefined,
            onCouponCodeChanged: {
                url: salla.url.get('checkout/{id}/coupons')
            },
            recalculateTotal: {
                url: salla.url.get('checkout/{id}/payments/recalculate?payment_method=apple_pay')
            },
            onError: function (message) {
                salla.log(message);
                salla.notify.error(message);
            }
        });
    }
    isGuestCheckout() {
        return salla.config.isGuest() && salla.config.get('store.features').includes('guest-checkout') && this.isPhysicalProduct();
    }
    getRequiredShippingContactFields() {
        let fields = [];
        if (this.isRequireShipping) {
            fields.push('postalAddress');
        }
        if (this.isGuestCheckout()) {
            fields.push('email', 'phone', 'name');
        }
        return fields;
    }
    componentWillLoad() {
        console.log('🍏 Pay: Quick Buy Component Loaded');
        const canMakePayments = typeof window !== 'undefined' && !!window.ApplePaySession?.canMakePayments?.();
        const storeHasApplePay = salla?.config?.get?.('store.settings.payments')?.includes?.('apple_pay') ?? true;
        const isSallaGateway = salla?.config?.get?.('store.settings.is_salla_gateway', false) ?? true;
        this.isApplePayActive = canMakePayments && storeHasApplePay && isSallaGateway;
        const runInit = async () => {
            if (!this.currency && salla?.config?.get) {
                this.currency = salla.config.get('store.settings.buy_now.multi_currency') ? salla.config.get('user.currency_code') : 'SAR';
            }
            if (!this.productId && salla?.config?.get && salla.url?.is_page) {
                this.productId = salla.config.get('page.id');
            }
            if (!this.applePayOnly && !this.productId) {
                salla?.logger?.warn?.('🍏 Pay: Failed load the quick buy, the product id is missing');
                return;
            }
            if ((!this.amount || !this.isRequireShipping) && this.productId && salla?.product?.getDetails) {
                await salla.product.getDetails(this.productId, []).then((response) => {
                    this.amount = response.data.price;
                    this.isRequireShipping = response?.data?.is_require_shipping || false;
                }).catch((error) => {
                    salla?.logger?.warn?.('🍏 Pay: Failed load the quick buy, get the product details failed: ', error);
                });
            }
            if (this.type === 'donate' && salla?.event?.on) {
                salla.event.on('product-options::donation-changed', (data) => {
                    if (String(data.id) !== String(this.productId))
                        return;
                    this.amount = data.price;
                });
            }
            else if (salla?.url?.is_page?.('product.single') && salla?.product?.event?.onPriceUpdated) {
                salla.product.event.onPriceUpdated(response => { this.amount = response.data.price; });
            }
            this.isApplePayActive = (salla?.helpers?.hasApplePay?.() ?? canMakePayments)
                && (salla?.config?.get?.('store.settings.payments')?.includes?.('apple_pay') ?? storeHasApplePay)
                && (salla?.config?.get?.('store.settings.is_salla_gateway', false) ?? isSallaGateway);
            if (!document.getElementById('apple-pay-sdk') && this.isApplePayActive) {
                const script = document.createElement('script');
                script.src = 'https://applepay.cdn-apple.com/jsapi/v1/apple-pay-sdk.js';
                script.setAttribute('id', 'apple-pay-sdk');
                script.async = true;
                document.body.appendChild(script);
            }
        };
        return new Promise((resolve) => {
            if (typeof salla?.onReady === 'function') {
                salla.onReady(() => runInit().then(() => resolve(true)));
            }
            else {
                runInit().then(() => resolve(true));
            }
        });
    }
    render() {
        return h(Host, { key: '6a161249c65a797bc7e9b61549b3b1f6ad1e39fa' }, this.quickBuyButton());
    }
    quickBuyButton() {
        return h("apple-pay-button", { locale: salla?.config?.get?.('user.language_code') || 'ar', onClick: () => this.quickBuyHandler(), "data-quick-purchase": "applepay", class: "s-quick-buy-apple-pay", "data-is-applepay": "1", buttonstyle: "black", type: this.type });
    }
    // function to check if product is physical
    isPhysicalProduct() {
        return this.productType === 'product' || this.productType === 'group_products' || this.productType === 'food';
    }
    get host() { return this; }
    static get style() { return sallaQuickBuyCss; }
}, [0, "salla-quick-buy", {
        "type": [1025],
        "productType": [1025, "product-type"],
        "productId": [1025, "product-id"],
        "cartId": [1025, "cart-id"],
        "amount": [1538],
        "currency": [1025],
        "options": [16],
        "isRequireShipping": [1028, "is-require-shipping"],
        "applePayOnly": [1028, "apple-pay-only"],
        "validateHost": [1025, "validate-host"],
        "isApplePayActive": [32],
        "quickBuy": [32]
    }]);
function defineCustomElement() {
    if (typeof customElements === "undefined") {
        return;
    }
    const components = ["salla-quick-buy"];
    components.forEach(tagName => { switch (tagName) {
        case "salla-quick-buy":
            if (!customElements.get(tagName)) {
                customElements.define(tagName, SallaQuickBuy);
            }
            break;
    } });
}
defineCustomElement();

export { SallaQuickBuy as S, defineCustomElement as d };
