# frozen_string_literal: true

require "rails_helper"

describe Chat::ChatMessageRateLimiter do
  fab!(:user) { Fabricate(:user, trust_level: 3) }
  let(:limiter) { described_class.new(user) }

  before do
    freeze_time
    RateLimiter.enable
    SiteSetting.chat_allowed_messages_for_trust_level_0 = 1
    SiteSetting.chat_allowed_messages_for_other_trust_levels = 2
    SiteSetting.chat_auto_silence_duration = 30
  end

  after { limiter.clear! }

  it "does nothing when rate limits are not exceeded" do
    limiter.run!
    expect(user.reload.silenced?).to be false
  end

  it "silences the user for the correct amount of time when they exceed the limit" do
    2.times do
      limiter.run!
      expect(user.reload.silenced?).to be false
    end

    expect { limiter.run! }.to raise_error(RateLimiter::LimitExceeded)

    expect(user.reload.silenced?).to be true
    expect(user.silenced_till).to be_within(0.1).of(30.minutes.from_now)
  end

  it "silences the user correctly based on trust level" do
    user.update(trust_level: 0) # Should only be able to run once without hitting limit
    limiter.run!
    expect(user.reload.silenced?).to be false
    expect { limiter.run! }.to raise_error(RateLimiter::LimitExceeded)
    expect(user.reload.silenced?).to be true
  end

  it "doesn't hit limit if site setting for allowed messages equals 0" do
    SiteSetting.chat_allowed_messages_for_other_trust_levels = 0
    5.times do
      limiter.run!
      expect(user.reload.silenced?).to be false
    end
  end

  it "doesn't silence the user even when the limit is broken if auto_silence_duration is set to 0" do
    SiteSetting.chat_allowed_messages_for_other_trust_levels = 1
    SiteSetting.chat_auto_silence_duration = 0
    limiter.run!
    expect(user.reload.silenced?).to be false

    expect { limiter.run! }.to raise_error(RateLimiter::LimitExceeded)
    expect(user.reload.silenced?).to be false
  end

  it "logs a staff action when the user is silenced" do
    SiteSetting.chat_allowed_messages_for_other_trust_levels = 1
    limiter.run!

    expect { limiter.run! }.to raise_error(RateLimiter::LimitExceeded).and change {
            UserHistory.where(
              target_user: user,
              acting_user: Discourse.system_user,
              action: UserHistory.actions[:silence_user],
            ).count
          }.by(1)
  end
end
