# typed: strict
class Domain::UserPostFav < ReduxApplicationRecord
  extend T::Sig
  extend T::Helpers

  include AttrJsonRecordAliases
  include BelongsToWithCounterCache

  self.table_name = "domain_user_post_favs"
  self.primary_key = %i[user_id post_id]

  belongs_to_with_counter_cache :user,
                                class_name: "Domain::User",
                                inverse_of: :user_post_favs,
                                counter_cache: :user_post_favs_count

  belongs_to :post, class_name: "Domain::Post", inverse_of: :user_post_favs

  scope :for_post_type,
        ->(post_klass) do
          post_klass = T.cast(post_klass, T.class_of(Domain::Post))
          joins(:post).where(post: { type: post_klass.name })
        end

  class FavedAtType < T::Enum
    enums do
      # Using the posted_at as a fallback
      PostedAt = new("posted_at")
      # Using an explicitly set time
      Explicit = new("explicit")
      # Using the inferred time from the regression model
      Inferred = new("inferred")
      # Using the inferred time, which was computed on the fly
      InferredNow = new("inferred_now")
    end
  end

  class FavedAt < T::ImmutableStruct
    include T::Struct::ActsAsComparable

    const :time, T.nilable(Time)
    const :type, FavedAtType
  end

  sig { overridable.returns(T.nilable(FavedAt)) }
  def faved_at
    FavedAt.new(time: post&.posted_at&.to_time, type: FavedAtType::PostedAt)
  end
end
