# frozen_string_literal: true require "value_semantics/monkey_patched" require_relative "tts_template" require_relative "low_balance" class CallAttempt EXPENSIVE_ROUTE = { "usd_beta_unlimited-v20210223" => 0.9, "cad_beta_unlimited-v20210223" => 1.1 }.freeze def self.for(customer, rate, usage, direction:, **kwargs) kwargs.merge!(direction: direction) included_credit = [customer.minute_limit.to_d - usage, 0].max if !rate || rate >= EXPENSIVE_ROUTE.fetch(customer.plan_name, 0.1) Unsupported.new(direction: direction) elsif included_credit + customer.balance < rate * 10 NoBalance.for(customer, rate, usage, **kwargs) else for_ask_or_go(customer, rate, usage, **kwargs) end end def self.for_ask_or_go(customer, rate, usage, digits: nil, **kwargs) can_use = customer.minute_limit.to_d + customer.monthly_overage_limit kwargs.merge!(customer_id: customer.customer_id) if digits != "1" && can_use - usage < rate * 10 AtLimit.new(**kwargs) else new(**kwargs) end end value_semantics do customer_id String from String to(/\A\+\d+\Z/) call_id String direction Either(:inbound, :outbound) end def to_render ["#{direction}/connect", { locals: to_h }] end def create_call(fwd, *args, &block) fwd.create_call(*args, &block) end def as_json(*) { from: from, to: to, customer_id: customer_id } end def to_json(*args) as_json.to_json(*args) end class Unsupported value_semantics do direction Either(:inbound, :outbound) end def view "#{direction}/unsupported" end def tts TTSTemplate.new(view).tts(self) end def to_render [view] end def create_call(*); end def as_json(*) { tts: tts } end def to_json(*args) as_json.to_json(*args) end end class NoBalance def self.for(customer, rate, usage, direction:, **kwargs) LowBalance.for(customer).then(&:notify!).then do |amount| if amount&.positive? CallAttempt.for( customer.with_balance(customer.balance + amount), rate, usage, direction: direction, **kwargs ) else NoBalance.new(balance: customer.balance, direction: direction) end end end value_semantics do balance Numeric direction Either(:inbound, :outbound) end def view "#{direction}/no_balance" end def tts TTSTemplate.new(view).tts(self) end def to_render [view, { locals: to_h }] end def create_call(*); end def as_json(*) { tts: tts } end def to_json(*args) as_json.to_json(*args) end end class AtLimit value_semantics do customer_id String from String to(/\A\+\d+\Z/) call_id String direction Either(:inbound, :outbound) end def view "#{direction}/at_limit" end def tts TTSTemplate.new(view).tts(self) end def to_render [view, { locals: to_h }] end def create_call(fwd, *args, &block) fwd.create_call(*args, &block) end def as_json(*) { tts: tts, from: from, to: to, customer_id: customer_id } end def to_json(*args) as_json.to_json(*args) end end end