# frozen_string_literal: true

# GroupMessage sends a private message to a group.
# It will also avoid sending the same message repeatedly, which can happen with
# notifications to moderators when spam is detected.
#
# Options:
#
#   user: (User) If the message is about a user, pass the user object.
#   limit_once_per: (seconds) Limit sending the given type of message once every X seconds.
#                   The default is 24 hours. Set to false to always send the message.

class GroupMessage
  include Rails.application.routes.url_helpers

  RECENT_MESSAGE_PERIOD = 3.months

  def self.create(group_name, message_type, opts = {})
    GroupMessage.new(group_name, message_type, opts).create
  end

  def initialize(group_name, message_type, opts = {})
    @group_name = group_name
    @message_type = message_type
    @opts = opts
  end

  def create
    return false if sent_recently?

    post =
      PostCreator.create(
        Discourse.system_user,
        target_group_names: [@group_name],
        archetype: Archetype.private_message,
        subtype: TopicSubtype.system_message,
        title: I18n.t("system_messages.#{@message_type}.subject_template", message_params),
        raw: I18n.t("system_messages.#{@message_type}.text_body_template", message_params),
      )
    remember_message_sent
    post
  end

  def delete_previous!(respect_sent_recently: true, match_raw: true)
    return false if respect_sent_recently && sent_recently?

    posts =
      Post
        .joins(topic: { topic_allowed_groups: :group })
        .where(
          topic: {
            posts_count: 1,
            user_id: Discourse.system_user,
            archetype: Archetype.private_message,
            subtype: TopicSubtype.system_message,
            title: I18n.t("system_messages.#{@message_type}.subject_template", message_params),
            topic_allowed_groups: {
              groups: {
                name: @group_name,
              },
            },
          },
        )
        .where("posts.created_at > ?", RECENT_MESSAGE_PERIOD.ago)

    if match_raw
      posts =
        posts.where(
          raw: I18n.t("system_messages.#{@message_type}.text_body_template", message_params).rstrip,
        )
    end

    posts.find_each { |post| PostDestroyer.new(Discourse.system_user, post).destroy }
  end

  def message_params
    @message_params ||=
      begin
        h = { base_url: Discourse.base_url }.merge(@opts[:message_params] || {})
        if @opts[:user]
          h.merge!(
            username: @opts[:user].username,
            user_url: user_path(@opts[:user].encoded_username(lower: true)),
          )
        end
        h
      end
  end

  def sent_recently?
    return false if @opts[:limit_once_per] == false
    Discourse.redis.get(sent_recently_key).present?
  end

  # default is to send no more than once every 24 hours (24 * 60 * 60 = 86,400 seconds)
  def remember_message_sent
    unless @opts[:limit_once_per] == false
      Discourse.redis.setex(sent_recently_key, @opts[:limit_once_per].try(:to_i) || 86_400, 1)
    end
  end

  def sent_recently_key
    "grpmsg:#{@group_name}:#{@message_type}:#{@opts[:user] ? @opts[:user].username : ""}"
  end
end