# frozen_string_literal: true

require_relative "trust_level_repo"
require_relative "credit_card_sale"

class BuyAccountCreditForm
	# Returns a TrustLevelRepo instance, allowing for dependency injection.
	# Either creates a new instance given kwargs or returns the existing instance.
	# @param kwargs [Hash] keyword arguments.
	# @option kwargs [TrustLevelRepo] :trust_level_repo An existing TrustLevelRepo
	# instance.
	# @return [TrustLevelRepo] An instance of TrustLevelRepo.
	def self.trust_level_repo(**kwargs)
		kwargs[:trust_level_repo] || TrustLevelRepo.new(**kwargs)
	end

	# Factory method to create a BuyAccountCreditForm for a given customer.
	# It fetches the customer's trust level to determine the maximum top-up
	# amount.
	# @param customer [Customer] The customer for whom the form is being created.
	# @return [EMPromise<BuyAccountCreditForm>] A promise that resolves with the
	# new form instance.
	def self.for(customer)
		trust_level_repo.find(customer).then do |trust_level|
			customer.payment_methods.then do |payment_methods|
				new(customer.balance, payment_methods, trust_level.max_top_up_amount)
			end
		end
	end

	# Initializes a new BuyAccountCreditForm.
	# @param balance [BigDecimal] The current balance of the customer.
	# @param payment_methods [PaymentMethods] The available payment methods for
	# the customer.
	# @param max_top_up_amount [Numeric] The maximum amount the customer is
	# allowed to top up, based on their trust level.
	def initialize(balance, payment_methods, max_top_up_amount)
		@balance = balance
		@payment_methods = payment_methods
		@max_top_up_amount = max_top_up_amount
	end

	# Generates the form template for topping up account credit.
	# The form will include a range for the amount field, constrained by a minimum
	# of $15
	# and the customer's specific maximum top-up amount.
	# @return [FormTemplate::OneRender] The rendered form template.
	def form
		FormTemplate.render(
			:top_up,
			balance: @balance,
			payment_methods: @payment_methods,
			max_top_up_amount: @max_top_up_amount
		)
	end

	def parse(form)
		amount = form.field("amount")&.value&.to_s
		amount_value = amount.to_f

		raise AmountTooLowError.new(amount_value, 15) if amount_value < 15

		{
			payment_method: @payment_methods.fetch(
				form.field("payment_method")&.value.to_i
			),
			amount: amount
		}
	end
end
