import django_filters
from django.db.models import Q
from collections import OrderedDict


from django.contrib.auth.models import User

from generic.models import CidUser, Examination, Supervisor, UserGrades


class CidUserFilter(django_filters.FilterSet):
    active = django_filters.BooleanFilter(
        field_name="active", label="CID active", initial=True
    )

    class Meta:
        model = CidUser
        # fields = ("cid", "active", "internal_candidate", "group")
        fields = {
            "cid": ["contains"],
            "active": ["exact"],
            "internal_candidate": ["exact"],
            "group": ["exact"],
            "group__name": ["contains"],
            "email": ["contains"],
        }

    @property
    def qs(self):
        parent = super().qs

        # filter_active = getattr(self.request, 'active', True)
        if "active" not in self.request.GET:
            return parent.filter(active=True)

        return parent

class UserUserFilter(django_filters.FilterSet):
    # Generic search across name and email/username
    q = django_filters.CharFilter(method='filter_search', label='Search')
    userprofile__grade = django_filters.ModelChoiceFilter(queryset=UserGrades.objects.all(),label="Grade")
    userprofile__supervisor = django_filters.ModelChoiceFilter(queryset=Supervisor.objects.all(), label="Supervisor")
    userprofile__peninsula_trainee = django_filters.BooleanFilter(label="Peninsula Trainee")
    #has_supervisor = django_filters.BooleanFilter(field_name='supervisor', lookup_expr='isnull', exclude=True, label="Has Supervisor")

    class Meta:
        model = User
        # fields = ("cid", "active", "internal_candidate", "group")
        fields = {
            "first_name": ["icontains"],
            "last_name": ["icontains"],
            #"active": ["exact"],
            "user_groups": ["exact"],
            "user_groups__name": ["icontains"],
            #"userprofile__grade": ["exact"],
            #"userprofile__supervisor": ["exact"],
            "email": ["icontains"],
            "is_active": ["exact"],
            "groups": ["exact"],
        }

    @property
    def qs(self):
        parent = super().qs

        ## filter_active = getattr(self.request, 'active', True)
        if "is_active" not in self.request.GET:
            return parent.filter(is_active=True)

        return parent

    def __init__(self, *args, **kwargs):
        super(UserUserFilter, self).__init__(*args, **kwargs)
        self.form.initial['is_active'] = True

    def filter_search(self, queryset, name, value):
        """
        Generic search that matches first name, last name, email or username.
        """
        v = (value or "").strip()
        if not v:
            return queryset

        return queryset.filter(
            Q(first_name__icontains=v)
            | Q(last_name__icontains=v)
            | Q(email__icontains=v)
            | Q(username__icontains=v)
        )

    def __post_init_reorder__(self):
        """Internal helper to move the generic search 'q' to the front of the form fields."""
        try:
            fields = self.form.fields
            if 'q' in fields:
                new_order = ['q'] + [k for k in fields.keys() if k != 'q']
                self.form.fields = OrderedDict((k, fields[k]) for k in new_order)
        except Exception:
            pass

    # Ensure reorder runs after initialization
    def __new__(cls, *args, **kwargs):
        instance = super(UserUserFilter, cls).__new__(cls)
        # attach a post-init hook to reorder form fields
        orig_init = instance.__init__

        def wrapped_init(*a, **k):
            orig_init(*a, **k)
            try:
                instance.__post_init_reorder__()
            except Exception:
                pass

        instance.__init__ = wrapped_init
        return instance


class ExaminationFilter(django_filters.FilterSet):
    class Meta:
        model = Examination
        fields = {"examination": ["icontains"], "modality": ["exact"]}

    def __init__(
        self,
        data=None,
        queryset=None,
        prefix=None,
        strict=None,
        user=None,
        request=None,
    ):
        super(ExaminationFilter, self).__init__(
            data=data, queryset=queryset, prefix=prefix, request=request
        )
        pass

class SupervisorFilter(django_filters.FilterSet):
    class Meta:
        model = Supervisor
        fields = {
            "name": ["icontains"],
            "email": ["icontains"],
            "active": ["exact"],
            "site": ["exact"],
        }

    @property
    def qs(self):
        parent = super().qs

        if "active" not in self.request.GET:
            return parent.filter(active=True)

        return parent


    def __init__(
        self,
        data=None,
        queryset=None,
        prefix=None,
        strict=None,
        user=None,
        request=None,
    ):
        super(SupervisorFilter, self).__init__(
            data=data, queryset=queryset, prefix=prefix, request=request
        )
        pass