/* global Stripe */

/**
 * This directive allows to extend a form with the Stripe payment input and error handling area.
 * Strong-customer authentication is supported.
 * --
 * https://stripe.com/docs/payments/payment-intents/web-manual
 */
Application.Directives.directive('stripeForm', ['Payment', 'growl', '_t',
  function (Payment, growl, _t) {
    return ({
      restrict: 'A',
      scope: {
        cartItems: '=',
        onPaymentSuccess: '=',
        stripeKey: '@'
      },
      link: function ($scope, element, attributes) {
        const stripe = Stripe($scope.stripeKey);
        const elements = stripe.elements();

        const style = {
          base: {
            color: '#32325d',
            fontFamily: '"Helvetica Neue", Helvetica, sans-serif',
            fontSmoothing: 'antialiased',
            fontSize: '16px',
            '::placeholder': {
              color: '#aab7c4'
            }
          },
          invalid: {
            color: '#fa755a',
            iconColor: '#fa755a'
          }
        };

        const card = elements.create('card', { style, hidePostalCode: true });

        card.addEventListener('change', function ({ error }) {
          const displayError = document.getElementById('card-errors');
          if (error) {
            displayError.textContent = error.message;
          } else {
            displayError.textContent = '';
          }
        });

        // Add an instance of the card Element into the `card-element` <div>.
        const form = angular.element(element);
        const cardElement = form.find('#card-element');
        card.mount(cardElement[0]);

        form.bind('submit', function () {
          const button = form.find('button');
          button.prop('disabled', true);

          stripe.createPaymentMethod('card', card).then(function ({ paymentMethod, error }) {
            if (error) {
              growl.error(error.message);
              button.prop('disabled', false);
            } else {
              // Send paymentMethod.id to your server (see Step 2)
              Payment.confirm({ payment_method_id: paymentMethod.id, cart_items: $scope.cartItems }, function (response) {
                // Handle server response (see Step 3)
                handleServerResponse(response, button);
              }, function (error) { handleServerResponse({ error }, button); });
            }
          });
        });

        function handleServerResponse (response, confirmButton) {
          if (response.error) {
            if (response.error.statusText) {
              growl.error(response.error.statusText);
            } else {
              growl.error(`${_t('app.shared.messages.payment_card_error')} ${response.error}`);
            }
            confirmButton.prop('disabled', false);
          } else if (response.requires_action) {
            // Use Stripe.js to handle required card action
            stripe.handleCardAction(
              response.payment_intent_client_secret
            ).then(function (result) {
              if (result.error) {
                growl.error(result.error.message);
                confirmButton.prop('disabled', false);
              } else {
                // The card action has been handled
                // The PaymentIntent can be confirmed again on the server
                Payment.confirm({ payment_intent_id: result.paymentIntent.id, cart_items: $scope.cartItems }, function (confirmResult) {
                  handleServerResponse(confirmResult, confirmButton);
                }, function (error) { handleServerResponse({ error }, confirmButton); });
              }
            });
          } else {
            $scope.onPaymentSuccess(response);
          }
        }
      }
    });
  }]);
