# frozen_string_literal: true require "bigdecimal" require "forwardable" require "relative_time" require "value_semantics/monkey_patched" require_relative "api" require_relative "call_attempt_repo" require_relative "customer" require_relative "customer_plan" require_relative "form_template" require_relative "promise_hash" require_relative "proxied_jid" class PlanInfo extend Forwardable def_delegators :customer, :expires_at, :auto_top_up_amount def self.for(customer) return EMPromise.resolve(NoPlan.new) unless customer&.plan_name PromiseHash.all( customer: customer, start_date: customer.activation_date, calling_charges_this_month: customer.calling_charges_this_month ).then(method(:new)) end class NoPlan def template FormTemplate.new("") end def admin_template FormTemplate.new("") end def status "Transitional" end end value_semantics do method_missing :customer, Customer start_date Time calling_charges_this_month BigDecimal end def template FormTemplate.for("plan_info", plan_info: self) end def admin_template FormTemplate.for("admin_plan_info", plan_info: self) end def monthly_price "$%.4f / month" % customer.monthly_price end def relative_start_date RelativeTime.in_words(start_date) end def formatted_start_date start_date.strftime("%Y-%m-%d %H:%M:%S") end def currency (customer.currency || "No Currency").to_s end def status customer.active? ? "Active" : "Expired" end def remaining_included_calling_credit [customer.minute_limit.to_d - calling_charges_this_month, 0].max end end class CustomerInfo value_semantics do plan_info Either(PlanInfo, PlanInfo::NoPlan) tel Either(String, nil) balance BigDecimal cnam Either(String, nil) end def self.for(customer) PromiseHash.all( plan_info: PlanInfo.for(customer), tel: customer.registered? ? customer.registered?.phone : nil, balance: customer.balance, cnam: customer.tndetails.dig(:features, :lidb, :subscriber_information) ).then(&method(:new)) end def form FormTemplate.render("customer_info", info: self) end end class AdminInfo value_semantics do jid ProxiedJID, coerce: ProxiedJID.method(:new) customer_id String fwd Either(CustomerFwd, nil) info CustomerInfo api API call_info String trust_level String end def self.for( customer, trust_level_repo: TrustLevelRepo.new, call_attempt_repo: CallAttemptRepo.new ) PromiseHash.all( jid: customer.jid, customer_id: customer.customer_id, fwd: customer.fwd, info: CustomerInfo.for(customer), api: API.for(customer), call_info: call_info(customer, call_attempt_repo), trust_level: trust_level_repo.find(customer).then(&:to_s) ).then(&method(:new)) end class FakeLowBalance def self.for(_) self end def self.notify! EMPromise.resolve(0) end end def self.call_info(customer, call_attempt_repo) if customer.registered? call_attempt_repo .find_outbound(customer, "+1", call_id: "dry_run") .then(&:to_s) else EMPromise.resolve("No calling") end end def form FormTemplate.render("admin_info", admin_info: self) end def tel_link [ "https://dashboard.bandwidth.com/portal/r/a", CONFIG[:creds][:account], "numbers/details", info.tel.gsub(/\A\+1/, "") ].join("/") end end