1# frozen_string_literal: true
 2
 3require_relative "expiring_lock"
 4
 5class BillPlanCommand
 6	def self.for(customer)
 7		return ForUnregistered.new(customer) unless customer.registered?
 8
 9		unless customer.balance >= customer.monthly_price
10			return ForLowBalance.new(customer)
11		end
12
13		new(customer)
14	end
15
16	def initialize(customer)
17		@customer = customer
18	end
19
20	def reload_customer(db)
21		@customer = Command.execution.customer_repo.with(db: db)
22			.find(customer_id).sync
23	end
24
25	def call
26		ExpiringLock.new("jmp_customer_bill_plan-#{customer_id}").with {
27			@customer.bill_plan(note: note) { |db|
28				reload_customer(db).balance > @customer.monthly_price
29			}
30		}.then do |billed|
31			Command.reply do |reply|
32				reply.note_type = billed ? :info : :error
33				reply.note_text = "#{customer_id}#{billed ? '' : ' not'} billed"
34			end
35		end
36	end
37
38protected
39
40	def note
41		"Renew account plan for #{@customer.registered?.phone}"
42	end
43
44	def customer_id
45		@customer.customer_id
46	end
47
48	class ForLowBalance
49		def initialize(customer)
50			@customer = customer
51		end
52
53		def call
54			LowBalance.for(@customer).then(&:notify!).then do |amount|
55				next command_for(amount).call if amount&.positive?
56
57				notify_failure
58				Command.reply do |reply|
59					reply.note_type = :error
60					reply.note_text = "#{@customer.customer_id} balance is too low"
61				end
62			end
63		end
64
65	protected
66
67		def notify_failure
68			m = Blather::Stanza::Message.new
69			m.from = CONFIG[:notify_from]
70			m.xhtml =
71				"Failed to renew account for #{@customer.registered?.phone}. " \
72				"To keep your number, please " \
73				"<a href='xmpp:cheogram.com?command'>buy more credit soon</a>."
74			m.body = m.xhtml_node.text
75			@customer.stanza_to(m)
76		end
77
78		def command_for(amount)
79			BillPlanCommand.for(
80				@customer.with_balance(@customer.balance + amount)
81			)
82		end
83	end
84
85	class ForUnregistered
86		def initialize(customer)
87			@customer = customer
88		end
89
90		def call
91			Command.reply do |reply|
92				reply.note_type = :error
93				reply.note_text = "#{@customer.customer_id} is not registered"
94			end
95		end
96	end
97end