class PostDisapproval < ApplicationRecord
  DELETION_THRESHOLD = 1.month
  REASONS = %w[breaks_rules poor_quality disinterest]

  belongs_to :post
  belongs_to :user
  validates :user, uniqueness: { scope: :post, message: "have already hidden this post" }
  validates :reason, inclusion: { in: REASONS }
  validate :validate_disapproval

  scope :with_message, -> { where.not(message: nil) }
  scope :without_message, -> { where(message: nil) }
  scope :breaks_rules, -> {where(:reason => "breaks_rules")}
  scope :poor_quality, -> {where(:reason => "poor_quality")}
  scope :disinterest, -> {where(:reason => "disinterest")}

  def self.prune!
    PostDisapproval.where("post_id in (select _.post_id from post_disapprovals _ where _.created_at < ?)", DELETION_THRESHOLD.ago).delete_all
  end

  concerning :SearchMethods do
    class_methods do
      def creator_matches(creator, searcher)
        return none if creator.nil?

        policy = Pundit.policy!(searcher, PostDisapproval.new(user: creator))

        if policy.can_view_creator?
          where(user: creator)
        else
          none
        end
      end

      def search(params)
        q = search_attributes(params, :id, :created_at, :updated_at, :message, :reason, :post)
        q = q.text_attribute_matches(:message, params[:message_matches])

        q = q.with_message if params[:has_message].to_s.truthy?
        q = q.without_message if params[:has_message].to_s.falsy?

        if params[:user_id].present?
          user = User.find(params[:user_id])
          q = q.creator_matches(user, CurrentUser.user)
        elsif params[:user_name].present?
          user = User.find_by_name(params[:user_name])
          q = q.creator_matches(user, CurrentUser.user)
        end

        case params[:order]
        when "post_id", "post_id_desc"
          q = q.order(post_id: :desc, id: :desc)
        else
          q = q.apply_default_order(params)
        end

        q
      end
    end
  end

  def self.available_includes
    [:user, :post]
  end

  def validate_disapproval
    if post.is_active?
      errors.add(:post, "is already active and cannot be disapproved")
    end
  end

  def message=(message)
    message = nil if message.blank?
    super(message)
  end
end
