class Group < ApplicationRecord
  has_many :user_groups, dependent: :destroy
  has_many :users, through: :user_groups
  has_many :application_groups, dependent: :destroy
  has_many :applications, through: :application_groups

  # Reserved OIDC claim names that should not be overridden
  RESERVED_CLAIMS = %w[
    iss sub aud exp iat nbf jti nonce azp
    email email_verified preferred_username name
    groups
  ].freeze

  validates :name, presence: true, uniqueness: {case_sensitive: false}
  normalizes :name, with: ->(name) { name.strip.downcase }
  validate :no_reserved_claim_names

  scope :auto_assign, -> { where(auto_assign: true) }
  scope :admin, -> { where(admin: true) }

  before_destroy :ensure_other_admin_group_exists

  # Parse custom_claims JSON field
  def parsed_custom_claims
    return {} if custom_claims.blank?
    custom_claims.is_a?(Hash) ? custom_claims : {}
  end

  private

  def ensure_other_admin_group_exists
    return unless admin?
    return if Group.where(admin: true).where.not(id: id).exists?
    errors.add(:base, "cannot delete the last administrators group")
    throw :abort
  end

  def no_reserved_claim_names
    return if custom_claims.blank?

    reserved_used = parsed_custom_claims.keys.map(&:to_s) & RESERVED_CLAIMS
    if reserved_used.any?
      errors.add(:custom_claims, "cannot override reserved OIDC claims: #{reserved_used.join(", ")}")
    end
  end
end
