# frozen_string_literal: true

require "value_semantics/monkey_patched"
require_relative "../admin_action"
require_relative "../form_to_h"

class AdminAction
	class NumberChange < AdminAction
		include Isomorphic
		class Command
			using FormToH

			def self.for(target_customer, reply:)
				EMPromise.resolve(
					new(
						customer_id: target_customer.customer_id,
						old_tel: target_customer.registered?.phone
					)
				).then { |x|
					reply.call(x.form).then(&x.method(:change))
				}
			end

			def initialize(**bag)
				@bag = bag
			end

			def form
				FormTemplate.render("admin_number_change")
			end

			def change(result)
				AdminAction::NumberChange.for(
					**@bag,
					**result.form.to_h
						.reject { |_k, v| v == "nil" }.transform_keys(&:to_sym)
				)
			end
		end

		NilKey = Struct.new(:key) {
			def to_s
			 "Expected a key with a value, but #{key} has no value."
			end
		}

		def customer_id
			@attributes[:customer_id]
		end

		def old_tel
			@attributes[:old_tel]
		end

		def new_tel
			@attributes[:new_tel]
		end

		def check_forward
			EMPromise.all([
				check_noop,
				check_exist
			])
		end

		def forward
			sgx = TrivialBackendSgxRepo.new.get(customer_id)
			EMPromise.all([
				REDIS.rename("catapult_fwd-#{old_tel}", "catapult_fwd-#{new_tel}"),
				sgx.register!(new_tel)
			]).then { self }
		end

		def to_reverse
			with(
			 old_tel: new_tel,
			 new_tel: old_tel
			)
		end

		def to_s
			"number_change(#{customer_id}): #{old_tel} -> #{new_tel}"
		end

	protected

		def check_noop
		 EMPromise.reject(NoOp.new) if new_tel == old_tel
		end

		def check_exist
			cat_jid = "catapult_jid-#{old_tel}"
			REDIS.exists(cat_jid).then { |v|
				EMPromise.reject(NilKey.new(cat_jid)) unless v == 1
			}
		end
	end
end
