lib/json_api/support/concerns/regular_filters.rb



# frozen_string_literal: true

module JSONAPI
  module Support
    module RegularFilters
      def apply_regular_filters(scope)
        return scope if filter_params.empty?

        regular_filters = filter_params.reject { |k, _v| k.to_s.include?(".") }
        return scope if regular_filters.empty?

        regular_filters.reduce(scope) do |current_scope, (filter_name, filter_value)|
          apply_regular_filter(current_scope, filter_name.to_s, filter_value)
        end
      end

      private

      def apply_regular_filter(scope, filter_name, filter_value)
        return scope if empty_filter_value?(filter_value)

        column_filter = parse_column_filter(filter_name)
        if column_filter
          apply_column_filter(scope, column_filter, filter_value)
        else
          apply_scope_fallback(scope, filter_name, filter_value)
        end
      end

      def apply_column_filter(scope, column_filter, raw_value)
        condition = build_column_condition(column_filter, raw_value)
        condition ? apply_condition(scope, condition) : scope
      rescue StandardError => e
        log_filter_error(column_filter, column_filter[:operator], e)
        scope
      end

      def build_column_condition(column_filter, raw_value)
        column = model_class.column_for_attribute(column_filter[:column])
        return nil unless column

        value = normalize_filter_value_for_model(model_class, column, raw_value)
        return nil if value.nil?

        build_condition(model_class, column, value, column_filter[:operator])
      end

      def log_filter_error(column_filter, operator, error)
        return unless defined?(Rails.logger)

        Rails.logger.warn("Filter error for #{column_filter[:column]}_#{operator}: #{error.class} - #{error.message}")
      end

      def apply_scope_fallback(scope, filter_name, filter_value)
        return scope unless model_class.respond_to?(filter_name.to_sym)

        scope.public_send(filter_name.to_sym, filter_value)
      rescue ArgumentError, NoMethodError
        scope
      end
    end
  end
end