# frozen_string_literal: true

# Encapsulation of logic used to convert a token generated by Stripe Elements
# into a Stripe Customer + Card which can then be charged at a later point in time
# Stores the generated customer & card ids against the local instance of Spree::CreditCard

module Stripe
  class ProfileStorer
    def initialize(payment, provider)
      @payment = payment
      @provider = provider
    end

    def create_customer_from_token
      token = ActiveMerchant::Billing::StripeGateway::StripePaymentToken.new(
        { 'id' => @payment.source.gateway_payment_profile_id }
      )
      response = @provider.store(token, options)

      if response.success?
        attrs = source_attrs_from(response)
        @payment.source.update!(attrs)
      else
        @payment.__send__(:gateway_error, response.message)
      end
    end

    private

    def options
      {
        email: @payment.order.email,
        login: Stripe.api_key,
        address: address_for(@payment)
      }
    end

    def address_for(payment)
      {}.tap do |hash|
        if address = payment.order.bill_address
          hash = {
            address1: address.address1,
            address2: address.address2,
            city: address.city,
            zip: address.zipcode
          }

          if address.country
            hash[:country] = address.country.name
          end

          if address.state
            hash[:state] = address.state.name
          end
        end
      end
    end

    def source_attrs_from(response)
      {
        cc_type: @payment.source.cc_type,
        gateway_customer_profile_id: customer_profile_id(response),
        gateway_payment_profile_id: payment_profile_id(response)
      }
    end

    def customer_profile_id(response)
      response.params['customer'] || response.params['id']
    end

    def payment_profile_id(response)
      if response.params['customer'] # Payment Intents API
        response.params['id']
      else
        response.params['default_source'] || response.params['default_card']
      end
    end
  end
end
