# frozen_string_literal: true

class Chat::ChatMailer
  def self.send_unread_mentions_summary
    return unless SiteSetting.chat_enabled

    users_with_unprocessed_unread_mentions.find_each do |user|
      # user#memberships_with_unread_messages is a nested array that looks like [[membership_id, unread_message_id]]
      # Find the max unread id per membership.
      membership_and_max_unread_mention_ids =
        user
          .memberships_with_unread_messages
          .group_by { |memberships| memberships[0] }
          .transform_values do |membership_and_msg_ids|
            membership_and_msg_ids.max_by { |membership, msg| msg }
          end
          .values

      Jobs.enqueue(
        :user_email,
        type: "chat_summary",
        user_id: user.id,
        force_respect_seen_recently: true,
        memberships_to_update_data: membership_and_max_unread_mention_ids,
      )
    end
  end

  private

  def self.users_with_unprocessed_unread_mentions
    when_away_frequency = UserOption.chat_email_frequencies[:when_away]
    allowed_group_ids = Chat.allowed_group_ids

    users =
      User
        .joins(:user_option)
        .where(user_options: { chat_enabled: true, chat_email_frequency: when_away_frequency })
        .where("users.last_seen_at < ?", 15.minutes.ago)

    if !allowed_group_ids.include?(Group::AUTO_GROUPS[:everyone])
      users = users.joins(:groups).where(groups: { id: allowed_group_ids })
    end

    users
      .select("users.id", "ARRAY_AGG(ARRAY[uccm.id, c_msg.id]) AS memberships_with_unread_messages")
      .joins("INNER JOIN user_chat_channel_memberships uccm ON uccm.user_id = users.id")
      .joins("INNER JOIN chat_channels cc ON cc.id = uccm.chat_channel_id")
      .joins("INNER JOIN chat_messages c_msg ON c_msg.chat_channel_id = uccm.chat_channel_id")
      .joins("LEFT OUTER JOIN chat_mentions c_mentions ON c_mentions.chat_message_id = c_msg.id")
      .where("c_msg.deleted_at IS NULL AND c_msg.user_id <> users.id")
      .where("c_msg.created_at > ?", 1.week.ago)
      .where(<<~SQL)
        (uccm.last_read_message_id IS NULL OR c_msg.id > uccm.last_read_message_id) AND
        (uccm.last_unread_mention_when_emailed_id IS NULL OR c_msg.id > uccm.last_unread_mention_when_emailed_id) AND
        (
          (uccm.user_id = c_mentions.user_id AND uccm.following IS true AND cc.chatable_type = 'Category') OR
          (cc.chatable_type = 'DirectMessage')
        )
      SQL
      .group("users.id, uccm.user_id")
  end
end
