import { proxyCustomElement, HTMLElement, createEvent, h } from '@stencil/core/internal/client';
import { a as state, r as removeQueryArgs } from './watchers.js';
import { c as clearCheckout } from './mutations.js';
import { s as state$1 } from './watchers3.js';
import { _ as __ } from './default-i18n.js';
import './index2.js';
import { u as updateFormState } from './mutations2.js';
import { p as parseFormData } from './form-data.js';
import { a as finalizeCheckout, f as fetchCheckout, c as createOrUpdateCheckout } from './index4.js';
import { d as defineCustomElement$1 } from './sc-line-items-provider2.js';
import { a as addQueryArgs, g as getQueryArgs } from './add-query-args.js';
import { g as getQueryArg } from './get-query-arg.js';

const ScSessionProvider = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement {
  constructor() {
    super();
    this.__registerHost();
    this.__attachShadow();
    this.scUpdateOrderState = createEvent(this, "scUpdateOrderState", 7);
    this.scUpdateDraftState = createEvent(this, "scUpdateDraftState", 7);
    this.scPaid = createEvent(this, "scPaid", 7);
    this.scError = createEvent(this, "scError", 7);
    this.scSetState = createEvent(this, "scSetState", 7);
    /** An array of prices to pre-fill in the form. */
    this.prices = [];
    /** Should we persist the session. */
    this.persist = true;
  }
  handlePricesChange() {
    let line_items = this.addInitialPrices() || [];
    line_items = this.addPriceChoices(line_items);
    if (!(line_items === null || line_items === void 0 ? void 0 : line_items.length)) {
      return;
    }
    return this.loadUpdate({ line_items });
  }
  /**
   * Finalize the order.
   *
   * @returns {Promise<Order>}
   */
  async finalize() {
    return await this.handleFormSubmit();
  }
  async getFormData() {
    let data = {};
    const form = this.el.querySelector('sc-form');
    if (form) {
      const json = await form.getFormJson();
      data = parseFormData(json);
    }
    return data;
  }
  /**
   * Handles the form submission.
   * @param e
   */
  async handleFormSubmit() {
    var _a, _b, _c, _d, _e, _f, _g, _h, _j;
    this.scError.emit({});
    updateFormState('FINALIZE');
    // Get current form state.
    let data = await this.getFormData();
    if (((_a = window === null || window === void 0 ? void 0 : window.scData) === null || _a === void 0 ? void 0 : _a.recaptcha_site_key) && (window === null || window === void 0 ? void 0 : window.grecaptcha)) {
      try {
        data['grecaptcha'] = await window.grecaptcha.execute(window.scData.recaptcha_site_key, { action: 'surecart_checkout_submit' });
      }
      catch (e) {
        console.error(e);
        updateFormState('REJECT');
        this.handleErrorResponse(e);
        return;
      }
    }
    // first lets make sure the session is updated before we process it.
    try {
      await this.update(data);
    }
    catch (e) {
      console.error(e);
      updateFormState('REJECT');
      this.handleErrorResponse(e);
    }
    // first validate server-side and get key
    try {
      state.checkout = await finalizeCheckout({
        id: (_b = state === null || state === void 0 ? void 0 : state.checkout) === null || _b === void 0 ? void 0 : _b.id,
        query: {
          ...((state$1 === null || state$1 === void 0 ? void 0 : state$1.method) ? { payment_method_type: state$1 === null || state$1 === void 0 ? void 0 : state$1.method } : {}),
          return_url: addQueryArgs(window.location.href, {
            ...(((_c = state === null || state === void 0 ? void 0 : state.checkout) === null || _c === void 0 ? void 0 : _c.id) ? { checkout_id: (_d = state === null || state === void 0 ? void 0 : state.checkout) === null || _d === void 0 ? void 0 : _d.id } : {}),
            is_surecart_payment_redirect: true,
          }),
        },
        data,
        processor: {
          id: state$1.id,
          manual: state$1.manual,
        },
      });
      // the checkout is paid.
      if (['paid', 'processing'].includes((_e = state.checkout) === null || _e === void 0 ? void 0 : _e.status)) {
        this.scPaid.emit();
      }
      if ((_j = (_h = (_g = (_f = state.checkout) === null || _f === void 0 ? void 0 : _f.payment_intent) === null || _g === void 0 ? void 0 : _g.processor_data) === null || _h === void 0 ? void 0 : _h.mollie) === null || _j === void 0 ? void 0 : _j.checkout_url) {
        updateFormState('PAYING');
        return setTimeout(() => { var _a, _b, _c, _d; return window.location.assign((_d = (_c = (_b = (_a = state.checkout) === null || _a === void 0 ? void 0 : _a.payment_intent) === null || _b === void 0 ? void 0 : _b.processor_data) === null || _c === void 0 ? void 0 : _c.mollie) === null || _d === void 0 ? void 0 : _d.checkout_url); }, 50);
      }
      setTimeout(() => {
        updateFormState('PAYING');
      }, 50);
      return state.checkout;
    }
    catch (e) {
      console.error(e);
      this.handleErrorResponse(e);
    }
  }
  /**
   * Handle paid event and update the
   */
  async handlePaid() {
    updateFormState('PAID');
  }
  async handlePayError() {
    updateFormState('REJECT');
  }
  async handleAbandonedCartUpdate(e) {
    const abandoned_checkout_enabled = e.detail;
    this.loadUpdate({
      abandoned_checkout_enabled,
    });
  }
  /** Handles coupon updates. */
  async handleCouponApply(e) {
    const promotion_code = e.detail;
    this.scError.emit({});
    this.loadUpdate({
      discount: {
        ...(promotion_code ? { promotion_code } : {}),
      },
    });
  }
  /** Find or create session on load. */
  componentDidLoad() {
    this.findOrCreateOrder();
  }
  /** Find or create an order */
  async findOrCreateOrder() {
    var _a;
    // get URL params.
    const { redirect_status, checkout_id, line_items, coupon, is_surecart_payment_redirect } = getQueryArgs(window.location.href);
    // remove params we don't want.
    window.history.replaceState({}, document.title, removeQueryArgs(window.location.href, 'redirect_status', 'coupon', 'line_items', 'confirm_checkout_id', 'checkout_id'));
    // handle abandoned checkout.
    if (!!is_surecart_payment_redirect && !!checkout_id) {
      updateFormState('FINALIZE');
      updateFormState('PAYING');
      return this.handleCheckoutIdFromUrl(checkout_id, coupon);
    }
    // handle redirect status.
    if (!!redirect_status) {
      return this.handleRedirectStatus(redirect_status, checkout_id);
    }
    // handle abandoned checkout.
    if (!!checkout_id) {
      return this.handleCheckoutIdFromUrl(checkout_id, coupon);
    }
    // handle initial line items.
    if (!!line_items) {
      return this.handleInitialLineItems(line_items, coupon);
    }
    // we have an existing saved checkout id in the session, and we are persisting.
    const id = (_a = state === null || state === void 0 ? void 0 : state.checkout) === null || _a === void 0 ? void 0 : _a.id;
    if (id && this.persist) {
      return this.handleExistingCheckout(id, coupon);
    }
    return this.handleNewCheckout(coupon);
  }
  /** Handle payment instrument redirect status */
  async handleRedirectStatus(status, id) {
    var _a, _b;
    console.info('Handling payment redirect.');
    // status failed.
    if (status === 'failed') {
      return this.scError.emit({
        message: __('Payment unsuccessful. Please try again.', 'surecart'),
      });
    }
    // get the
    if (!id) {
      return this.scError.emit({
        message: __('Could not find checkout. Please contact us before attempting to purchase again.', 'surecart'),
      });
    }
    // success, refetch the checkout
    try {
      updateFormState('FINALIZE');
      updateFormState('PAID');
      state.checkout = (await fetchCheckout({
        id,
        query: {
          refresh_status: true,
        },
      }));
      // TODO: should we even check this?
      if (((_a = state.checkout) === null || _a === void 0 ? void 0 : _a.status) && ['paid', 'processing'].includes((_b = state.checkout) === null || _b === void 0 ? void 0 : _b.status)) {
        setTimeout(() => {
          this.scPaid.emit();
        }, 100);
      }
    }
    catch (e) {
      this.handleErrorResponse(e);
    }
  }
  /** Handle abandoned checkout from URL */
  async handleCheckoutIdFromUrl(id, promotion_code = '') {
    var _a;
    console.info('Handling existing checkout from url.', promotion_code, id);
    // if coupon code, load the checkout with the code.
    if (promotion_code) {
      return this.loadUpdate({
        id,
        discount: { promotion_code },
      });
    }
    try {
      updateFormState('FETCH');
      state.checkout = (await fetchCheckout({
        id,
        query: {
          refresh_status: true,
        },
      }));
      updateFormState('RESOLVE');
    }
    catch (e) {
      this.handleErrorResponse(e);
    }
    // handle status.
    switch ((_a = state.checkout) === null || _a === void 0 ? void 0 : _a.status) {
      case 'paid':
      case 'processing':
        return setTimeout(() => {
          updateFormState('FINALIZE');
          updateFormState('PAID');
          this.scPaid.emit();
        }, 100);
      case 'payment_failed':
        clearCheckout();
        return this.scError.emit({
          message: __('Payment unsuccessful. Please try again.', 'surecart'),
        });
      case 'payment_intent_canceled':
      case 'canceled':
        clearCheckout();
        return this.scError.emit({
          message: __('Payment canceled. Please try again.', 'surecart'),
        });
      case 'finalized':
        this.scError.emit({
          message: __('Payment unsuccessful. Please try again.', 'surecart'),
        });
        updateFormState('REJECT');
    }
  }
  /** Handle line items (and maybe ) */
  async handleInitialLineItems(line_items, promotion_code) {
    console.info('Handling initial line items.');
    // TODO: move this to central store.
    const address = this.el.querySelector('sc-order-shipping-address');
    clearCheckout();
    return this.loadUpdate({
      line_items,
      ...(promotion_code ? { discount: { promotion_code } } : {}),
      ...((address === null || address === void 0 ? void 0 : address.defaultCountry)
        ? {
          shipping_address: {
            country: address === null || address === void 0 ? void 0 : address.defaultCountry,
          },
        }
        : {}),
    });
  }
  /** Handle a brand new checkout. */
  async handleNewCheckout(promotion_code) {
    console.info('Handling new checkout.');
    // get existing form data from defaults (default country selection, etc).
    const data = this.getFormData();
    const line_items = this.addPriceChoices(this.addInitialPrices() || []);
    const address = this.el.querySelector('sc-order-shipping-address');
    try {
      updateFormState('FETCH');
      state.checkout = (await createOrUpdateCheckout({
        data: {
          ...data,
          ...(promotion_code ? { discount: { promotion_code } } : {}),
          ...((address === null || address === void 0 ? void 0 : address.defaultCountry)
            ? {
              shipping_address: {
                country: address === null || address === void 0 ? void 0 : address.defaultCountry,
              },
            }
            : {}),
          line_items,
        },
      }));
      updateFormState('RESOLVE');
    }
    catch (e) {
      console.error(e);
      this.handleErrorResponse(e);
    }
  }
  /** Handle existing checkout */
  async handleExistingCheckout(id, promotion_code) {
    if (!id)
      return this.handleNewCheckout(promotion_code);
    console.info('Handling existing checkout.');
    try {
      updateFormState('FETCH');
      state.checkout = (await createOrUpdateCheckout({
        id,
        data: {
          ...(promotion_code ? { discount: { promotion_code } } : {}),
        },
      }));
      updateFormState('RESOLVE');
    }
    catch (e) {
      console.error(e);
      this.handleErrorResponse(e);
    }
  }
  /** Handle the error response. */
  async handleErrorResponse(e) {
    var _a, _b, _c, _d;
    // reinitalize if order not found.
    if (['checkout.not_found'].includes(e === null || e === void 0 ? void 0 : e.code)) {
      window.history.replaceState({}, document.title, removeQueryArgs(window.location.href, 'checkout_id'));
      clearCheckout();
      return this.handleNewCheckout(false);
    }
    if (((_b = (_a = e === null || e === void 0 ? void 0 : e.additional_errors) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.code) === 'order.line_items.old_price_versions') {
      await this.loadUpdate({
        id: (_c = state === null || state === void 0 ? void 0 : state.checkout) === null || _c === void 0 ? void 0 : _c.id,
        data: {
          status: 'draft',
          refresh_price_versions: true,
        },
      });
      return;
    }
    if (['order.invalid_status_transition'].includes(e === null || e === void 0 ? void 0 : e.code)) {
      await this.loadUpdate({
        id: (_d = state === null || state === void 0 ? void 0 : state.checkout) === null || _d === void 0 ? void 0 : _d.id,
        data: {
          status: 'draft',
        },
      });
      this.handleFormSubmit();
      return;
    }
    // expired
    if ((e === null || e === void 0 ? void 0 : e.code) === 'rest_cookie_invalid_nonce') {
      updateFormState('EXPIRE');
      return;
    }
    // paid
    if ((e === null || e === void 0 ? void 0 : e.code) === 'readonly') {
      clearCheckout();
      window.location.assign(removeQueryArgs(window.location.href, 'order'));
      return;
    }
    console.log('emit', e);
    this.scError.emit(e);
    updateFormState('REJECT');
  }
  /** Looks through children and finds items needed for initial session. */
  async initialize(args = {}) {
    let line_items = this.addInitialPrices() || [];
    line_items = this.addPriceChoices(line_items);
    if (line_items === null || line_items === void 0 ? void 0 : line_items.length) {
      return this.loadUpdate({ line_items, ...args });
    }
    else {
      return this.loadUpdate({ ...args });
    }
  }
  /** Add prices that are passed into the component. */
  addInitialPrices() {
    var _a;
    if (!((_a = this === null || this === void 0 ? void 0 : this.prices) === null || _a === void 0 ? void 0 : _a.length))
      return [];
    // check for id
    if (this.prices.some(p => !(p === null || p === void 0 ? void 0 : p.id))) {
      return;
    }
    // add prices that are passed into this component.
    return this.prices.map(price => {
      return {
        price_id: price.id,
        quantity: price.quantity,
      };
    });
  }
  /** Add default prices that may be selected in form. */
  addPriceChoices(line_items = []) {
    const elements = this.el.querySelectorAll('[price-id]');
    elements.forEach(el => {
      // handle price choices.
      if (el.checked) {
        line_items.push({
          quantity: el.quantity || 1,
          price_id: el.priceId,
          ...(el.defaultAmount ? { ad_hoc_amount: el.defaultAmount } : {}),
        });
      }
      // handle donation default amount.
      if (el.defaultAmount) {
        line_items.push({
          quantity: el.quantity || 1,
          price_id: el.priceId,
          ad_hoc_amount: el.defaultAmount,
        });
      }
    });
    return line_items;
  }
  getSessionId() {
    var _a, _b;
    // check url first.
    const checkoutId = getQueryArg(window.location.href, 'checkout_id');
    if (!!checkoutId) {
      return checkoutId;
    }
    // check existing order.
    if ((_a = state === null || state === void 0 ? void 0 : state.checkout) === null || _a === void 0 ? void 0 : _a.id) {
      return (_b = state === null || state === void 0 ? void 0 : state.checkout) === null || _b === void 0 ? void 0 : _b.id;
    }
    // we don't have and order id.
    return null;
  }
  async fetchCheckout(id, { query = {}, data = {} } = {}) {
    try {
      updateFormState('FETCH');
      const checkout = (await createOrUpdateCheckout({
        id,
        query,
        data,
      }));
      updateFormState('RESOLVE');
      return checkout;
    }
    catch (e) {
      this.handleErrorResponse(e);
    }
  }
  /** Fetch a session. */
  async fetch(query = {}) {
    try {
      updateFormState('FETCH');
      state.checkout = (await fetchCheckout({
        id: this.getSessionId(),
        query,
      }));
      updateFormState('RESOLVE');
    }
    catch (e) {
      this.handleErrorResponse(e);
    }
  }
  /** Update a session */
  async update(data = {}, query = {}) {
    try {
      state.checkout = (await createOrUpdateCheckout({
        id: (data === null || data === void 0 ? void 0 : data.id) ? data.id : this.getSessionId(),
        data,
        query,
      }));
    }
    catch (e) {
      // reinitalize if order not found.
      if (['checkout.not_found'].includes(e === null || e === void 0 ? void 0 : e.code)) {
        clearCheckout();
        return this.initialize();
      }
      console.error(e);
      throw e;
    }
  }
  /** Updates a session with loading status changes. */
  async loadUpdate(data = {}) {
    try {
      updateFormState('FETCH');
      await this.update(data);
      updateFormState('RESOLVE');
    }
    catch (e) {
      this.handleErrorResponse(e);
    }
  }
  render() {
    return (h("sc-line-items-provider", { order: state === null || state === void 0 ? void 0 : state.checkout, onScUpdateLineItems: e => this.loadUpdate({ line_items: e.detail }) }, h("slot", null)));
  }
  get el() { return this; }
  static get watchers() { return {
    "prices": ["handlePricesChange"]
  }; }
}, [1, "sc-session-provider", {
    "prices": [16],
    "persist": [4],
    "finalize": [64]
  }, [[0, "scFormSubmit", "handleFormSubmit"], [0, "scPaid", "handlePaid"], [0, "scPayError", "handlePayError"], [0, "scUpdateAbandonedCart", "handleAbandonedCartUpdate"], [0, "scApplyCoupon", "handleCouponApply"]]]);
function defineCustomElement() {
  if (typeof customElements === "undefined") {
    return;
  }
  const components = ["sc-session-provider", "sc-line-items-provider"];
  components.forEach(tagName => { switch (tagName) {
    case "sc-session-provider":
      if (!customElements.get(tagName)) {
        customElements.define(tagName, ScSessionProvider);
      }
      break;
    case "sc-line-items-provider":
      if (!customElements.get(tagName)) {
        defineCustomElement$1();
      }
      break;
  } });
}
defineCustomElement();

export { ScSessionProvider as S, defineCustomElement as d };
