1# frozen_string_literal: true
 2
 3require_relative "trust_level_repo"
 4require_relative "credit_card_sale"
 5
 6class BuyAccountCreditForm
 7	# Returns a TrustLevelRepo instance, allowing for dependency injection.
 8	# Either creates a new instance given kwargs or returns the existing instance.
 9	# @param kwargs [Hash] keyword arguments.
10	# @option kwargs [TrustLevelRepo] :trust_level_repo An existing TrustLevelRepo
11	# instance.
12	# @return [TrustLevelRepo] An instance of TrustLevelRepo.
13	def self.trust_level_repo(**kwargs)
14		kwargs[:trust_level_repo] || TrustLevelRepo.new(**kwargs)
15	end
16
17	# Factory method to create a BuyAccountCreditForm for a given customer.
18	# It fetches the customer's trust level to determine the maximum top-up
19	# amount.
20	# @param customer [Customer] The customer for whom the form is being created.
21	# @return [EMPromise<BuyAccountCreditForm>] A promise that resolves with the
22	# new form instance.
23	def self.for(customer)
24		trust_level_repo.find(customer).then do |trust_level|
25			customer.payment_methods.then do |payment_methods|
26				new(customer.balance, payment_methods, trust_level.max_top_up_amount)
27			end
28		end
29	end
30
31	# Initializes a new BuyAccountCreditForm.
32	# @param balance [BigDecimal] The current balance of the customer.
33	# @param payment_methods [PaymentMethods] The available payment methods for
34	# the customer.
35	# @param max_top_up_amount [Numeric] The maximum amount the customer is
36	# allowed to top up, based on their trust level.
37	def initialize(balance, payment_methods, max_top_up_amount)
38		@balance = balance
39		@payment_methods = payment_methods
40		@max_top_up_amount = max_top_up_amount
41	end
42
43	# Generates the form template for topping up account credit.
44	# The form will include a range for the amount field, constrained by a minimum
45	# of $15
46	# and the customer's specific maximum top-up amount.
47	# @return [FormTemplate::OneRender] The rendered form template.
48	def form
49		FormTemplate.render(
50			:top_up,
51			balance: @balance,
52			payment_methods: @payment_methods,
53			max_top_up_amount: @max_top_up_amount
54		)
55	end
56
57	def parse(form)
58		amount = form.field("amount")&.value&.to_s
59		amount_value = amount.to_f
60
61		raise AmountTooLowError.new(amount_value, 15) if amount_value < 15
62
63		{
64			payment_method: @payment_methods.fetch(
65				form.field("payment_method")&.value.to_i
66			),
67			amount: amount
68		}
69	end
70end