# frozen_string_literal: true

class Subscription < ApplicationRecord
  belongs_to :user
  belongs_to :answer

  class << self
    def subscribe(recipient, target)
      existing = Subscription.find_by(user: recipient, answer: target)
      return true if existing.present?

      Subscription.create!(user: recipient, answer: target)
    end

    def unsubscribe(recipient, target)
      return nil if recipient.nil? || target.nil?

      subs = Subscription.find_by(user: recipient, answer: target)
      subs&.destroy
    end

    def destruct(target)
      return nil if target.nil?

      Subscription.where(answer: target).destroy_all
    end

    def notify(source, target)
      return nil if source.nil? || target.nil?

      # As we will need to notify for each person subscribed,
      # it's much faster to bulk insert than to use +Notification.notify+
      notifications = Subscription.for(source, target).pluck(:user_id).map do |recipient_id|
        {
          target_id:    source.id,
          target_type:  Comment,
          recipient_id:,
          new:          true,
          type:         Notification::Commented,
          created_at:   source.created_at,
          updated_at:   source.created_at,
        }
      end

      return if notifications.empty?

      # rubocop:disable Rails/SkipsModelValidations
      Notification.insert_all!(notifications)
      User.where(id: notifications.pluck(:recipient_id)).touch_all(:notifications_updated_at)
      # rubocop:enable Rails/SkipsModelValidations
    end

    def denotify(source, target)
      return nil if source.nil? || target.nil?

      subs = Subscription.where(answer: target)
      Notification.where(target:, recipient: subs.map(&:user)).delete_all
    end

    def for(source, target)
      muted_by = Relationships::Mute.where(target: source.user).pluck(&:source_id)

      Subscription.where(answer: target)
                  .where.not(user: source.user)
                  .where.not(user_id: muted_by)
    end
  end
end