<template>
  <section class="section">
    <h2 class="section__title">Choose your payment method</h2>

    <div class="payment__form">
      <div class="radio-option" @click="activateCreditOption" v-if="stripePlanId">
        <label for="option1" :class="['radio-option__wrapper', {'selected': chooseCredit}]">
          <input type="radio" id="option1" name="payment-option" value="option1" class="radio-option__input" checked>
          <span class="radio-option__marker"></span>
          <span class="radio-option__label">
            Credit or Debit Card
          </span>
        </label>

        <div :class="['radio-option__content', {'active': chooseCredit}]">
          <div v-if="stripePlanId">
            <form class="float-form" ref="form">
              <floating-label :inputId="'address[line1]'" :inputLabel="'Street address*'" v-model="address.line1" />
              <floating-label :required="false" :inputId="'address[line2]'" :inputLabel="'Apt., ste., bldg'" v-model="address.line2" />
              <floating-label :inputId="'address[city]'" :inputLabel="'City*'" v-model="address.city" />
              <floating-label :required="false" :inputId="'address[state]'" :inputLabel="'State/Region/Province*'" v-model="address.state" />
              <floating-label :inputId="'address[postal_code]'" :inputLabel="'Zip code*'" v-model="address.postal_code" />

              <div class="float-label float-label--selectbox filled">
                <select id="address6" class="float-label__select" name="address[country]" v-model="address.country" required>
                  <option v-for="country in countries" :key="country.iso" :value="country.iso">
                    {{ country.name }}
                  </option>
                </select>
                <label for="address6" class="float-label__text">Country</label>
              </div>
            </form>
            <div id="card-element" class="MyCardElement">
              <!-- Elements will create input elements here -->
            </div>
            <div id="card-element-errors" role="alert"></div>
            <button :disabled="loadingForm" type="button" class="button button--cta" @click="handleStripeSubmit">
              <dots-loader v-if="loadingForm"/>
              <span v-else>Confirm and Subscribe</span>
            </button>
          </div>
        </div>
      </div>


      <div class="radio-option" @click="activatePaypalOption">
        <label for="option2" :class="['radio-option__wrapper', {'selected': choosePaypal}]">
          <input type="radio" id="option2" name="payment-option" value="option2" class="radio-option__input">
          <span class="radio-option__marker"></span>
          <span class="radio-option__label">
            Paypal
          </span>
        </label>
      
        <div :class="['radio-option__content', {'active': choosePaypal}]">
          <div style="margin-bottom: 12px;">
            <span>Click the button below to proceed with PayPal</span>
          </div>
          <div id="paypal-button-container"></div>
        </div>
        <div id="paypal-button-container"></div>
      </div>
    </div>
  </section>
</template>

<script>
import FloatingLabel from '../shared/FloatingLabel'
import countries from '../utils/countries'
import DotsLoader from '../shared/DotsLoader'

function facebookTracking(subscription) {
  !function(f,b,e,v,n,t,s){if(f.fbq)return;n=f.fbq=function(){n.callMethod?
  n.callMethod.apply(n,arguments):n.queue.push(arguments)};if(!f._fbq)f._fbq=n;
  n.push=n;n.loaded=!0;n.version='2.0';n.queue=[];t=b.createElement(e);t.async=!0;
  t.src=v;s=b.getElementsByTagName(e)[0];s.parentNode.insertBefore(t,s)}(window,
  document,'script','//connect.facebook.net/en_US/fbevents.js');

  let fbPixelOptions = {
    em: subscription.email,
    fn: subscription.first_name,
    ln: subscription.last_name
  }

  let fbPixelId = 236053640510469;
  window.fbq('init', fbPixelId, fbPixelOptions);
}

export default {
  components: {
    FloatingLabel,
    DotsLoader
  },
  props: {
    paypalPlanId: String,
    programData: {},
    subscription: {},
    stripePlanId: {
      type: String,
      default: null
    },
    stripeInfo: {}
  },
  data() {
    return {
      success: false,
      chooseCredit: false,
      choosePaypal: true,
      address: {
        country: 'US'
      },
      loadingForm: false
    }
  },
  computed: {
    stripeId() {
      return this.stripeInfo?.id
    },
    countries() {
      return countries
    },
  },
  methods: {
    validateInputs () {
      const isValidatable = (input) => typeof input.validate === 'function'
      const inputValidations = this.$children
        .filter(isValidatable)
        .map((input) => input.validate())
      return !inputValidations.some((validation) => validation.hasErrors)
    },
    mountBtn() {
      window.paypal.Buttons({
        createSubscription: this.createSubscription,
        onApprove: this.approveSubscription
      }).render('#paypal-button-container');
    },

    facebookPixelPurchase() {
        window.fbq.push([
        'track',
        'Purchase',
        {
          content_type: 'subscription',
          value: this.programData.price,
          currency: this.programData.currency,
        }
      ]);
      window.fbq.push([
        'track',
        'Subscribe',
        {
          value: this.programData.price,
          currency: this.programData.currency,
        }
      ]);
    },

    logRollBar(remoteId) {
      this.$rollbar.info('Approved subscription', { ...this.subscription, remoteId });
    },

    createSubscription(_, actions) {
      return actions.subscription.create({ plan_id: this.paypalPlanId });
    },

    approveSubscription(paypalData) {
      this.facebookPixelPurchase()
      this.logRollBar(paypalData.subscriptionID)
      this.$axios.post(
        `${process.env.VUE_APP_GOSUBS_HOST}/api/subscription/`,
        { subscription: this.subscription, paypal_data: paypalData }
      ).then(({ data: { payment, subscription, material, program } }) => {
        this.$store.dispatch('setSubscriptionInfo', { payment, subscription, material, program })
        //this.success = true
        // alert('Your subscription was successfully recieved!')
        this.$router.push('/confirmation')
      })
    },
    clearCache() {
      localStorage.clear();
    },
    onSubscriptionComplete(data) {
      console.log(data)
      const {
        payment,
        gosubs_subscription: subscription,
        material,
        program
      } = data.subscription.gosubs
      this.facebookPixelPurchase()
      // Payment was successful. Provision access to your service.
      // Remove invoice from localstorage because payment is now complete.
      this.clearCache();
      this.$store.dispatch('setSubscriptionInfo', { payment, subscription, material, program })
      //this.success = true
      // alert('Your subscription was successfully recieved!')
      this.$router.push('/confirmation')
      this.loadingForm = false
      // Change your UI to show a success message to your customer.
      // onSubscriptionSampleDemoComplete(result);
      // Call your backend to grant access to your service based on
      // the product your customer subscribed to.
      // Get the product by using result.subscription.price.product
    },
    handleRequiresPaymentMethod({
      subscription,
      paymentMethodId,
      priceId,
    }) {
      if (subscription.status === 'active') {
        // subscription is active, no customer actions required.
        return { subscription, priceId, paymentMethodId };
      } else if (
        subscription.latest_invoice.payment_intent.status ===
        'requires_payment_method' ||
        subscription.latest_invoice.payment_intent.status ===
        'requires_source'
      ) {
        // Using localStorage to store the state of the retry here
        // (feel free to replace with what you prefer)
        // Store the latest invoice ID and status
        localStorage.setItem('latestInvoiceId', subscription.latest_invoice.id);
        localStorage.setItem(
          'latestInvoicePaymentIntentStatus',
          subscription.latest_invoice.payment_intent.status
        );
        throw { error: { message: 'Your card was declined.' } };
      } else {
        return { subscription, priceId, paymentMethodId };
      }
    },
     handlePaymentThatRequiresCustomerAction({
      subscription,
      invoice,
      priceId,
      paymentMethodId,
      isRetry,
    }) {
      if (subscription && subscription.status === 'active') {
        // subscription is active, no customer actions required.
        return { subscription, priceId, paymentMethodId };
      }

      // If it's a first payment attempt, the payment intent is on the subscription latest invoice.
      // If it's a retry, the payment intent will be on the invoice itself.
      let paymentIntent = invoice
        ? invoice.payment_intent
        : subscription.latest_invoice.payment_intent;

      if (
        paymentIntent.status === 'requires_action' ||
        paymentIntent.status === 'requires_source_action' ||
        (isRetry === true && paymentIntent.status === 'requires_source') ||
        (isRetry === true && paymentIntent.status === 'requires_payment_method')
      ) {
        return this.stripe
          .confirmCardPayment(paymentIntent.client_secret, {
            payment_method: paymentMethodId,
          })
          .then((result) => {
            if (result.error) {
              // start code flow to handle updating the payment details
              // Display error message in your UI.
              // The card was declined (i.e. insufficient funds, card has expired, etc)
              throw result;
            } else {
              if (result.paymentIntent.status === 'succeeded') {
                // There's a risk of the customer closing the window before callback
                // execution. To handle this case, set up a webhook endpoint and
                // listen to invoice.paid. This webhook endpoint returns an Invoice.
                return {
                  priceId: priceId,
                  subscription: subscription,
                  invoice: invoice,
                  paymentMethodId: paymentMethodId,
                };
              }
            }
          });
      } else {
        // No customer action needed
        return { subscription, priceId, paymentMethodId };
      }
    },
    createStripeSubscription({ customerId, paymentMethodId, priceId }) {
      return (
        this.$axios.post(
          `${process.env.VUE_APP_GOSUBS_HOST}/api/create-subscription`, {
            customerId: customerId,
            paymentMethodId: paymentMethodId,
            priceId: priceId,
            address: this.address,
            subscription: this.subscription
        })
        .then(({ data }) => {
          if (data.error) {
            // The card had an error when trying to attach it to a customer
            throw data
          }
          return data
        })
        .then((data) => {
          return {
            // Use the Stripe 'object' property on the
            // returned result to understand what object is returned.
            subscription: data,
            paymentMethodId: paymentMethodId,
            priceId: priceId,
          };
        })
        .then(this.handlePaymentThatRequiresCustomerAction)
        // If attaching this card to a Customer object succeeds,
        // but attempts to charge the customer fail. You will
        // get a requires_payment_method error.
        .then(this.handleRequiresPaymentMethod)
        // No more actions required. Provision your service for the user.
        .then(this.onSubscriptionComplete)
        .catch((error) => {
          // An error has happened. Display the failure to the user here.
          // We utilize the HTML element we created.
          this.displayError(error);
        })
      )
    },
    retryInvoiceWithNewPaymentMethod({
      customerId,
      paymentMethodId,
      invoiceId,
      priceId
    }) {
      return (
        this.$axios.post(
          `${process.env.VUE_APP_GOSUBS_HOST}/api/retry-invoice`, {
            customerId: customerId,
            paymentMethodId: paymentMethodId,
            invoiceId: invoiceId,
            address: this.address,
            subscription: this.subscription
          })
          // If the card is declined, display an error to the user.
          .then(({ data }) => {
            if (data.error) {
              // The card had an error when trying to attach it to a customer.
              throw data;
            }
            return data;
          })
          // Normalize the result to contain the object returned by Stripe.
          // Add the additional details we need.
          .then((data) => {
            return {
              // Use the Stripe 'object' property on the
              // returned result to understand what object is returned.
              invoice: data,
              paymentMethodId: paymentMethodId,
              priceId: priceId,
              isRetry: true,
            };
          })
          // Some payment methods require a customer to be on session
          // to complete the payment process. Check the status of the
          // payment intent to handle these actions.
          .then(this.handlePaymentThatRequiresCustomerAction)
          // No more actions required. Provision your service for the user.
          .then(this.onSubscriptionComplete)
          .catch((error) => {
            // An error has happened. Display the failure to the user here.
            // We utilize the HTML element we created.
            this.displayError(error);
          })
      );
    },
    createPaymentMethod({ card, isPaymentRetry, invoiceId }) {
      const customerId = this.stripeId
      const billingName = this.subscription.first_name
      this.stripe.createPaymentMethod({
        type: 'card',
        card: card,
        billing_details: {
          name: billingName,
        }
      })
      .then((result) => {
        if (result.error) {
        this.displayError(result);
      } else {
        if (isPaymentRetry) {
          // Update the payment method and retry invoice payment
          this.retryInvoiceWithNewPaymentMethod({
            customerId: customerId,
            paymentMethodId: result.paymentMethod.id,
            invoiceId: invoiceId,
            priceId: this.stripePlanId,
          });
        } else {
          // Create the subscription
          this.createStripeSubscription({
            customerId: customerId,
            paymentMethodId: result.paymentMethod.id,
            priceId: this.stripePlanId,
          });
        }
      }
      })
    },
    handleStripeSubmit() {
      try {
        if (!this.validateInputs()){
          this.loadingForm = false
          return
        }
        this.loadingForm = true
        const latestInvoicePaymentIntentStatus = localStorage.getItem(
          'latestInvoicePaymentIntentStatus'
        )
        if (
          latestInvoicePaymentIntentStatus === 'requires_payment_method' ||
          latestInvoicePaymentIntentStatus === 'requires_source'
          ) {
          const invoiceId = localStorage.getItem('latestInvoiceId');
          this.createPaymentMethod({
            card: this.card,
            isPaymentRetry: true,
            invoiceId,
          });
        } else {
          this.createPaymentMethod({ card: this.cardElement })
        }
      } catch {
        this.$displayTopMessage('Something went wrong, please try again in a few moments', 'error')
      }
    },
    displayError(event) {
      // changeLoadingStatePrices(false);
      const displayError = document.getElementById('card-element-errors');
      if (event.error) {
        displayError.textContent = event.error.message;
      } else {
        displayError.textContent = '';
      }
      this.loadingForm = false
    },
    loadStripeElements() {
      this.elements = this.stripe.elements();
      this.cardElement = this.elements.create('card', {
        hidePostalCode: true,
        iconStyle: 'solid',
        style: {
          base: {
            iconColor: '#d2d2d6',
            lineHeight: '56px',
            backgroundColor: '#f2f2f6',
            color: '#555',
            fontSize: '14px',
            fontSmoothing: 'antialiased',
            '::placeholder': {
              color: '#555',
            }
          },
          invalid: {
            color: '#EC3F69',
            iconColor: '#EC3F69',
          }
        }
      })
      this.cardElement.mount('#card-element')
      this.cardElement.on('blur', function () {
      const el = document.getElementById('card-element-errors');
        el.classList.remove('focused');
      });
      this.cardElement.on('change', (event) => {
        this.displayError(event);
      });

    },
    loadStripe() {
      this.stripe = window.Stripe(process.env.VUE_APP_STRIPE_KEY)
      this.loadStripeElements()
    },
    mountStripe() {
      const stripeScript = document.createElement('script');
      stripeScript.src = 'https://js.stripe.com/v3/'
      stripeScript.onload = this.loadStripe
      document.head.append(stripeScript);
      const stripeStyle = document.createElement('link')
      stripeStyle.rel = 'stylesheet'
      stripeStyle.href = 'StripeElements.css'
    },
    activateCreditOption() {
      this.chooseCredit = true
      this.choosePaypal = false
    },
    activatePaypalOption() {
      this.choosePaypal = true
      this.chooseCredit = false
    }
  },

  mounted() {
    if (this.stripePlanId) this.mountStripe()
    // TODO: USE DYNAMIC ATTRIBUTE
    const script = document.createElement('script');
    script.src = `https://www.paypal.com/sdk/js?client-id=${process.env.VUE_APP_CLIENT_SECRET}&vault=true&disable-funding=card`;
    script.onload = this.mountBtn;
    document.head.append(script);
    facebookTracking(this.subscription);
  },
  name: "PaypalButton"
}
</script>

<style lang="scss">


.gosubs-subtitle {
  text-align: left;
  margin-bottom: 3 * $gutter;
}

.payment__form {
  padding: 0 1px;
}

.radio-option {
  margin-bottom: 2 * $gutter;

  .button {
    margin: 4 * $gutter 0 0;
  }
}

.radio-option__wrapper {
  display: flex;
  padding: 3 * $gutter;
  cursor: pointer;
  border: 1px solid #e2e2e6;
  border-radius: 4px;

  &.selected {
    border-color: $color_primary;
    background-color: $color_gray_medium;
    border-bottom-left-radius: 0;
    border-bottom-right-radius: 0;
  }

  &:hover {
    .radio-option__marker {
      background-color: darken($color_gray_medium, 10%);
    }
  }
}

.radio-option__label {
  color: $color_title;
  font-size: 16px;
  cursor: pointer;
  display: inline-block;
  margin-left: 2 * $gutter;

  span {
    color: $color_primary;
    font-size: 14px;
  }
}

.radio-option__input {
  display: none;
}
.radio-option__marker {
  width: 16px;
  height: 16px;
  flex-shrink: 0;
  background-color: $color_gray_medium;
  border-radius: 16px;
  box-sizing: border-box;
  display: inline-block;
  vertical-align: text-top;
}
.radio-option__wrapper.selected .radio-option__marker {
  background: $color_primary;
  border: 3px solid #FFF;
  box-shadow: 0px 0px 0px 1px $color_primary;
}

.radio-option__content {
  display: none;
  margin: 3 * $gutter 0 8 * $gutter;
  border: 1px solid $color_gray_medium;
  border-top: 0;
  border-bottom-left-radius: 4px;
  border-bottom-right-radius: 4px;
  padding: 16px;
  margin: 0;

  &.active {
    display: block;
    border-color: $color_primary;
  }

  .float-form {
    margin-top: 0;
  }
}

#card-element {
  padding: 0 8px 0 16px;
  border-radius: 12px;
  background: #f2f2f6;
}

#card-element-errors {
  text-align: left;
  color: #EC3F69;
  font-size: 12px;
  margin-top: 4px;
  display: block;

  &:empty {
    display: none;
  }
}

.gosubs-btn--form {
  margin-top: $gutter_mobile;
}


.divisor {
  margin: $gutter_mobile 0;
}
</style>