# frozen_string_literal: true

require 'solidus_braintree_helper'

RSpec.describe "Checkout", type: :feature, js: true do
  let(:braintree_preferences) { { venmo: true }.merge(preferences) }
  let(:preferences) { {} }
  let(:user) { create(:user) }
  let!(:payment_method) { create_gateway }

  before do
    create(:store, payment_methods: [payment_method]).tap do |s|
      s.braintree_configuration.update!(braintree_preferences)
    end

    go_to_payment_checkout_page
  end

  context 'with Venmo checkout' do
    context 'when Venmo is disabled' do
      let(:preferences) { { venmo: false } }

      it 'does not load the Venmo payment button' do
        expect(page).not_to have_selector('#venmo-button')
      end
    end

    context 'when Venmo is enabled' do
      it 'loads the Venmo payment button' do
        expect(page).to have_selector('#venmo-button')
      end
    end

    context "when Venmo's button style is customized" do
      context 'when venmo_button_color is "blue" and venmo_button_width is "280"' do
        let(:preferences) { { preferred_venmo_button_color: 'blue', preferred_venmo_button_width: '280' } }

        it 'has the correct style' do
          venmo_button.assert_matches_style(width: '280px', 'background-image': /venmo_blue_button_280x48/)
          venmo_button.hover
          venmo_button.assert_matches_style('background-image': /venmo_active_blue_button_280x48/)
        end
      end

      context 'when venmo_button_color is "white" and venmo_button_width is "375"' do
        let(:preferences) { { preferred_venmo_button_color: 'white', preferred_venmo_button_width: '375' } }

        it 'has the correct style' do
          venmo_button.assert_matches_style(width: '375px', 'background-image': /venmo_white_button_375x48/)
          venmo_button.hover
          venmo_button.assert_matches_style('background-image': /venmo_active_white_button_375x48/)
        end
      end
    end

    context 'when the Venmo button is clicked' do
      before { venmo_button.click }

      it 'opens the QR modal which shows an error when closed' do
        within_frame(venmo_frame) do
          expect(page).to have_selector('#venmo-qr-code-view')

          click_button('close-icon')

          expect(page).not_to have_selector('#venmo-qr-code-view')
        end

        expect(page).to have_content('Venmo authorization was canceled by closing the Venmo Desktop modal.')
      end
    end

    # TODO: Reenable these specs once Venmo is enabled on the Braintree sandbox.
    xcontext 'with Venmo transactions', vcr: { cassette_name: 'checkout/valid_venmo_transaction' } do
      before do
        fake_venmo_successful_tokenization
      end

      context 'with CreditCard disabled' do
        it 'can checkout with Venmo' do
          next_checkout_step
          finalize_checkout

          expect(Spree::Order.last.complete?).to be(true)
        end
      end

      # To test that the hosted-fields inputs do not conflict with Venmo's
      context 'with CreditCard enabled' do
        let(:preferences) { { credit_card: true } }

        it 'can checkout with Venmo' do
          disable_hosted_fields_inputs
          disable_hosted_fields_form_listener

          next_checkout_step
          finalize_checkout

          expect(Spree::Order.last.complete?).to be(true)
          expect(Spree::Payment.last.source.venmo?).to be(true)
        end
      end

      # https://developer.paypal.com/braintree/docs/guides/venmo/client-side#custom-integration
      it "meet's Braintree's acceptance criteria during checkout", aggregate_failures: true do
        next_checkout_step

        expect(page).to have_content('Payment Type: Venmo')

        finalize_checkout

        expect(page).to have_content('Venmo Account: venmojoe')
      end

      # the VCR must be based on this test, so it includes HTTP requests of the second order
      it 'saves the used Venmo source in the wallet and can be reused' do
        next_checkout_step
        finalize_checkout
        go_to_payment_checkout_page(order_number: 'R300000002')

        expect(Spree::User.first.wallet.wallet_payment_sources).not_to be_empty
        expect(page).to have_selector('#existing_cards')
        expect(page).to have_content('venmojoe')

        next_checkout_step
        finalize_checkout

        expect(Spree::Order.all.all?(&:complete?)).to be(true)
      end
    end
  end

  private

  def go_to_payment_checkout_page(order_number: 'R300000001' )
    order = if Spree.solidus_gem_version >= Gem::Version.new('2.6.0')
              SolidusBraintree::OrderWalkthrough.up_to(:address)
            else
              OrderWalkthrough.up_to(:address)
            end

    order.update!(user: user, number: order_number) # constant order number for VCRs

    allow_any_instance_of(CheckoutsController).to receive_messages(current_order: order)

    first_user = Spree::User.first
    allow_any_instance_of(CheckoutsController).to receive_messages(try_spree_current_user: first_user)
    allow_any_instance_of(CheckoutsController).to receive_messages(spree_current_user: first_user)

    allow_any_instance_of(Spree::Payment).to receive(:gateway_order_id).and_return(order_number)

    visit checkout_state_path(order.state)
    next_checkout_step
  end

  def next_checkout_step
    click_button('Save and Continue')
  end

  def finalize_checkout
    click_button('Place Order')
  end

  def venmo_button
    find_button('venmo-button', disabled: false)
  end

  def venmo_frame
    find('#venmo-desktop-iframe')
  end

  def fake_venmo_successful_tokenization
    enable_venmo_inputs
    fake_payment_method_nonce
  end

  def enable_venmo_inputs
    page.execute_script("$('.venmo-fields input').each(function(_index, input){input.removeAttribute('disabled');});")
  end

  def fake_payment_method_nonce
    page.execute_script("$('#venmo_payment_method_nonce').val('fake-venmo-account-nonce');")
  end

  def disable_hosted_fields_inputs
    page.execute_script("$('.hosted-fields input').each(function(_index, input){input.disabled=true;});")
  end

  def disable_hosted_fields_form_listener
    # Once the submit button is enabled, the submit listener has been added
    find("#checkout_form_payment [type='submit']:not(:disabled)")
    page.execute_script("$('#checkout_form_payment').off('submit');")
  end
end