/* * * * * * * * * * * *
 * Paypal integration  *
 * * * * * * * * * * * */

var donationAmount = 0;
var csrfToken = null;
var baseUrl = null;
var displayPaymentError = null;
var handleFormErrors = null

function paypalInit(donation, token, serverBase, errorPay, errorForm) {
  donationAmount = donation;
  csrfToken = token;
  baseUrl = serverBase;
  displayPaymentError = errorPay;
  handleFormErrors = errorForm;
}

function paypalDonationSet(d) {
  donationAmount = Number(d / 100).toFixed(2);
}

function paypalDonationGet() {
  return donationAmount;
}

function setupPaypalOneTimeButtons() {
  if (typeof paypal_one_time == "undefined") return;
  paypal_one_time
    .Buttons({
      // Order is created on the server and the order id is returned
      async createOrder() {

        // First, enforce front-end validation
        const userDataForm = document.getElementById("donateForm");
        const formData = $(userDataForm).serializeArray();
        const formParam = $.param(formData);

        try {
          if (
            !userDataForm.checkValidity() ||
            $(userDataForm).data("shippingRestricted")
          ) {
            if($(userDataForm).data("shippingRestricted")) {
              displayPaymentError("Due to shipping restrictions, we currently can not ship to Ukraine, or Russia. We apologize for the inconvenience.");
            }
            throw new Error("Form did not pass front-end validation.");
          }
        } catch (error) {
          return;
        } finally {
          $(userDataForm).addClass("was-validated");
          $.fn.matchHeight._update();
        }

        const formValidate = await fetch("/validate/", {
          method: "POST",
          credentials: "include",
          headers: {
            "Content-Type": "application/json",
            "X-CSRFToken": csrfToken,
          },
          body: JSON.stringify({
            form: formParam,
          }),
        });

        const validateData = await formValidate.json();

        if(validateData.errors) {
          handleFormErrors(validateData.errors);
          return false;
        }

        let processObject = {};

        formData.forEach(function (el) {
          processObject[el.name] = el.value;
        });
        processObject.email = processObject.email_address;

        try {
          const response = await fetch("/paypal/create-order/", {
            method: "POST",
            credentials: "include",
            headers: {
              "Content-Type": "application/json",
              "X-CSRFToken": csrfToken,
            },

            body: JSON.stringify({
              payment_amount: paypalDonationGet(),
              form: JSON.stringify(processObject),
            }),
          });

          const orderData = await response.json();

          if (orderData.id) {
            return orderData.id;
          } else if (orderData.error) {
            displayPaymentError(`Error during order creation: ${orderData.error}`);
            return false;
          }
        } catch (error) {
          console.log("error in setupPaypalButtons createOrder:", error);
          displayPaymentError(`Could not initiate PayPal checkout: ${error}`);
        }
      },
      async onApprove(data, actions) {
        try {
          const response = await fetch(`/paypal/capture-order-payment/`, {
            method: "POST",
            credentials: "include",
            headers: {
              "Content-Type": "application/json",
              "X-CSRFToken": csrfToken,
            },

            body: JSON.stringify({
              order_id: data.orderID,
            }),
          });

          const orderData = await response.json();
          console.log("orderData after backend capture", orderData);

          // Three cases to handle:
          //   (1) Recoverable INSTRUMENT_DECLINED -> call actions.restart()
          //   (2) Other non-recoverable errors -> Show a failure message
          //   (3) Successful transaction -> Show confirmation or thank you message

          const errorDetail = orderData?.details?.[0];

          if (errorDetail?.issue === "INSTRUMENT_DECLINED") {
            return actions.restart();
          } else if (errorDetail) {
              displayPaymentError(`${errorDetail.description} (${orderData.debug_id})`);
              return false;
          } else if (orderData.error) {
            displayPaymentError(`Error capturing payment: ${orderData.error}`);
            return false;
          } else {
            actions.redirect(
              `${baseUrl}/donate-thank-you/?paypal_status=${orderData.status}`
            );
          }
        } catch (error) {
          console.error(error);
          displayPaymentError(
            `Sorry, your transaction could not be processed: ${error}`
          );
        }
      },
    })
    .render("#paypal-button-container-single");
}

function setupPaypalSubscriptionButtons() {
  if (typeof paypal_subscriptions == "undefined") return;
  paypal_subscriptions
    .Buttons({
      createSubscription: async function (data, actions) {

        // First, enforce front-end validation
        const userDataForm = document.getElementById("donateForm");
        const formData = $(userDataForm).serializeArray();
        const formParam = $.param(formData);

        try {
          if (
            !userDataForm.checkValidity() ||
            $(userDataForm).data("shippingRestricted")
          ) {
            if($(userDataForm).data("shippingRestricted")) {
              displayPaymentError("Due to shipping restrictions, we currently can not ship to Ukraine, or Russia. We apologize for the inconvenience.");
            }
            throw new Error("Form did not pass front-end validation.");
          }
        } catch (error) {
          return;
        } finally {
          $(userDataForm).addClass("was-validated");
          $.fn.matchHeight._update();
        }

        const formValidate = await fetch("/validate/", {
          method: "POST",
          credentials: "include",
          headers: {
            "Content-Type": "application/json",
            "X-CSRFToken": csrfToken,
          },
          body: JSON.stringify({
            form: formParam,
          }),
        });

        const validateData = await formValidate.json();

        if(validateData.errors) {
          handleFormErrors(validateData.errors);
          return false;
        }

        try {
          const response = await fetch("/paypal/create-subscription/", {
            method: "POST",
            credentials: "include",
            headers: {
              "Content-Type": "application/json",
              "X-CSRFToken": csrfToken,
            },

            body: JSON.stringify({
              payment_amount: paypalDonationGet(),
            }),
          });

          const subscriptionData = await response.json();

          if (subscriptionData.id) {
            return actions.subscription.create({
              plan_id: subscriptionData.id,
            });
          } else if (subscriptionData.error) {
            displayPaymentError(`Error during order creation: ${subscriptionData.error}`);
            return false;
          }
        } catch (error) {
          console.error(error);
          displayPaymentError(
            `Sorry, your transaction could not be processed...<br><br>${error}`
          );
        }
      },
      async onApprove(approvalData, actions) {
        const formData = $("#donateForm").serializeArray();
        let processObject = {};

        formData.forEach(function (el) {
          processObject[el.name] = el.value;
        });
        processObject.email = processObject.email_address;

        const response = await fetch("/paypal/capture-subscription/", {
          method: "POST",
          credentials: "include",
          headers: {
            "Content-Type": "application/json",
            "X-CSRFToken": csrfToken,
          },
          body: JSON.stringify({
            sid: approvalData["subscriptionID"],
            form: JSON.stringify(processObject),
          }),
        });

        const subscriptionCapture = await response.json();

        actions.redirect(
          `${baseUrl}/donate-thank-you/?paypal_status=COMPLETED`
        );
      },
    })
    .render("#paypal-button-container-monthly");
}

async function paypalResults() {
  const params = new Proxy(new URLSearchParams(window.location.search), {
    get: (searchParams, prop) => searchParams.get(prop),
  });

  let paypal_status = params.paypal_status || "";

  if (!paypal_status) return;

  $("body").addClass(paypal_status || "requires_payment_method");
}

export {
  paypalInit,
  paypalDonationSet,
  setupPaypalOneTimeButtons,
  setupPaypalSubscriptionButtons,
  paypalResults,
};
