class CmAdmin::Models::Filter

def cm_date_and_range_filter(scope_value, records, filters)

def cm_date_and_range_filter(scope_value, records, filters)
  return nil if scope_value.nil?
  scope_value.each do |key, value|
    filters.select { |x| x if [:date, :range].include?(x.filter_type) && x.db_column_name.to_s == key.to_s }.each do |filter|
      next unless value.present?
      value = value.split(' to ')
      from = value[0].presence
      to = value[1].presence
      if filter.filter_with.present?
        records = records.send(filter.filter_with, from, to)
      else
        records = records.where(key => from..to)
      end
    end
  end
  records
end

def cm_dropdown_filter(scope_value, records, filters)

def cm_dropdown_filter(scope_value, records, filters)
  return nil if scope_value.nil?
  scope_value.each do |key, value|
    filters.select { |x| x if [:single_select, :multi_select].include?(x.filter_type) && x.db_column_name.to_s == key.to_s  }.each do |filter|
      if filter.filter_with.present?
        records = records.send(filter.filter_with, value) if value.present?
      else
        records = records.where(key => value) if value.present?
      end
    end
  end
  records
end

def cm_search_filter(scope_value, records, filters)

def cm_search_filter(scope_value, records, filters)
  return nil if scope_value.blank?
  table_name = records.table_name
  filters.select { |x| x if x.filter_type.eql?(:search) }.each do |filter|
    if filter.filter_with.present?
      return records.send(filter.filter_with, scope_value)
    else
      query_variables = []
      filter.db_column_name.each do |col|
        case col
        when Symbol
          query_variables << "#{table_name.pluralize}.#{col}"
        when Hash
          col.map do |key, value|
            value.map { |val| query_variables << "#{key.to_s.pluralize}.#{val}" }
          end
        end
      end
      terms = scope_value.downcase.split(/\s+/)
      terms = terms.map { |e|
        (e.gsub('*', '%').prepend('%') + '%').gsub(/%+/, '%')
      }
      sql = ''
      query_variables.each.with_index do |column, i|
        sql.concat("#{column} ILIKE ?")
        sql.concat(' OR ') unless query_variables.size.eql?(i + 1)
      end
      if filter.db_column_name.map { |x| x.is_a?(Hash) }.include?(true)
        associations_hash = filter.db_column_name.select { |x| x if x.is_a?(Hash) }.last
        records = records.left_joins(associations_hash.keys).distinct
      end
      records = records.where(
        terms.map { |term|
          sql
        }.join(' AND '),
        *terms.map { |e| [e] * query_variables.size }.flatten
      )
      return records
    end
  end
end

def filtered_data(filter_params, records, filters)

def filtered_data(filter_params, records, filters)
  if filter_params
    filter_params.each do |scope_type, scope_value|
      filter_method = case scope_type
                   when 'date', 'range'
                     'date_and_range'
                   when 'single_select', 'multi_select'
                     'dropdown'
                   else
                     scope_type
                   end
      records = send("cm_#{filter_method}_filter", scope_value, records, filters) if scope_value.present?
    end
  end
  records
end

def initialize(db_column_name:, filter_type:, options: {})

def initialize(db_column_name:, filter_type:, options: {})
  raise TypeError, "Can't have array of multiple columns for #{filter_type} filter" if db_column_name.is_a?(Array) && db_column_name.size > 1 && !filter_type.to_sym.eql?(:search)
  raise ArgumentError, "Kindly select a valid filter type like #{VALID_FILTER_TYPES.sort.to_sentence(last_word_connector: ', or ')} instead of #{filter_type} for column #{db_column_name}" unless VALID_FILTER_TYPES.include?(filter_type.to_sym)
  @db_column_name, @filter_type = structure_data(db_column_name, filter_type)
  @filter_with = nil
  set_default_values
  options.each do |key, value|
    send("#{key}=", value)
  end
end

def set_default_values

Else condition is added for fallback.
Date and range filter will not have any placeholder.
Set default placeholder for the filter.
def set_default_values
  placeholder = case filter_type
                when :search
                  'Search'
                when :single_select, :multi_select
                  "Select/search #{humanized_field_value(db_column_name)}"
                else
                  "Enter #{humanized_field_value(db_column_name)}"
                end
  self.placeholder = placeholder
end

def structure_data(db_column_name, filter_type)

def structure_data(db_column_name, filter_type)
  filter_type = filter_type.is_a?(Array) ? filter_type[0].to_sym : filter_type.to_sym
  db_column_name = case filter_type
                   when :search
                     ([] << db_column_name).flatten.map { |x| x.instance_of?(Hash) ? x : x.to_sym }
                   else
                     db_column_name.is_a?(Array) ? db_column_name[0].to_sym : db_column_name.to_sym
                   end
  [db_column_name, filter_type]
end