import logging

from django.db.models import Q
from rest_framework import filters

from django.db.models.fields import CharField, TextField, EmailField, SlugField, URLField, UUIDField

_log = logging.getLogger()


class SearchAllFieldsBackend(filters.BaseFilterBackend):
    """DRF search filter per all fields"""
    def get_search_terms(self, request):
        """
        Search terms are set by a ?search=... query parameter.
        """
        params = request.query_params.get('search', '')
        params = params.replace('\x00', '')  # strip null characters
        return params

    def filter_queryset(self, request, queryset, view):
        def is_type(field):
            checked_types = [CharField, TextField, EmailField, SlugField, URLField, UUIDField]
            for field_type in checked_types:
                if isinstance(field, field_type):
                    return True
            return False

        search = self.get_search_terms(request)
        if not search:
            return queryset

        fields = [field.name for field in queryset.model._meta.fields if is_type(field) and field.choices is None]

        queries = Q()
        for field in fields:
            queries |= Q(**{f'{field}__icontains': search})
        return queryset.filter(queries)
