import { loadScript } from '@paypal/paypal-js';
import { Component, Element, Event, h, Prop, State, Watch } from '@stencil/core';
import { __ } from '@wordpress/i18n';
import apiFetch from '../../../functions/fetch';
import { hasSubscription } from '../../../functions/line-items';
import { fetchCheckout } from '../../../services/session';
import { getScriptLoadParams } from './functions';
export class ScPaypalButtons {
  constructor() {
    /** Is this busy? */
    this.busy = false;
    /** Buttons to render */
    this.buttons = ['paypal', 'card'];
    /** Label for the button. */
    this.label = 'paypal';
    /** Button color. */
    this.color = 'gold';
  }
  handleOrderChange(val, prev) {
    if ((val === null || val === void 0 ? void 0 : val.updated_at) === (prev === null || prev === void 0 ? void 0 : prev.updated_at)) {
      return;
    }
    this.cardContainer.innerHTML = '';
    this.paypalContainer.innerHTML = '';
    this.loadScript();
  }
  /** Load the script */
  async loadScript() {
    var _a, _b;
    if (!this.clientId || !this.merchantId)
      return;
    try {
      const paypal = await loadScript(getScriptLoadParams({
        clientId: this.clientId,
        merchantId: this.merchantId,
        merchantInitiated: this.merchantInitiated,
        reusable: (_a = this.order) === null || _a === void 0 ? void 0 : _a.reusable_payment_method_required,
        currency: (_b = this.order) === null || _b === void 0 ? void 0 : _b.currency,
      }));
      this.renderButtons(paypal);
    }
    catch (err) {
      console.error('failed to load the PayPal JS SDK script', err);
    }
  }
  /** Load the script on component load. */
  componentDidLoad() {
    this.loadScript();
  }
  /** Render the buttons. */
  renderButtons(paypal) {
    const createFunc = hasSubscription(this.order) ? 'createBillingAgreement' : 'createOrder';
    const config = {
      /**
       * Validate the form, client-side when the button is clicked.
       */
      onClick: async (_, actions) => {
        const form = this.el.closest('sc-checkout');
        const isValid = await form.validate();
        return isValid ? actions.resolve() : actions.reject();
      },
      onInit: () => {
        this.loaded = true;
      },
      onCancel: () => {
        this.scSetState.emit('REJECT');
      },
      /**
       * The transaction has been approved.
       * We can capture it.
       */
      onApprove: async () => {
        var _a, _b, _c, _d;
        try {
          this.order = (await fetchCheckout({ id: (_a = this.order) === null || _a === void 0 ? void 0 : _a.id }));
        }
        catch (e) {
          console.error(e);
          this.scError.emit({ code: 'could_not_capture', message: __('The payment did not process. Please try again.', 'surecart') });
          this.scSetState.emit('REJECT');
        }
        try {
          this.scSetState.emit('PAYING');
          const intent = (await apiFetch({
            method: 'PATCH',
            path: `surecart/v1/payment_intents/${((_c = (_b = this.order) === null || _b === void 0 ? void 0 : _b.payment_intent) === null || _c === void 0 ? void 0 : _c.id) || ((_d = this.order) === null || _d === void 0 ? void 0 : _d.payment_intent)}/capture`,
          }));
          if (['succeeded', 'pending', 'requires_approval'].includes(intent === null || intent === void 0 ? void 0 : intent.status)) {
            this.scSetState.emit('PAID');
            this.scPaid.emit();
          }
          else {
            this.scError.emit({ code: 'could_not_capture', message: __('The payment did not process. Please try again.', 'surecart') });
            this.scSetState.emit('REJECT');
          }
        }
        catch (err) {
          console.error(err);
          this.scError.emit({ code: 'could_not_capture', message: __('The payment did not process. Please try again.', 'surecart') });
          this.scSetState.emit('REJECT');
        }
      },
      /**
       * Transaction errored.
       * @param err
       */
      onError: err => {
        console.error(err);
        this.scError.emit({ code: err === null || err === void 0 ? void 0 : err.code, message: err === null || err === void 0 ? void 0 : err.message });
        this.scSetState.emit('REJECT');
      },
    };
    config[createFunc] = async () => {
      return new Promise(async (resolve, reject) => {
        var _a, _b;
        // get the checkout component.
        const checkout = this.el.closest('sc-checkout');
        // submit and get the finalized order
        const order = (await checkout.submit());
        // an error occurred. reject with the error.
        if (order instanceof Error) {
          return reject(order);
        }
        // assume there was a validation issue here.
        // that is handled by our fetch function.
        if ((order === null || order === void 0 ? void 0 : order.status) !== 'finalized') {
          return reject(new Error('Something went wrong. Please try again.'));
        }
        // resolve the payment intent id.
        if ((_a = order === null || order === void 0 ? void 0 : order.payment_intent) === null || _a === void 0 ? void 0 : _a.external_intent_id) {
          return resolve((_b = order === null || order === void 0 ? void 0 : order.payment_intent) === null || _b === void 0 ? void 0 : _b.external_intent_id);
        }
        // we don't have the correct payment intent for some reason.
        this.scError.emit({ code: 'missing_payment_intent', message: __('Something went wrong. Please contact us for payment.', 'surecart') });
        return reject();
      });
    };
    if (paypal.FUNDING.PAYPAL) {
      const paypalButton = paypal.Buttons({
        fundingSource: paypal.FUNDING.PAYPAL,
        style: {
          label: this.label,
          color: this.color,
        },
        ...config,
      });
      if (paypalButton.isEligible()) {
        paypalButton.render(this.paypalContainer);
      }
    }
    if (paypal.FUNDING.CARD) {
      const cardButton = paypal.Buttons({
        fundingSource: paypal.FUNDING.CARD,
        style: {
          color: 'black',
        },
        ...config,
      });
      if (cardButton.isEligible()) {
        cardButton.render(this.cardContainer);
      }
    }
  }
  render() {
    return (h("div", { part: `base ${this.busy || (!this.loaded && 'base--busy')}`, class: { 'paypal-buttons': true, 'paypal-buttons--busy': this.busy || !this.loaded } },
      (!this.loaded || this.busy) && h("sc-skeleton", { style: { 'height': '55px', '--border-radius': '4px', 'cursor': 'wait' } }),
      h("div", { class: "sc-paypal-button-container", hidden: !this.loaded || this.busy },
        h("div", { part: "paypal-card-button", hidden: !this.buttons.includes('card'), class: "sc-paypal-card-button", ref: el => (this.cardContainer = el) }),
        h("div", { part: "paypal-button", hidden: !this.buttons.includes('paypal'), class: "sc-paypal-button", ref: el => (this.paypalContainer = el) }))));
  }
  static get is() { return "sc-paypal-buttons"; }
  static get encapsulation() { return "shadow"; }
  static get originalStyleUrls() { return {
    "$": ["paypal-buttons.scss"]
  }; }
  static get styleUrls() { return {
    "$": ["paypal-buttons.css"]
  }; }
  static get properties() { return {
    "clientId": {
      "type": "string",
      "mutable": false,
      "complexType": {
        "original": "string",
        "resolved": "string",
        "references": {}
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": "Client id for the script."
      },
      "attribute": "client-id",
      "reflect": false
    },
    "busy": {
      "type": "boolean",
      "mutable": false,
      "complexType": {
        "original": "boolean",
        "resolved": "boolean",
        "references": {}
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": "Is this busy?"
      },
      "attribute": "busy",
      "reflect": false,
      "defaultValue": "false"
    },
    "merchantId": {
      "type": "string",
      "mutable": false,
      "complexType": {
        "original": "string",
        "resolved": "string",
        "references": {}
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": "The merchant id for paypal."
      },
      "attribute": "merchant-id",
      "reflect": false
    },
    "merchantInitiated": {
      "type": "boolean",
      "mutable": false,
      "complexType": {
        "original": "boolean",
        "resolved": "boolean",
        "references": {}
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": "Merchant initiated billing enabled."
      },
      "attribute": "merchant-initiated",
      "reflect": false
    },
    "mode": {
      "type": "string",
      "mutable": false,
      "complexType": {
        "original": "'test' | 'live'",
        "resolved": "\"live\" | \"test\"",
        "references": {}
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": "Test or live mode."
      },
      "attribute": "mode",
      "reflect": false
    },
    "order": {
      "type": "unknown",
      "mutable": true,
      "complexType": {
        "original": "Checkout",
        "resolved": "Checkout",
        "references": {
          "Checkout": {
            "location": "import",
            "path": "../../../types"
          }
        }
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": "The order."
      }
    },
    "buttons": {
      "type": "unknown",
      "mutable": false,
      "complexType": {
        "original": "string[]",
        "resolved": "string[]",
        "references": {}
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": "Buttons to render"
      },
      "defaultValue": "['paypal', 'card']"
    },
    "label": {
      "type": "string",
      "mutable": false,
      "complexType": {
        "original": "'paypal' | 'checkout' | 'buynow' | 'pay' | 'installment'",
        "resolved": "\"buynow\" | \"checkout\" | \"installment\" | \"pay\" | \"paypal\"",
        "references": {}
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": "Label for the button."
      },
      "attribute": "label",
      "reflect": false,
      "defaultValue": "'paypal'"
    },
    "color": {
      "type": "string",
      "mutable": false,
      "complexType": {
        "original": "'gold' | 'blue' | 'silver' | 'black' | 'white'",
        "resolved": "\"black\" | \"blue\" | \"gold\" | \"silver\" | \"white\"",
        "references": {}
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": "Button color."
      },
      "attribute": "color",
      "reflect": false,
      "defaultValue": "'gold'"
    }
  }; }
  static get states() { return {
    "loaded": {}
  }; }
  static get events() { return [{
      "method": "scError",
      "name": "scError",
      "bubbles": true,
      "cancelable": true,
      "composed": true,
      "docs": {
        "tags": [],
        "text": "Emit an error"
      },
      "complexType": {
        "original": "object",
        "resolved": "object",
        "references": {}
      }
    }, {
      "method": "scSetState",
      "name": "scSetState",
      "bubbles": true,
      "cancelable": true,
      "composed": true,
      "docs": {
        "tags": [],
        "text": "Set the state machine"
      },
      "complexType": {
        "original": "string",
        "resolved": "string",
        "references": {}
      }
    }, {
      "method": "scPaid",
      "name": "scPaid",
      "bubbles": true,
      "cancelable": true,
      "composed": true,
      "docs": {
        "tags": [],
        "text": ""
      },
      "complexType": {
        "original": "void",
        "resolved": "void",
        "references": {}
      }
    }]; }
  static get elementRef() { return "el"; }
  static get watchers() { return [{
      "propName": "order",
      "methodName": "handleOrderChange"
    }]; }
}
