# vim:spell:spelllang=fr
# -*- encoding: utf-8 -*-

from optparse import make_option
from ldap.filter import filter_format
import datetime


from django.core.management.base import BaseCommand
from django.db.models import Q
from django.db import transaction
from django.conf import settings

import django_journal

from appli_project.appli_socle import models, backends

class Command(BaseCommand):
    '''
       Traverse les listes des modèles UtilisateurCAS et supprime ceux qui
       n'existent plus dans le LDAP.
    '''
    can_import_django_settings = True
    output_transaction = True
    requires_model_validation = True
    args = ''
    help = 'Synchronise la base de compte ENT avec le LDAP'

    option_list = BaseCommand.option_list + (
            make_option("--delete", action="store_true"),
            make_option("--verbose", action="store_true"),
            make_option("--now", action="store_true"),)

    def slice(self, slicable, length):
        i = 0
        while True:
            l = slicable[i:i+length]
            yield l
            if len(l) < length:
                break
            i += length

    def suppression_profil_offre_invalide(self, *args, **options):
        if options.get('now'):
            seuil = datetime.datetime.now()
        else:
            seuil = datetime.datetime.now() - datetime.timedelta(
                    days=settings.PROFIL_OFFRE_NON_CONFIRME_TIMEOUT)

        qs = models.ProfilOffre.objects.filter(date_joined__lt=seuil) \
                .filter(Q(acceptation_cgu=False)|Q(acceptation_charte_qualite=False))
        if options.get('delete'):
            if qs.exists():
                if options.get('verbose'):
                    print 'Comptes supprimés:'
                    for user in qs:
                        print '-', user.email.encode('utf-8')
                for user in qs:
                    msg = u'compte supprimé car non confirmé depuis plus de %s jours' % settings.PROFIL_OFFRE_NON_CONFIRME_TIMEOUT
                    django_journal.record('supprime-compte', msg, user=user)
                qs.delete()
        else:
            if qs.exists():
                print 'Comptes à supprimer:'
                for user in qs:
                    print '-', user.email.encode('utf-8')

    @transaction.commit_on_success
    def handle(self, *args, **options):
        self.suppression_profil_offre_invalide(*args, **options)
        engine = backends.ProfilRechercheAuthentification()
        qs = models.UtilisateurCAS.objects.all()
        identifiants_a_supprimer = set()
        for q in self.slice(qs, 50):
            if not q:
                break
            identifiants = [v.encode('utf-8') for v in q.values_list('identifiant', flat=True)]
            filtre = []
            for identifiant in identifiants:
                f = filter_format('(%s=%s)', (settings.LDAP_CAS_UID, identifiant))
                filtre.append(f)
            filtre = '(|%s)' % ''.join(filtre)
            result = engine.recherche_ldap(filtre, [settings.LDAP_CAS_UID])
            identifiants_trouves = filter(None, [ attrs.get(settings.LDAP_CAS_UID, [None])[0] for dn, attrs in result ])
            identifiants_a_supprimer.update(set(identifiants) - set(identifiants_trouves))
        if identifiants_a_supprimer:
            if options.get('delete'):
                for sl in self.slice(list(identifiants_a_supprimer), 30):
                    for user in models.ProfilRecherche.objects.filter(utilisateur_cas__identifiant__in=sl):
                        django_journal.record('supprime-compte',
                                u'compte {cas_user} supprimé suite à sa '
                                u'suppression dans le LDAP', user=user,
                                cas_user=user.utilisateur_cas.all()[0].identifiant)
                    models.ProfilRecherche.objects.filter(utilisateur_cas__identifiant__in=sl).delete()
                print 'Identifiant supprimés:'
            else:
                print 'Identifiant à supprimer:'
            for identifiant in identifiants_a_supprimer:
                print ' -', identifiant
