from ldap3 import Connection
from django.shortcuts import render
from django.http import Http404
from django.db.models import Q
from django.conf import settings

from gestioncof.models import User
from kfet.decorators import teamkfet_required
from kfet.models import Account


class Clipper(object):
    def __init__(self, clipper, fullname):
        if fullname is None:
            fullname = ""
        assert isinstance(clipper, str)
        assert isinstance(fullname, str)
        self.clipper = clipper
        self.fullname = fullname


@teamkfet_required
def account_create(request):
    if "q" not in request.GET:
        raise Http404
    q = request.GET.get("q")

    if (len(q) == 0):
        return render(request, "kfet/account_create_autocomplete.html")

    data = {'q': q}

    queries = {}
    search_words = q.split()

    # Fetching data from User, CofProfile and Account tables
    queries['kfet'] = Account.objects
    queries['users_cof'] = User.objects.filter(profile__is_cof=True)
    queries['users_notcof'] = User.objects.filter(profile__is_cof=False)

    for word in search_words:
        queries['kfet'] = queries['kfet'].filter(
            Q(cofprofile__user__username__icontains=word)
            | Q(cofprofile__user__first_name__icontains=word)
            | Q(cofprofile__user__last_name__icontains=word)
        )
        queries['users_cof'] = queries['users_cof'].filter(
            Q(username__icontains=word)
            | Q(first_name__icontains=word)
            | Q(last_name__icontains=word)
        )
        queries['users_notcof'] = queries['users_notcof'].filter(
            Q(username__icontains=word)
            | Q(first_name__icontains=word)
            | Q(last_name__icontains=word)
        )

    # Clearing redundancies
    queries['kfet'] = queries['kfet'].distinct()
    usernames = set(
        queries['kfet'].values_list('cofprofile__user__username', flat=True))
    queries['kfet'] = [
        (account, account.cofprofile.user)
        for account in queries['kfet']
    ]

    queries['users_cof'] = \
        queries['users_cof'].exclude(username__in=usernames).distinct()
    queries['users_notcof'] = \
        queries['users_notcof'].exclude(username__in=usernames).distinct()
    usernames |= set(
        queries['users_cof'].values_list('username', flat=True))
    usernames |= set(
        queries['users_notcof'].values_list('username', flat=True))

    # Fetching data from the SPI
    if getattr(settings, 'LDAP_SERVER_URL', None):
        # Fetching
        ldap_query = '(&{:s})'.format(''.join(
            '(|(cn=*{bit:s}*)(uid=*{bit:s}*))'.format(bit=word)
            for word in search_words if word.isalnum()
        ))
        if ldap_query != "(&)":
            # If none of the bits were legal, we do not perform the query
            entries = None
            with Connection(settings.LDAP_SERVER_URL) as conn:
                conn.search(
                    'dc=spi,dc=ens,dc=fr', ldap_query,
                    attributes=['uid', 'cn']
                )
                entries = conn.entries
            # Clearing redundancies
            queries['clippers'] = [
                Clipper(entry.uid.value, entry.cn.value)
                for entry in entries
                if entry.uid.value
                and entry.uid.value not in usernames
            ]

    # Resulting data
    data.update(queries)
    data['options'] = sum([len(query) for query in queries])

    return render(request, "kfet/account_create_autocomplete.html", data)


@teamkfet_required
def account_search(request):
    if "q" not in request.GET:
        raise Http404
    q = request.GET.get("q")
    words = q.split()

    data = {'q': q}

    for word in words:
        query = Account.objects.filter(
                Q(cofprofile__user__username__icontains=word) |
                Q(cofprofile__user__first_name__icontains=word) |
                Q(cofprofile__user__last_name__icontains=word)
            ).distinct()

    query = [(account.trigramme, account.cofprofile.user.get_full_name())
             for account in query]

    data['accounts'] = query
    return render(request, 'kfet/account_search_autocomplete.html', data)