# frozen_string_literal: true

require "test_helper"
require "payment_methods"

class PaymentMethodsTest < Minitest::Test
	def test_for
		braintree_customer = Minitest::Mock.new
		braintree_customer.expect(:payment_methods, [
			OpenStruct.new(card_type: "Test", last_4: "1234")
		])
		methods = PaymentMethods.for(braintree_customer, [])
		assert_kind_of PaymentMethods, methods
		assert_equal 1, methods.to_a.length
		refute methods.empty?
	end

	def test_for_badcards
		braintree_customer = Minitest::Mock.new
		braintree_customer.expect(:payment_methods, [
			OpenStruct.new(
				card_type: "Test",
				last_4: "1234",
				unique_number_identifier: "wut"
			)
		])
		methods = PaymentMethods.for(braintree_customer, ["wut"])
		assert_kind_of PaymentMethods, methods
		assert_equal 0, methods.to_a.length
		assert methods.empty?
	end

	def test_for_expired_cards
		braintree_customer = Minitest::Mock.new
		braintree_customer.expect(:payment_methods, [
			OpenStruct.new(
				card_type: "Test",
				last_4: "1234",
				unique_number_identifier: "abc",
				expired?: true
			)
		])

		methods = PaymentMethods.for(braintree_customer, [])
		assert_kind_of PaymentMethods, methods
		assert_equal 0, methods.to_a.length
		assert methods.empty?
	end

	def test_for_badcards_and_expired_cards
		braintree_customer = Minitest::Mock.new
		braintree_customer.expect(:payment_methods, [
			OpenStruct.new(
				card_type: "Test",
				last_4: "1234",
				unique_number_identifier: "abc",
				expired?: true
			)
		])

		methods = PaymentMethods.for(braintree_customer, ["abc"])
		assert_kind_of PaymentMethods, methods
		assert_equal 0, methods.to_a.length
		assert methods.empty?
	end

	def test_for_non_expired_cards
		braintree_customer = Minitest::Mock.new
		braintree_customer.expect(:payment_methods, [
			OpenStruct.new(
				card_type: "Test",
				last_4: "1234",
				unique_number_identifier: "abc",
				expired?: false
			)
		])

		methods = PaymentMethods.for(braintree_customer, [])
		assert_kind_of PaymentMethods, methods
		assert_equal 1, methods.to_a.length
		refute methods.empty?
	end

	def test_for_no_methods
		braintree_customer = Minitest::Mock.new
		braintree_customer.expect(:payment_methods, [])
		methods = PaymentMethods.for(braintree_customer, [])
		assert_kind_of PaymentMethods, methods
		assert_raises do
			methods.to_list_single
		end
		assert_equal 0, methods.to_a.length
		assert methods.empty?
	end

	def test_default_payment_method
		methods = PaymentMethods.new([
			OpenStruct.new(card_type: "Test", last_4: "1234"),
			OpenStruct.new(card_type: "Test", last_4: "1234", default?: true)
		])
		assert_equal methods.fetch(1), methods.default_payment_method
	end

	def test_default_payment_method_index
		methods = PaymentMethods.new([
			OpenStruct.new(card_type: "Test", last_4: "1234"),
			OpenStruct.new(card_type: "Test", last_4: "1234", default?: true)
		])
		assert_equal "1", methods.default_payment_method_index
	end

	def test_to_options
		methods = PaymentMethods.new([
			OpenStruct.new(card_type: "Test", last_4: "1234")
		])
		assert_equal(
			[
				{ value: "0", label: "Test 1234" }
			],
			methods.to_options
		)
	end

	def test_to_list_single
		methods = PaymentMethods.new([
			OpenStruct.new(card_type: "Test", last_4: "1234")
		])
		assert_equal(
			{
				var: "payment_method",
				type: "list-single",
				label: "Credit card to pay with",
				required: true,
				value: nil,
				options: [
					{ value: "0", label: "Test 1234" }
				]
			},
			methods.to_list_single
		)
	end

	class EmptyTest < Minitest::Test
		def test_to_list_single
			assert_raises do
				PaymentMethods::Empty.new.to_list_single
			end
		end
	end
end
