# frozen_string_literal: true

require "braintree"
require_relative "customer"

class CreditCardGateway
	class ErrorResult < StandardError
		def self.for(result)
			if result.verification&.status == "gateway_rejected" &&
			   result.verification&.gateway_rejection_reason == "cvv"
				new("fieldInvalidForCvv")
			else
				new(result.message)
			end
		end
	end

	def initialize(currency, antifraud)
		@currency = currency
		@antifraud = antifraud

		@gateway = Braintree::Gateway.new(
			environment: BRAINTREE_CONFIG[:environment].to_s,
			merchant_id: BRAINTREE_CONFIG[:merchant_id].to_s,
			public_key: BRAINTREE_CONFIG[:public_key].to_s,
			private_key: BRAINTREE_CONFIG[:private_key].to_s
		)
	end

	def merchant_account
		BRAINTREE_CONFIG[:merchant_accounts][@currency]
	end

	def client_token(**kwargs)
		kwargs[:merchant_account_id] = merchant_account.to_s if merchant_account
		@gateway.client_token.generate(**kwargs)
	end

	def antifraud
		REDIS.mget(@antifraud.map { |k| "jmp_antifraud-#{k}" }).find do |anti|
			anti.to_i > 2
		end &&
			Braintree::ErrorResult.new(
				@gateway, errors: {}, message: "Please contact support"
			)
	end

	def with_antifraud
		result = antifraud || yield
		return result if result.success?

		@antifraud.each do |k|
			REDIS.incr("jmp_antifraud-#{k}")
			REDIS.expire("jmp_antifraud-#{k}", 60 * 60 * 24)
		end

		raise ErrorResult.for(result)
	end

	def sale(nonce, amount, **kwargs)
		with_antifraud do
			@gateway.transaction.sale(
				payment_method_nonce: nonce,
				amount: amount, merchant_account_id: merchant_account.to_s,
				options: {
					store_in_vault_on_success: true, submit_for_settlement: true
				}, **kwargs
			)
		end
	end

	def customer
		@gateway.customer
	end

	def payment_method
		@gateway.payment_method
	end
end
