# frozen_string_literal: true

require "forwardable"
require "ruby-bandwidth-iris"
Faraday.default_adapter = :em_synchrony

class BandwidthTNOrder
	ORDER_DEFAULTS = {
		site_id: CONFIG[:bandwidth_site],
		peer_id: CONFIG[:bandwidth_peer]
	}.freeze

	def self.get(id)
		EMPromise.resolve(nil).then do
			self.for(BandwidthIris::Order.get_order_response(
				# https://github.com/Bandwidth/ruby-bandwidth-iris/issues/44
				BandwidthIris::Client.new,
				id
			))
		end
	end

	def self.create(
		tel,
		name: "sgx-jmp order #{tel}",
		reservation_id: nil,
		**kwargs
	)
		create_custom(
			name: name, **kwargs,
			existing_telephone_number_order_type: {
				telephone_number_list: { telephone_number: [tel.sub(/^\+?1?/, "")] }
			}.merge(ReservationIdList.new(reservation_id).to_h)
		)
	end

	def self.create_custom(name:, **kwargs)
		EMPromise.resolve(nil).then do
			Received.new(BandwidthIris::Order.create(
				name: name, **ORDER_DEFAULTS, **kwargs
			))
		end
	end

	def self.for(bandwidth_order)
		const_get(bandwidth_order.order_status.capitalize).new(bandwidth_order)
	rescue NameError
		new(bandwidth_order)
	end

	extend Forwardable
	def_delegators :@order, :id

	def initialize(bandwidth_order)
		@order = bandwidth_order
	end

	def status
		@order[:order_status]&.downcase&.to_sym
	end

	def error_description
		[@order[:error_list]].flatten.first&.dig(:error, :description)
	end

	def poll
		raise "Unknown order status: #{status}"
	end

	class Received < BandwidthTNOrder
		def status
			:received
		end

		def poll
			EM.promise_timer(1).then do
				BandwidthTNOrder.get(id).then(&:poll)
			end
		end
	end

	class Complete < BandwidthTNOrder
		def status
			:complete
		end

		def tel
			tels[0]
		end

		def tels
			tns = @order.completed_numbers[:telephone_number]
			(tns.is_a?(Array) ? tns : [tns]).map do |item|
				"+1#{item[:full_number]}"
			end
		end

		def poll
			EMPromise.resolve(self)
		end
	end

	class Failed < BandwidthTNOrder
		def status
			:failed
		end

		def poll
			raise "Order failed: #{id} #{error_description}"
		end
	end

	class ReservationIdList
		def initialize(reservation_id)
			@reservation_id = reservation_id
		end

		def to_h
			return {} unless @reservation_id

			{ reservation_id_list: { reservation_id: @reservation_id } }
		end
	end
end
