<commit_before>module Payment
  class << self
    def table_name_prefix
      'payment_'
    end

    def write_successful_transaction(action:, transaction_response:)
      BraintreeTransactionBuilder.build(action, transaction_response)
    end

    def write_unsuccessful_transaction(action:, transaction_response:)
      # TODO: Implement
    end

    def write_subscription(subscription:)
      BraintreeSubscriptionBuilder.build(subscription)
    end

    def customer(email)
      member = Member.find_by(email: email)
      member.try(:customer)
    end
  end

  class BraintreeSubscriptionBuilder

    def self.build(response)
      new(response).build
    end

    def initialize(response)
      @response = response
      @subscription = response.subscription
    end

    def build
      if @response.success?
        ::Payment::BraintreeSubscription.create(attrs)
      end
    end

    def attrs
     {
        subscription_id:        @subscription.id,
        price:                  @subscription.price,
        merchant_account_id:    @subscription.merchant_account_id
      }
    end
  end

  class BraintreeTransactionBuilder
    #
    # Stores and associates a Braintree transaction as +Payment::BraintreeTransaction+. Builder will also
    # create an instance of +Payment::BraintreeCustomer+, if it doesn't already exist.
    #
    # === Options
    #
    # * +:action+                 - The ActiveRecord model of the corresponding action.
    # * +:transaction_response+   - An Braintree::Transaction response object (see https://developers.braintreepayments.com/reference/response/transaction/ruby)
    #

    def self.build(action, transaction_response)
      new(action, transaction_response).build
    end

    def initialize(action, transaction_response)
      @action = action
      @transaction_response = transaction_response
    end


    def build
      if @transaction_response.success?
        ::Payment::BraintreeTransaction.create(transaction_attrs)

        unless locally_stored_customer
          store_braintree_customer_locally
        end
      end
    end

    private

    def locally_stored_customer
      @locally_stored_customer ||= Payment.customer(customer_details.email)
    end

    def store_braintree_customer_locally
      Payment::BraintreeCustomer.create(customer_attrs)
    end

    def transaction_attrs
     {
        transaction_id:          sale.id,
        transaction_type:        sale.type,
        payment_instrument_type: sale.payment_instrument_type,
        amount:                  sale.amount,
        transaction_created_at:  sale.created_at,
        merchant_account_id:     sale.merchant_account_id,
        currency:                sale.currency_iso_code,
        page:                    @action.page
      }
    end

    def customer_attrs
      {
        card_type:        card.card_type,
        card_bin:         card.bin,
        cardholder_name:  card.cardholder_name,
        card_debit:       card.debit,
        card_last_4:      card.last_4,
        card_vault_token: card.token,
        customer_id:      customer_details.id,
        email:            customer_details.email,
        member:           @action.member
      }
    end

    def sale<commit_msg>Do not save email address<commit_after>module Payment
  class << self
    def table_name_prefix
      'payment_'
    end

    def write_successful_transaction(action:, transaction_response:)
      BraintreeTransactionBuilder.build(action, transaction_response)
    end

    def write_unsuccessful_transaction(action:, transaction_response:)
      # TODO: Implement
    end

    def write_subscription(subscription:)
      BraintreeSubscriptionBuilder.build(subscription)
    end

    def customer(email)
      member = Member.find_by(email: email)
      member.try(:customer)
    end
  end

  class BraintreeSubscriptionBuilder

    def self.build(response)
      new(response).build
    end

    def initialize(response)
      @response = response
      @subscription = response.subscription
    end

    def build
      if @response.success?
        ::Payment::BraintreeSubscription.create(attrs)
      end
    end

    def attrs
     {
        subscription_id:        @subscription.id,
        price:                  @subscription.price,
        merchant_account_id:    @subscription.merchant_account_id
      }
    end
  end

  class BraintreeTransactionBuilder
    #
    # Stores and associates a Braintree transaction as +Payment::BraintreeTransaction+. Builder will also
    # create an instance of +Payment::BraintreeCustomer+, if it doesn't already exist.
    #
    # === Options
    #
    # * +:action+                 - The ActiveRecord model of the corresponding action.
    # * +:transaction_response+   - An Braintree::Transaction response object (see https://developers.braintreepayments.com/reference/response/transaction/ruby)
    #

    def self.build(action, transaction_response)
      new(action, transaction_response).build
    end

    def initialize(action, transaction_response)
      @action = action
      @transaction_response = transaction_response
    end


    def build
      if @transaction_response.success?
        ::Payment::BraintreeTransaction.create(transaction_attrs)

        unless locally_stored_customer
          store_braintree_customer_locally
        end
      end
    end

    private

    def locally_stored_customer
      @locally_stored_customer ||= Payment.customer(customer_details.email)
    end

    def store_braintree_customer_locally
      Payment::BraintreeCustomer.create(customer_attrs)
    end

    def transaction_attrs
     {
        transaction_id:          sale.id,
        transaction_type:        sale.type,
        payment_instrument_type: sale.payment_instrument_type,
        amount:                  sale.amount,
        transaction_created_at:  sale.created_at,
        merchant_account_id:     sale.merchant_account_id,
        currency:                sale.currency_iso_code,
        page:                    @action.page
      }
    end

    def customer_attrs
      {
        card_type:        card.card_type,
        card_bin:         card.bin,
        cardholder_name:  card.cardholder_name,
        card_debit:       card.debit,
        card_last_4:      card.last_4,
        card_vault_token: card.token,
        customer_id:      customer_details.id,
        member:           @action.member
      }
    end

    def sale
{'fraction_non_alphanumeric': 0.0668424317617866, 'fraction_numerical': 0.0006203473945409429, 'mean_word_length': 2.3501298701298703, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 3, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '472597', 'n_tokens_mistral': 1782, 'n_tokens_neox': 1749, 'n_words': 357}