class AudienceSegment < ApplicationRecord
  # enum does not like names that start with "not_"
  enum type_of: {
    manual: 0, # never matches anyone, used in test factory
    trusted: 1,
    posted: 2,
    no_posts_yet: 3,
    dark_theme: 4,
    light_theme: 5,
    no_experience: 6,
    experience1: 7,
    experience2: 8,
    experience3: 9,
    experience4: 10,
    experience5: 11
  }

  has_many :segmented_users, dependent: :destroy
  has_many :users, through: :segmented_users
  has_many :emails, dependent: :nullify

  after_validation :persist_recently_active_users, unless: :manual?

  QUERIES = {
    manual: ->(scope = User) { scope.where(id: nil) },
    trusted: ->(scope = User) { scope.with_role(:trusted) },
    no_posts_yet: ->(scope = User) { scope.where(articles_count: 0) },
    posted: ->(scope = User) { scope.where("articles_count > 0") },
    dark_theme: ->(scope = User) { scope.where(id: Users::Setting.dark_theme.select(:user_id)) },
    light_theme: ->(scope = User) { scope.where(id: Users::Setting.light_theme.select(:user_id)) },
    experience1: ->(scope = User) { scope.with_experience_level(1) },
    # see SettingsHelper#user_experience_levels
    experience2: ->(scope = User) { scope.with_experience_level(3) },
    experience3: ->(scope = User) { scope.with_experience_level(5) },
    experience4: ->(scope = User) { scope.with_experience_level(8) },
    experience5: ->(scope = User) { scope.with_experience_level(10) },
    no_experience: ->(scope = User) { scope.with_experience_level(nil) }
  }.freeze

  def self.scoped_users_in_segment(segment_type, scope: nil)
    query_for_segment(segment_type)&.call(scope) || []
  end

  def self.all_users_in_segment(segment_type, scope: User)
    query_for_segment(segment_type)&.call(scope) || []
  end

  def self.recently_active_users_in_segment(segment_type, scope: User.recently_active)
    scoped_users_in_segment(segment_type, scope: scope)
  end

  def self.query_for_segment(segment_type)
    QUERIES[segment_type.to_sym]
  end

  def self.human_readable_description_for(type)
    I18n.t("models.#{model_name.i18n_key}.type_ofs.#{type}")
  end

  def self.including_user_counts
    left_joins(:segmented_users)
      .select("audience_segments.*, COUNT(segmented_users.id) AS user_count")
      .group("audience_segments.id")
  end

  def persist_recently_active_users
    self.users = self.class.recently_active_users_in_segment(type_of)
  end

  def all_users_in_segment
    return users if manual?

    self.class.all_users_in_segment(type_of)
  end

  def includes?(user_or_id)
    user_id = user_or_id.respond_to?(:id) ? user_or_id.id : user_or_id
    all_users_in_segment.exists?(user_id)
  end

  alias refresh! save!
end
