#  Copyright (c) 2012-2024, Jungwacht Blauring Schweiz. This file is part of
#  hitobito and licensed under the Affero General Public License version 3
#  or later. See the COPYING file at the top-level directory or at
#  https://github.com/hitobito/hitobito.

module Event::Participatable
  def refresh_participant_counts!
    update_column(:teamer_count, distinct_count(teamers_scope))
    update_column(:participant_count, distinct_count(participants_scope))
    update_column(:applicant_count, distinct_count(applicants_scope))
  end

  def participations_for(*role_types)
    participations_for = participations.active
      .joins(:roles)
      .where(event_roles: {type: role_types.map(&:sti_name)})
      .order_by_role(self)
      .select(Event::Participation.column_names)

    Event::Participation::PreloadParticipations.preload(participations_for, [:participant, :event])

    participations_for
  end

  def active_participations_without_affiliate_types
    affiliate_types = role_types.reject(&:kind).collect(&:sti_name)
    exclude_affiliate_types = affiliate_types.present? &&
      ["event_roles.type NOT IN (?)", affiliate_types]

    participations.active
      .joins(:roles)
      .where(exclude_affiliate_types)
  end

  # gets a list of all user defined participation role labels for this event
  def participation_role_labels
    @participation_role_labels ||=
      Event::Role.joins(:participation)
        .where(event_participations: {event_id: id})
        .where("event_roles.label <> ''")
        .distinct.order(:label)
        .pluck(:label)
  end

  # All assigned participations (no leaders/teamers)
  def participants_scope
    participations.active
      .joins(:roles)
      .where(event_roles: {type: participant_types.collect(&:sti_name)})
  end

  private

  # All members of the leading team (non-participants)
  def teamers_scope
    active_participations_without_affiliate_types
      .where.not(event_roles: {type: participant_types.collect(&:sti_name)})
  end

  # Assigned participations (all prios, no leaders/teamers) and unassigned with prio 1
  def applicants_scope
    participations
      .joins("LEFT JOIN event_roles ON event_participations.id = event_roles.participation_id")
      .where("event_roles.participation_id IS NULL OR event_roles.type IN (?)",
        participant_types.collect(&:sti_name))
  end

  def distinct_count(scope)
    scope.distinct.count
  end
end
