# Path: tests/factories.py
# class ClientFactory(factory.django.DjangoModelFactory):
#     class Meta:
#         model = 'customers.Client'
# 
#     first_name = factory.faker.Faker('first_name')
#     email = factory.Sequence(lambda n: 'c%d@foo.com' % n)
# 
# class SalesRepFactory(factory.django.DjangoModelFactory):
#     class Meta:
#         model = 'reps.SalesRep'
#         django_get_or_create = ('username',)
# 
#     username = 'user'
#     password = 'test'
#     email = 'jacob@example.com'
#     is_staff = True
#     is_superuser = False
# 
#     @classmethod
#     def _prepare(cls, create, **kwargs):
#         password = kwargs.pop('password', None)
#         user = super()._prepare(create, **kwargs)
#         if password:
#             user.set_password(password)
#             if create:
#                 user.save()
#         return user
# 
# Path: advanced_filters/admin.py
# class AdvancedListFilters(admin.SimpleListFilter):
#     """Allow filtering by stored advanced filters (selection by title)"""
#     title = _('Advanced filters')
# 
#     parameter_name = '_afilter'
# 
#     def lookups(self, request, model_admin):
#         if not model_admin:
#             raise Exception(
#                 "Cannot use AdvancedListFilters without a model_admin"
#             )
#         model_name = (
#             f"{model_admin.model._meta.app_label}."
#             f"{model_admin.model._meta.object_name}"
#         )
#         return AdvancedFilter.objects.filter_by_user(request.user).filter(
#             model=model_name).values_list('id', 'title')
# 
#     def queryset(self, request, queryset):
#         if self.value():
#             filters = AdvancedFilter.objects.filter(id=self.value())
#             advfilter = None
#             if hasattr(filters, 'first'):
#                 advfilter = filters.first()
#             if not advfilter:
#                 logger.error("AdvancedListFilters.queryset: Invalid filter id")
#                 return queryset
#             query = advfilter.query
#             logger.debug(query.__dict__)
#             return queryset.filter(query).distinct()
#         return queryset
# 
# Path: advanced_filters/models.py
# class AdvancedFilter(models.Model):
#     class Meta:
#         verbose_name = _('Advanced Filter')
#         verbose_name_plural = _('Advanced Filters')
# 
#     title = models.CharField(max_length=255, null=False, blank=False, verbose_name=_('Title'))
#     created_by = models.ForeignKey(
#         settings.AUTH_USER_MODEL,
#         related_name='created_advanced_filters',
#         verbose_name=_('Created by'),
#         on_delete=models.CASCADE,
#     )
#     created_at = models.DateTimeField(auto_now_add=True, null=True, verbose_name=_('Created at'))
#     url = models.CharField(max_length=255, null=False, blank=False, verbose_name=_('URL'))
#     users = models.ManyToManyField(settings.AUTH_USER_MODEL, blank=True, verbose_name=_('Users'))
#     groups = models.ManyToManyField('auth.Group', blank=True, verbose_name=_('Groups'))
# 
#     objects = UserLookupManager()
# 
#     b64_query = models.CharField(max_length=2048)
#     model = models.CharField(max_length=64, blank=True, null=True)
# 
#     @property
#     def query(self):
#         """
#         De-serialize, decode and return an ORM query stored in b64_query.
#         """
#         if not self.b64_query:
#             return None
#         s = QSerializer(base64=True)
#         return s.loads(self.b64_query)
# 
#     @query.setter
#     def query(self, value):
#         """
#         Serialize an ORM query, Base-64 encode it and set it to
#         the b64_query field
#         """
#         if not isinstance(value, Q):
#             raise Exception('Must only be passed a Django (Q)uery object')
#         s = QSerializer(base64=True)
#         self.b64_query = s.dumps(value)
# 
#     def list_fields(self):
#         s = QSerializer(base64=True)
#         d = s.loads(self.b64_query, raw=True)
#         return s.get_field_values_list(d)
# 
# Path: advanced_filters/tests/factories.py
# class AdvancedFilterFactory(factory.django.DjangoModelFactory):
#     model = 'customers.Client'
# 
#     class Meta:
#         model = 'advanced_filters.AdvancedFilter'


import pytest
from django.contrib.auth.models import Permission
from django.db.models import Q
from django.urls import reverse
from tests.factories import ClientFactory, SalesRepFactory
from ..admin import AdvancedListFilters
from ..models import AdvancedFilter
from .factories import AdvancedFilterFactory

URL_NAME_CLIENT_CHANGELIST = "admin:customers_client_changelist"


@pytest.fixture
def user(db):
    user = SalesRepFactory()
    user.user_permissions.add(Permission.objects.get(codename="change_client"))
    return user


@pytest.fixture()
def client(client, user):
    client.force_login(user)
    return client


@pytest.fixture
def advanced_filter(user):
    af = AdvancedFilterFactory.build(
        title="Russian speakers", url="foo", model="customers.Client", created_by=user
    )
    af.query = Q(language="ru")
    af.save()
    return af


@pytest.fixture(autouse=True)
def clients(user):
    ClientFactory.create_batch(8, assigned_to=user, language="en")

# Path: tests/factories.py
# class ClientFactory(factory.django.DjangoModelFactory):
#     class Meta:
#         model = 'customers.Client'
# 
#     first_name = factory.faker.Faker('first_name')
#     email = factory.Sequence(lambda n: 'c%d@foo.com' % n)
# 
# class SalesRepFactory(factory.django.DjangoModelFactory):
#     class Meta:
#         model = 'reps.SalesRep'
#         django_get_or_create = ('username',)
# 
#     username = 'user'
#     password = 'test'
#     email = 'jacob@example.com'
#     is_staff = True
#     is_superuser = False
# 
#     @classmethod
#     def _prepare(cls, create, **kwargs):
#         password = kwargs.pop('password', None)
#         user = super()._prepare(create, **kwargs)
#         if password:
#             user.set_password(password)
#             if create:
#                 user.save()
#         return user
# 
# Path: advanced_filters/admin.py
# class AdvancedListFilters(admin.SimpleListFilter):
#     """Allow filtering by stored advanced filters (selection by title)"""
#     title = _('Advanced filters')
# 
#     parameter_name = '_afilter'
# 
#     def lookups(self, request, model_admin):
#         if not model_admin:
#             raise Exception(
#                 "Cannot use AdvancedListFilters without a model_admin"
#             )
#         model_name = (
#             f"{model_admin.model._meta.app_label}."
#             f"{model_admin.model._meta.object_name}"
#         )
#         return AdvancedFilter.objects.filter_by_user(request.user).filter(
#             model=model_name).values_list('id', 'title')
# 
#     def queryset(self, request, queryset):
#         if self.value():
#             filters = AdvancedFilter.objects.filter(id=self.value())
#             advfilter = None
#             if hasattr(filters, 'first'):
#                 advfilter = filters.first()
#             if not advfilter:
#                 logger.error("AdvancedListFilters.queryset: Invalid filter id")
#                 return queryset
#             query = advfilter.query
#             logger.debug(query.__dict__)
#             return queryset.filter(query).distinct()
#         return queryset
# 
# Path: advanced_filters/models.py
# class AdvancedFilter(models.Model):
#     class Meta:
#         verbose_name = _('Advanced Filter')
#         verbose_name_plural = _('Advanced Filters')
# 
#     title = models.CharField(max_length=255, null=False, blank=False, verbose_name=_('Title'))
#     created_by = models.ForeignKey(
#         settings.AUTH_USER_MODEL,
#         related_name='created_advanced_filters',
#         verbose_name=_('Created by'),
#         on_delete=models.CASCADE,
#     )
#     created_at = models.DateTimeField(auto_now_add=True, null=True, verbose_name=_('Created at'))
#     url = models.CharField(max_length=255, null=False, blank=False, verbose_name=_('URL'))
#     users = models.ManyToManyField(settings.AUTH_USER_MODEL, blank=True, verbose_name=_('Users'))
#     groups = models.ManyToManyField('auth.Group', blank=True, verbose_name=_('Groups'))
# 
#     objects = UserLookupManager()
# 
#     b64_query = models.CharField(max_length=2048)
#     model = models.CharField(max_length=64, blank=True, null=True)
# 
#     @property
#     def query(self):
#         """
#         De-serialize, decode and return an ORM query stored in b64_query.
#         """
#         if not self.b64_query:
#             return None
#         s = QSerializer(base64=True)
#         return s.loads(self.b64_query)
# 
#     @query.setter
#     def query(self, value):
#         """
#         Serialize an ORM query, Base-64 encode it and set it to
#         the b64_query field
#         """
#         if not isinstance(value, Q):
#             raise Exception('Must only be passed a Django (Q)uery object')
#         s = QSerializer(base64=True)
#         self.b64_query = s.dumps(value)
# 
#     def list_fields(self):
#         s = QSerializer(base64=True)
#         d = s.loads(self.b64_query, raw=True)
#         return s.get_field_values_list(d)
# 
# Path: advanced_filters/tests/factories.py
# class AdvancedFilterFactory(factory.django.DjangoModelFactory):
#     model = 'customers.Client'
# 
#     class Meta:
#         model = 'advanced_filters.AdvancedFilter'


# Path: advanced_filters/tests/test_usage.py
import pytest
from django.contrib.auth.models import Permission
from django.db.models import Q
from django.urls import reverse
from tests.factories import ClientFactory, SalesRepFactory
from ..admin import AdvancedListFilters
from ..models import AdvancedFilter
from .factories import AdvancedFilterFactory


URL_NAME_CLIENT_CHANGELIST = "admin:customers_client_changelist"


@pytest.fixture
def user(db):
    user = SalesRepFactory()
    user.user_permissions.add(Permission.objects.get(codename="change_client"))
    return user


@pytest.fixture()
def client(client, user):
    client.force_login(user)
    return client


@pytest.fixture
def advanced_filter(user):
    af = AdvancedFilterFactory.build(
        title="Russian speakers", url="foo", model="customers.Client", created_by=user
    )
    af.query = Q(language="ru")
    af.save()
    return af


@pytest.fixture(autouse=True)
def clients(user):
    ClientFactory.create_batch(8, assigned_to=user, language="en")

    ClientFactory.create_batch(2, assigned_to=user, language="ru")