# typed: strict
module BelongsToWithCounterCache
  extend T::Sig
  extend T::Helpers
  extend ActiveSupport::Concern
  abstract!

  requires_ancestor { ActiveRecord::Base }

  class_methods do
    extend T::Sig

    sig do
      params(association_name: Symbol, options: T.untyped).returns(T.untyped)
    end
    def belongs_to_with_counter_cache(association_name, **options)
      T.bind(self, T.class_of(ActiveRecord::Base))
      counter_name_column =
        (
          if options[:counter_cache].is_a?(Symbol)
            options[:counter_cache]
          elsif (inverse_of = options[:inverse_of])
            :"#{inverse_of.to_s.pluralize}_count"
          else
            :"#{self.name&.demodulize&.underscore&.pluralize}_count"
          end
        )

      belongs_to(association_name, counter_cache: true, **options)
      inverse_association_name = options[:inverse_of]
      before_create do
        if target =
             T.cast(
               association(association_name).target,
               T.nilable(ActiveRecord::Base),
             )
          if target.send(counter_name_column).nil?
            target.class.reset_counters(target.id, inverse_association_name)
          end
        end
      end
    end
  end
end
