# frozen_string_literal: true

require "test_helper"
require "registration"

class RegistrationTest < Minitest::Test
	Customer::IQ_MANAGER = Minitest::Mock.new

	def test_for_activated
		skip "Registration#for activated not implemented yet"
		iq = Blather::Stanza::Iq::Command.new
		Registration.for(iq, Customer.new("test"), Minitest::Mock.new).sync
	end
	em :test_for_activated

	def test_for_not_activated_with_customer_id
		Customer::IQ_MANAGER.expect(
			:write,
			EMPromise.resolve(nil),
			[Blather::Stanza::Iq]
		)
		web_manager = WebRegisterManager.new
		web_manager["test@example.com"] = "+15555550000"
		iq = Blather::Stanza::Iq::Command.new
		iq.from = "test@example.com"
		result = Registration.for(
			iq,
			Customer.new("test"),
			web_manager
		).sync
		assert_kind_of Registration::Activation, result
	end
	em :test_for_not_activated_with_customer_id

	def test_for_not_activated_without_customer_id
		skip "customer_id creation not implemented yet"
		iq = Blather::Stanza::Iq::Command.new
		Registration.for(iq, nil, Minitest::Mock.new).sync
	end
	em :test_for_not_activated_without_customer_id

	class ActivationTest < Minitest::Test
		Registration::Activation::COMMAND_MANAGER = Minitest::Mock.new
		def setup
			iq = Blather::Stanza::Iq::Command.new
			@activation = Registration::Activation.new(iq, "test", "+15555550000")
		end

		def test_write
			result = Minitest::Mock.new
			result.expect(:then, result)
			result.expect(:then, EMPromise.resolve(:test_result))
			Registration::Activation::COMMAND_MANAGER.expect(
				:write,
				result,
				[Blather::Stanza::Iq::Command]
			)
			assert_equal :test_result, @activation.write.sync
		end
		em :test_write
	end

	class PaymentTest < Minitest::Test
		Registration::Payment::Bitcoin::ELECTRUM = Minitest::Mock.new

		def test_for_bitcoin
			Registration::Payment::Bitcoin::ELECTRUM.expect(:createnewaddress, "addr")
			iq = Blather::Stanza::Iq::Command.new
			iq.form.fields = [
				{ var: "activation_method", value: "bitcoin" },
				{ var: "plan_name", value: "test_usd" }
			]
			result = Registration::Payment.for(
				iq,
				Customer.new("test"),
				"+15555550000"
			)
			assert_kind_of Registration::Payment::Bitcoin, result
		end

		def test_for_credit_card
			skip "CreditCard not implemented yet"
			iq = Blather::Stanza::Iq::Command.new
			iq.form.fields = [
				{ var: "activation_method", value: "credit_card" },
				{ var: "plan_name", value: "test_usd" }
			]
			result = Registration::Payment.for(iq, "test", "+15555550000")
			assert_kind_of Registration::Payment::CreditCard, result
		end

		def test_for_code
			skip "Code not implemented yet"
			iq = Blather::Stanza::Iq::Command.new
			iq.form.fields = [
				{ var: "activation_method", value: "code" },
				{ var: "plan_name", value: "test_usd" }
			]
			result = Registration::Payment.for(iq, "test", "+15555550000")
			assert_kind_of Registration::Payment::Code, result
		end

		class BitcoinTest < Minitest::Test
			Registration::Payment::Bitcoin::ELECTRUM = Minitest::Mock.new
			Registration::Payment::Bitcoin::REDIS = Minitest::Mock.new
			Registration::Payment::Bitcoin::BTC_SELL_PRICES = Minitest::Mock.new
			Registration::Payment::Bitcoin::BLATHER = Minitest::Mock.new

			def setup
				Registration::Payment::Bitcoin::ELECTRUM.expect(
					:createnewaddress,
					EMPromise.resolve("testaddr")
				)
				iq = Blather::Stanza::Iq::Command.new
				iq.form.fields = [
					{ var: "plan_name", value: "test_usd" }
				]
				@bitcoin = Registration::Payment::Bitcoin.new(
					iq,
					Customer.new("test"),
					"+15555550000"
				)
			end

			def test_write
				reply_text = <<~NOTE
					Activate your account by sending at least 1.000000 BTC to
					testaddr

					You will receive a notification when your payment is complete.
				NOTE
				Registration::Payment::Bitcoin::BLATHER.expect(
					:<<,
					nil,
					[Matching.new do |reply|
						assert_equal :completed, reply.status
						assert_equal :info, reply.note_type
						assert_equal reply_text, reply.note.content
						true
					end]
				)
				Registration::Payment::Bitcoin::BTC_SELL_PRICES.expect(
					:usd,
					EMPromise.resolve(BigDecimal.new(1))
				)
				@bitcoin.stub(:save, EMPromise.resolve(nil)) do
					@bitcoin.write.sync
				end
				Registration::Payment::Bitcoin::BLATHER.verify
			end
			em :test_write
		end
	end
end
