module ActiveRecord::Enum

def self.extended(base) # :nodoc:

:nodoc:
def self.extended(base) # :nodoc:
  base.class_attribute(:defined_enums, instance_writer: false, default: {})
end

def _enum(name, values, prefix: nil, suffix: nil, scopes: true, **options)

def _enum(name, values, prefix: nil, suffix: nil, scopes: true, **options)
  assert_valid_enum_definition_values(values)
  # statuses = { }
  enum_values = ActiveSupport::HashWithIndifferentAccess.new
  name = name.to_s
  # def self.statuses() statuses end
  detect_enum_conflict!(name, name.pluralize, true)
  singleton_class.define_method(name.pluralize) { enum_values }
  defined_enums[name] = enum_values
  detect_enum_conflict!(name, name)
  detect_enum_conflict!(name, "#{name}=")
  attribute(name, **options) do |subtype|
    subtype = subtype.subtype if EnumType === subtype
    EnumType.new(name, enum_values, subtype)
  end
  value_method_names = []
  _enum_methods_module.module_eval do
    prefix = if prefix
      prefix == true ? "#{name}_" : "#{prefix}_"
    end
    suffix = if suffix
      suffix == true ? "_#{name}" : "_#{suffix}"
    end
    pairs = values.respond_to?(:each_pair) ? values.each_pair : values.each_with_index
    pairs.each do |label, value|
      enum_values[label] = value
      label = label.to_s
      value_method_name = "#{prefix}#{label}#{suffix}"
      value_method_names << value_method_name
      define_enum_methods(name, value_method_name, value, scopes)
      method_friendly_label = label.gsub(/[\W&&[:ascii:]]+/, "_")
      value_method_alias = "#{prefix}#{method_friendly_label}#{suffix}"
      if value_method_alias != value_method_name && !value_method_names.include?(value_method_alias)
        value_method_names << value_method_alias
        define_enum_methods(name, value_method_alias, value, scopes)
      end
    end
  end
  detect_negative_enum_conditions!(value_method_names) if scopes
  enum_values.freeze
end

def _enum_methods_module

def _enum_methods_module
  @_enum_methods_module ||= begin
    mod = EnumMethods.new(self)
    include mod
    mod
  end
end

def assert_valid_enum_definition_values(values)

def assert_valid_enum_definition_values(values)
  unless values.is_a?(Hash) || values.all?(Symbol) || values.all?(String)
    error_message = <<~MSG
      Enum values #{values} must be either a hash, an array of symbols, or an array of strings.
    MSG
    raise ArgumentError, error_message
  end
  if values.is_a?(Hash) && values.keys.any?(&:blank?) || values.is_a?(Array) && values.any?(&:blank?)
    raise ArgumentError, "Enum label name must not be blank."
  end
end

def detect_enum_conflict!(enum_name, method_name, klass_method = false)

def detect_enum_conflict!(enum_name, method_name, klass_method = false)
  if klass_method && dangerous_class_method?(method_name)
    raise_conflict_error(enum_name, method_name, type: "class")
  elsif klass_method && method_defined_within?(method_name, Relation)
    raise_conflict_error(enum_name, method_name, type: "class", source: Relation.name)
  elsif !klass_method && dangerous_attribute_method?(method_name)
    raise_conflict_error(enum_name, method_name)
  elsif !klass_method && method_defined_within?(method_name, _enum_methods_module, Module)
    raise_conflict_error(enum_name, method_name, source: "another enum")
  end
end

def detect_negative_enum_conditions!(method_names)

def detect_negative_enum_conditions!(method_names)
  return unless logger
  method_names.select { |m| m.start_with?("not_") }.each do |potential_not|
    inverted_form = potential_not.sub("not_", "")
    if method_names.include?(inverted_form)
      logger.warn "Enum element '#{potential_not}' in #{self.name} uses the prefix 'not_'." \
        " This has caused a conflict with auto generated negative scopes." \
        " Avoid using enum elements starting with 'not' where the positive form is also an element."
    end
  end
end

def enum(name = nil, values = nil, **options)

def enum(name = nil, values = nil, **options)
  if name
    values, options = options, {} unless values
    return _enum(name, values, **options)
  end
  definitions = options.slice!(:_prefix, :_suffix, :_scopes, :_default)
  options.transform_keys! { |key| :"#{key[1..-1]}" }
  definitions.each { |name, values| _enum(name, values, **options) }
end

def inherited(base) # :nodoc:

:nodoc:
def inherited(base) # :nodoc:
  base.defined_enums = defined_enums.deep_dup
  super
end

def raise_conflict_error(enum_name, method_name, type: "instance", source: "Active Record")

def raise_conflict_error(enum_name, method_name, type: "instance", source: "Active Record")
  raise ArgumentError, ENUM_CONFLICT_MESSAGE % {
    enum: enum_name,
    klass: name,
    type: type,
    method: method_name,
    source: source
  }
end