# frozen_string_literal: true

class PostMerger
  class CannotMergeError < StandardError
  end

  def initialize(user, posts)
    @user = user
    @posts = posts
  end

  def merge
    return if @posts.count < 2

    ensure_same_topic!
    ensure_same_user!

    guardian = Guardian.new(@user)
    ensure_can_merge!(guardian)

    posts =
      @posts.sort_by do |post|
        guardian.ensure_can_delete!(post)
        post.post_number
      end

    post_content = posts.map(&:raw)
    post = posts.pop

    merged_post_raw = post_content.join("\n\n")
    changes = {
      raw: merged_post_raw,
      edit_reason: I18n.t("merge_posts.edit_reason", count: posts.length, username: @user.username),
    }

    ensure_max_post_length!(merged_post_raw)
    PostRevisor
      .new(post, post.topic)
      .revise!(@user, changes) { posts.each { |p| PostDestroyer.new(@user, p).destroy } }
  end

  private

  def ensure_same_topic!
    if @posts.map(&:topic_id).uniq.size != 1
      raise CannotMergeError.new(I18n.t("merge_posts.errors.different_topics"))
    end
  end

  def ensure_same_user!
    if @posts.map(&:user_id).uniq.size != 1
      raise CannotMergeError.new(I18n.t("merge_posts.errors.different_users"))
    end
  end

  def ensure_can_merge!(guardian)
    raise Discourse::InvalidAccess unless guardian.can_moderate_topic?(@posts[0].topic)
  end

  def ensure_max_post_length!(raw)
    value = StrippedLengthValidator.get_sanitized_value(raw)
    if value.size > SiteSetting.max_post_length
      raise CannotMergeError.new(I18n.t("merge_posts.errors.max_post_length"))
    end
  end
end