# typed: true
# frozen_string_literal: true

module HasAuxTable
  module RelationExtensions
    extend T::Sig
    Util = HasAuxTable::Util

    sig { params(aux_config: AuxTableConfig).void }
    def setup_relation_extensions!(aux_config)
      setup_main_class_extensions!(aux_config)
    end

    sig { params(aux_config: AuxTableConfig).void }
    def setup_main_class_extensions!(aux_config)
      main_class = aux_config.main_class

      Util.hook_method(main_class, :where, false) do |original, *args|
        if args.length == 1 && args.first.is_a?(Hash)
          opts_remapped = aux_config.remap_conditions(args.first)
          original.call(opts_remapped)
        else
          original.call(*args)
        end
      end

      Util.hook_method(
        main_class,
        :all,
        false
      ) do |original, *args, **kwargs, &block|
        original.call(*args, **kwargs, &block).eager_load(
          aux_config.aux_association_name
        )
      end

      Util.hook_method(
        main_class,
        :unscoped,
        false
      ) do |original, *args, **kwargs|
        original.call(*args, **kwargs).eager_load(
          aux_config.aux_association_name
        )
      end

      relation_class =
        main_class.relation_delegate_class(ActiveRecord::Relation)

      Util.hook_method(relation_class, :where!, true) do |original, opts, *rest|
        if opts.is_a?(Hash)
          opts_remapped = aux_config.remap_conditions(opts)
          T.unsafe(original).call(opts_remapped, *rest)
        else
          T.unsafe(original).call(opts, *rest)
        end
      end

      Util.hook_method(
        relation_class,
        :bind_attribute,
        true
      ) do |original, name, value, &block|
        if aux_config.is_aux_column?(name)
          aux_config.aux_bind_attribute(name, value, &block)
        else
          original.call(name, value, &block)
        end
      end
    end
  end
end
