# typed: true
# frozen_string_literal: true

module HasAuxTable
  module Util
    extend T::Sig

    sig do
      params(
        target:
          T.any(
            T.class_of(ActiveRecord::Base),
            T.class_of(ActiveRecord::Relation)
          ),
        method_name: Symbol,
        is_instance_method: T::Boolean,
        hook_block: T.proc.params(args: T.untyped).void
      ).void
    end
    def self.hook_method(target, method_name, is_instance_method, &hook_block)
      define_method =
        is_instance_method ? :define_method : :define_singleton_method

      target_method =
        (
          if is_instance_method
            target.instance_method(method_name)
          else
            target.method(method_name)
          end
        )

      target.send(define_method, method_name) do |*args, **kwargs, &block|
        method = is_instance_method ? target_method.bind(self) : target_method
        T.unsafe(hook_block).call(method, *args, **kwargs, &block)
      end
    end

    sig do
      params(aux_config: HasAuxTable::AuxTableConfig).returns(T::Array[String])
    end
    def self.attributes_for_inspect(aux_config)
      main_class = aux_config.main.klass

      main_class_attributes =
        if main_class.attributes_for_inspect == :all
          main_class.attribute_names
        else
          main_class.attributes_for_inspect
        end

      main_class_attributes
    end

    sig do
      type_parameters(:T)
        .params(
          instance: T.all(T.type_parameter(:T), Object),
          klass: T::Class[T.type_parameter(:T)]
        )
        .void
    end
    def self.ensure_is_instance_of!(instance, klass)
      unless instance.class <= klass
        Kernel.raise("#{instance.class.name} not a #{klass.name}")
      end
    end
  end
end
