# frozen_string_literal: true

require "jennifer"
require_relative "../rantly_extensions/data_extensions"

class MessageStanza
	# @param redis [FakeRedis]
	def initialize(redis)
		@redis = redis
	end

	include Jennifer.rant(self) { |component|
		recv_nums(transient: true) {
			array(range(1, 5)) {
				choose(
					value { nanpa_phone },
					value { non_nanp_phone },
					value { shortcode }
				)
			}
		}
		to derived_from(:recv_nums), transient: true do |recv_nums|
			recv_nums.map { |num| "#{num}@#{component}" }
		end
		phone(transient: true) { nanpa_phone }
		from(transient: true) { bare_jid }
		media(transient: true) {
			array(range(0, 5)) {
				[media_url, range(0, MAX_MEDIA_SIZE << 1)]
			}
		}
		registered?(transient: true) { true }
		body(transient: true) { choose(nil, "", value { message_body }) }
		id(transient: true) { SecureRandom.uuid }
		subject { _utf8_body(range(1, 10)) }
		stanza derived_from(:body, :to, :from, :subject, :media, :id, :recv_nums) { |body, to_jids, from, subject, media, id, recv_nums|
			stanza_body = body
			if media.any? && boolean
				url = media.first.first
				stanza_body = stanza_body.to_s.empty? ? url : "#{stanza_body}\n#{url}"
			end

			if recv_nums.length == 1
				m = Blather::Stanza::Message.new(to_jids.first, stanza_body)
			else
				m = Blather::Stanza::Message.new(component, stanza_body)
				addrs = Nokogiri::XML::Node.new('addresses', m.document)
				addrs['xmlns'] = 'http://jabber.org/protocol/address'
				recv_nums.each do |num|
					addr = Nokogiri::XML::Node.new('address', m.document)
					addr['type'] = 'to'
					addr['uri'] = "sms:#{num}"
					addrs.add_child(addr)
				end
				m.add_child(addrs)
			end

			m.from = from
			m.id = id
			m.subject = subject if subject

			media.each do |url, _size|
				x = Nokogiri::XML::Node.new('x', m.document)
				ns = x.add_namespace(nil, 'jabber:x:oob')
				url_node = Nokogiri::XML::Node.new('url', m.document)
				url_node.namespace = ns
				url_node.content = url
				x.add_child(url_node)
				m.add_child(x)
			end

			m
		}
		redis_state derived_from(:from, :phone, :registered?), transient: true do |from, phone, registered|
			@redis.reset!
			@redis.set("catapult_jid-", "HERE")
			next unless registered

			@redis.set("catapult_jid-#{phone}", from)
			@redis.rpush("catapult_cred-#{from}", 'account', 'token', 'secret', phone)
		end
		http_stubs derived_from(:media, :registered?), transient: true do |media, registered|
			WebMock.reset!
			next [] unless registered

			media.map do |url, size|
				ext = File.extname(URI.parse(url).path)
				content_type = freq(
					[95, proc { Rack::Mime.mime_type(ext) }],
					[5, proc { Rack::Mime.mime_type(".#{string(:alpha)}") }]
				)
				WebMock::API.stub_request(:head, url).to_return(
					status: 200,
					headers: {
						"Content-Length" => size.to_s,
						"Content-Type" => content_type
					}
				)
			end
		end
		bandwidth_stub derived_from(:registered?, :media), transient: true do |registered, _media|
			next unless registered

			WebMock::API.stub_request(:post, BW_MESSAGES_URL).to_return(
				status: 202,
				body: JSON.dump(id: "bw-msg-#{SecureRandom.hex(4)}")
			)
		end
		assertions derived_from(:http_stubs, :bandwidth_stub) { |stubs, bw|
			a = stubs.map { |stub| -> { assert_requested(stub) } }
			a << -> { assert_requested(bw) } if bw
			a
		}
		written_state(transient: true) {
			SGXbwmsgsv2.instance_variable_set(:@written, [])
		}
	}
end
