# frozen_string_literal: true

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

class BandwidthTNOptions
	def self.tn_eligible_for_port_out_pin?(creds)
		user_id, token, secret, tel = creds
		tel_local = tel.sub(/^\+1/, '')
		client = BandwidthIris::Client.new(
			account_id: user_id,
			username: token,
			password: secret
		)
		EMPromise.resolve(nil).then do
			tn = BandwidthIris::Tn.get(client, tel_local)
			details = tn.get_details()
			details[:tier] == 0.0 && details[:on_net_vendor] == true
		end
	end

	def self.set_port_out_pin(creds, pin)
		tn_eligible_for_port_out_pin?(creds).then do |eligible|
			unless eligible
				raise "TN not eligible for port-out PIN"
			end

			user_id, token, secret, tel = creds
			tel_local = tel.sub(/^\+1/, '')

			client = BandwidthIris::Client.new(
				account_id: user_id,
				username: token,
				password: secret
			)


			data = {
				tn_option_groups: {
					tn_option_group: [
						{
							port_out_passcode: pin,
							telephone_numbers: {
								telephone_number: [tel]
							}
						}
					]
				}
			}

			order = BandwidthIris::TnOptions.create_tn_option_order(client, data)
			order_id = order[:order_id]

			unless order_id
				raise "Missing OrderId in create response"
			end

			poll_order(order_id, client)
		end
	end

	def self.poll_order(order_id, client, attempt=1, max_attempts=30)
		if attempt > max_attempts
			return EMPromise.reject(RuntimeError.new(
				"TnOptions polling timeout after #{max_attempts} attempts"
			))
		end

		EMPromise.resolve(nil).then do
			order = BandwidthIris::TnOptions.get_tn_option_order(client, order_id)

			error_list = order[:error_list]
			if error_list&.any?
				errors = [error_list].flatten
				msgs = errors.map { |e| e.to_s }.reject(&:empty?).join('; ')
				raise "Dashboard tnOptions errors: #{msgs}"
			end

			warnings = order[:warnings]
			if warnings&.any?
				warns = [warnings].flatten
				descs = warns.map { |w| w.to_s }.reject(&:empty?).join('; ')
				raise "Dashboard tnOptions warnings: #{descs}"
			end

			status = order[:order_status] || order[:processing_status]

			case status&.to_s&.upcase
			when 'COMPLETE', 'PARTIAL'
				true
			when 'FAILED'
				raise "TnOptions order failed with status: #{status}"
			when 'RECEIVED', 'PROCESSING'
				EMPromise.new { |resolve, reject|
					EM.add_timer(2) do
						poll_order(order_id, client, attempt + 1, max_attempts)
							.then { |result| resolve.call(result) }
							.catch { |error| reject.call(error) }
					end
				}
			else
				raise "Unexpected poll status: #{status.inspect}"
			end
		end
	end
end
