# frozen_string_literal: true

require "test_helper"
require_relative "../../sgx-bwmsgsv2"
require "rantly/minitest_extensions"
require_relative "generators/port_out_pin_cmd"

def panic(e)
	$panic = e
end

class PortOutPinPropertyTest < Minitest::Test
	def setup
		reset_stanzas!
		reset_redis!
	end

	def test_execute_returns_form_for_registered_user
		property_of {
			PortOutPinExecuteCmd.new(REDIS).generate
		}.check { |_metadata, example|
			process_stanza(example['stanza'])

			assert_equal 1, written.length
			reply = written.shift

			assert_equal example['jid'], reply.to.to_s
			assert_equal :executing, reply.status
			assert_equal 'set-port-out-pin', reply.node

			vars = reply.form.fields.map(&:var)
			assert_includes vars, 'pin'
			assert_includes vars, 'confirm_pin'
		}
	end
	em :test_execute_returns_form_for_registered_user

	def test_execute_rejects_unregistered_user
		property_of {
			PortOutPinExecuteCmd
				.new(REDIS)
				.redis_state { |_jid, _phone| @redis.reset! }
				.generate
		}.check { |_metadata, example|
			process_stanza(example['stanza'])

			assert_equal 1, written.length
			reply = written.shift
			assert_kind_of Blather::StanzaError, reply
			assert_equal :auth, reply.type
			assert_equal :registration_required, reply.name
		}
	end
	em :test_execute_rejects_unregistered_user

	def test_complete_success_sets_pin
		property_of {
			PortOutPinCompleteCmd.new(REDIS).generate
		}.check { |_metadata, example|
			BandwidthTNOptions.stub(
				:set_port_out_pin,
				EMPromise.resolve(nil)
			) do
				process_stanza(example['stanza'])
			end

			assert_equal 1, written.length
			reply = written.shift

			assert_equal example['jid'], reply.to.to_s
			assert_equal :completed, reply.status
			assert_equal 'set-port-out-pin', reply.node
			ns = 'http://jabber.org/protocol/commands'
			note = reply.find('.//ns:note', ns: ns).first
			assert_equal 'info', note[:type]
			assert_equal 'Port-out PIN has been set successfully.', note.content
		}
	end
	em :test_complete_success_sets_pin

	def test_complete_nil_pin_returns_error
		property_of {
			PortOutPinCompleteCmd
				.new(REDIS)
				.pin {
					choose(true, false) ? nil : sized(range(4, 10)) { string(:alnum) }
				}
				.confirm_pin { |pin|
					pin.nil? ? choose(nil, sized(range(4, 10)) { string(:alnum) }) : nil
				}
				.stanza { |jid, sid, pin, cpin|
					cmd = Blather::Stanza::Iq::Command.new
					cmd.type = :set
					cmd.to = 'component'
					cmd.node = 'set-port-out-pin'
					cmd.sessionid = sid
					cmd.action = :complete
					cmd.from = jid
					cmd.form.type = :submit

					fields = []
					if pin
						fields << { var: 'pin', value: pin }
					elsif choose(true, false)
						fields << { var: 'pin', value: nil }
					end
					if cpin
						fields << { var: 'confirm_pin', value: cpin }
					elsif choose(true, false)
						fields << { var: 'confirm_pin', value: nil }
					end
					cmd.form.fields = fields unless fields.empty?
					cmd
				}
				.generate
		}.check { |_metadata, example|
			process_stanza(example['stanza'])

			assert_equal 1, written.length
			reply = written.shift
			assert_kind_of Blather::StanzaError, reply
			assert_equal :modify, reply.type
			assert_equal :bad_request, reply.name
		}
	end
	em :test_complete_nil_pin_returns_error

	def test_complete_mismatched_pins_returns_error
		property_of {
			PortOutPinCompleteCmd
				.new(REDIS)
				.confirm_pin { |_pin|
					sized(range(4, 10)) { string(:alnum) } + "X"
				}
				.generate
		}.check { |_metadata, example|
			process_stanza(example['stanza'])

			assert_equal 1, written.length
			reply = written.shift
			assert_kind_of Blather::StanzaError, reply
			assert_equal :modify, reply.type
			assert_equal :bad_request, reply.name
		}
	end
	em :test_complete_mismatched_pins_returns_error

	def test_complete_invalid_pin_format_returns_error
		property_of {
			PortOutPinCompleteCmd
				.new(REDIS)
				.pin { choose("ab", "a" * 11, "pin!@#") }
				.confirm_pin { |pin| pin }
				.generate
		}.check { |_metadata, example|
			process_stanza(example['stanza'])

			assert_equal 1, written.length
			reply = written.shift
			assert_kind_of Blather::StanzaError, reply
			assert_equal :modify, reply.type
			assert_equal :bad_request, reply.name
		}
	end
	em :test_complete_invalid_pin_format_returns_error
end
