# frozen_string_literal: true
require "value_semantics/monkey_patched"
require_relative "../admin_action"
require_relative "../form_to_h"
class AdminAction
class AddInvites < AdminAction
class Command
using FormToH
def self.for(target_customer, reply:)
EMPromise.resolve(
new(customer_id: target_customer.customer_id)
).then { |x|
reply.call(x.form).then(&x.method(:create))
}
end
def initialize(**bag)
@bag = bag
end
def form
FormTemplate.render("admin_add_invites")
end
def create(result)
AdminAction::AddInvites.for(
**@bag,
**result.form.to_h
.reject { |_k, v| v == "nil" }.transform_keys(&:to_sym)
)
end
end
CodesTaken = Struct.new(:codes) do
def to_s
"One of these tokens already exists: #{codes.join(', ')}"
end
end
CodesClaimed = Struct.new(:codes) do
def to_s
"One of these tokens is already claimed: #{codes.join(', ')}"
end
end
class MustHaveCodes
def to_s
"Action must have list of codes to reverse"
end
end
def customer_id
@attributes[:customer_id]
end
def to_add
@attributes[:to_add].to_i
end
def check_forward
EMPromise.resolve(nil)
.then { check_noop }
.then {
next nil if chosen_invites.empty?
InvitesRepo.new.any_existing?(chosen_invites).then { |taken|
EMPromise.reject(CodesTaken.new(chosen_invites)) if taken
}
}
end
def forward
if chosen_invites.empty?
InvitesRepo.new.create_n_codes(customer_id, to_add).then { |codes|
with(invites: codes.join("\n"))
}
else
InvitesRepo.new.create_codes(customer_id, chosen_invites).then { self }
end
end
def check_reverse
return EMPromise.reject(MustHaveCodes.new) if chosen_invites.empty?
InvitesRepo.new.any_claimed?(chosen_invites).then { |claimed|
EMPromise.reject(CodesClaimed.new(chosen_invites)) if claimed
}
end
def reverse
InvitesRepo.new.delete_codes(chosen_invites).then { self }
end
def to_s
"add_invites(#{customer_id}): #{chosen_invites.join(', ')}"
end
protected
def check_noop
EMPromise.reject(NoOp.new) if to_add.zero?
end
def check_too_many
max = split_invites.length
EMPromise.reject(TooMany.new(to_add, max)) if to_add > max
end
def chosen_invites
@attributes[:invites]&.split("\n") || []
end
end
end