import json
from django.http import JsonResponse
from django.shortcuts import redirect, render
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from gestion_conge.forms import CongeForm
from gestion_employe.models import Affectation, Employe
from django.forms.models import model_to_dict
from django.utils import timezone
from django.db.models import Q
from fonction_utilitaire import fonctions_utilitaire 
from .models import Conge

@login_required
def index(request):  
    """Vue de gestion de l'index"""  

    employe = Employe.objects.get(user__username = request.user)
    membre_direction = 'direction' in employe.user.groups.values_list('name', flat=True)

    try:
        affectation = Affectation.objects.get(employe = employe, date_fin_daffectation__gte = timezone.now().date())
    except Affectation.DoesNotExist:
        affectation = None

    try:
        projet = Affectation.objects.get(employe=employe, date_fin_daffectation__gte = timezone.now().date())
    except Affectation.DoesNotExist:
        pass
    
    if employe.chef:
        nombre_conges_valide = Conge.objects.filter(validation_hierarchique = True, employe__departement = employe.departement).count()
        nombre_conges_refuse = Conge.objects.filter(validation_hierarchique = False, employe__departement = employe.departement).count()
        conges_en_attente = Conge.objects.filter(validation_hierarchique = None, employe__departement = employe.departement).order_by('-date_demande')
    
    elif membre_direction:
        nombre_conges_valide = Conge.objects.filter(validation_direction = True).count()
        nombre_conges_refuse = Conge.objects.filter(validation_direction = False).count()
        conges_en_attente = Conge.objects.filter(validation_hierarchique = True, validation_direction = None).order_by('-date_demande')

    elif affectation and affectation.role == "chef_projet":
        employes_du_projet = Affectation.objects.filter(
            projet = projet.projet,
            date_fin_daffectation__gte = timezone.now().date()
        ).values('employe')

        nombre_conges_valide = Conge.objects.filter(
            employe__in = employes_du_projet,
            validation_hierarchique = True
        ).count()

        nombre_conges_refuse = Conge.objects.filter(
            Q(employe__in = employes_du_projet) & 
            (Q(validation_hierarchique = False) | Q(validation_direction = False))
        ).count()

        conges_en_attente = Conge.objects.filter(
            Q(employe__in = employes_du_projet) &
            (
                Q(validation_hierarchique__isnull = True) | Q(validation_direction__isnull = True)
            )
        ).exclude(
            Q(validation_hierarchique = True) | Q(validation_hierarchique = False) | 
            Q(validation_direction = True) | Q(validation_direction = False)
        ).order_by('-date_demande')

    else:
        nombre_conges_valide = Conge.objects.filter(
            employe=employe,
            validation_direction = True
        ).count()

        nombre_conges_refuse = Conge.objects.filter(Q(employe=employe) & (
            Q(validation_direction = False) | Q(validation_hierarchique = False)
        )).count()
        
        conges_en_attente = Conge.objects.filter(
            Q(employe = employe) &
            (
                Q(validation_direction__isnull = True) | Q(validation_hierarchique__isnull = True)
            )
        ).exclude(
            Q(validation_hierarchique = True) | Q(validation_hierarchique = False)
        ).order_by('-date_demande')

    return render(request, 'gestion_conge/index.html', {
        "nombre_conges_valide": nombre_conges_valide, 
        "nombre_conges_refuse": nombre_conges_refuse, 
        "nombre_conges_en_attente": conges_en_attente.count(), 
        "formulaire_demande_conge": CongeForm,
        "employe_est_il_chef": employe.chef,
        "membre_de_la_direction": membre_direction,
        "est_chef_projet": affectation.role == "chef_projet" if affectation else False,
    })

@login_required
def demander_conge(request):
    """Vue de gestion des demandes de congés"""
    try:
        employe = Employe.objects.get(user__username = request.user)
    except Employe.DoesNotExist:
        messages.error(request, "Votre demande de congé a échoué car votre profil Utilisateur n'est lié à aucun profil Employé. Veuillez contacter l'administrateur.")
        return redirect("gestion_conges:conge")
    
    retour_quota = fonctions_utilitaire.solde_conge(employe)
    if retour_quota["success"]:
        quota_annuel = retour_quota['quota_annuel']
    else:
        messages.error(request, retour_quota['message'])
        return redirect("gestion_conges:conge")

    if request.method == "POST":
        form = CongeForm(request.POST, request.FILES)
        if form.is_valid():
            conge_obj = form.save(commit=False)
            conge_obj.employe = employe

            if conge_obj.type == "conge_annuel":
                if retour_quota["nombre_jours_valide"] + conge_obj.nombre_jours > quota_annuel:
                    messages.error(request, "Quota annuel dépassé (30 jours max).")
                    return redirect("gestion_conges:conge")
                
            conge_obj.save()
            messages.success(request, "Votre demande de congé a été enregistrée.")

            fonctions_utilitaire.envoyer_mail(
                sujet = "Demande de congé",
                message = f"""Bonjour {employe.user.first_name} {employe.user.last_name}, votre demande de congé a été enregistrée. Veuillez consulter votre profil pour plus de détails.""",
                destinataires = fonctions_utilitaire.destinataire_mail_demande_conges() + [employe.user.email]
            )
            
            return redirect("gestion_conges:conge")
    
    return redirect("gestion_conges:conge")

@login_required
def liste_demande_conges(request):

    try:
        employe = Employe.objects.get(user=request.user)
    except Employe.DoesNotExist:
        return JsonResponse({
            "success": False,
            "message": "Profil employé introuvable"
        })

    affectation = Affectation.objects.filter(
        employe=employe,
        date_fin_daffectation__gte=timezone.now().date()
    ).first()

    is_direction = employe.user.groups.filter(name='direction').exists()

    if employe.chef:

        conges = Conge.objects.filter(
            Q(employe__departement=employe.departement) |
            Q(employe=employe)
        ).order_by('-date_demande')

    elif affectation and affectation.role == "chef_projet":

        employes_du_projet = Affectation.objects.filter(
            projet=affectation.projet,
            date_fin_daffectation__gte=timezone.now().date()
        ).values_list('employe', flat=True)

        conges = Conge.objects.filter(
            Q(employe__in=employes_du_projet) |
            Q(employe=employe)
        ).order_by('-date_demande')

   
    elif is_direction:

        conges = Conge.objects.filter(
            Q(validation_hierarchique=True) |
            Q(employe__user__groups__name='direction')
        ).distinct().order_by('-date_demande')

    else:

        conges = Conge.objects.filter(
            employe=employe
        ).order_by('-date_demande')

    return JsonResponse({
        "success": True,
        "data": [
            {
                **model_to_dict(conge),
                "prenom_nom": f"{conge.employe.user.first_name} {conge.employe.user.last_name}",
                "date_demande": conge.date_demande,
                "nombre_jours": conge.nombre_jours,
                "type": dict(conge.TYPE_CHOICES).get(conge.type),
                "solde_conge": fonctions_utilitaire.solde_conge(conge.employe)["quota_annuel"]
            }
            for conge in conges
        ]
    })

@login_required
def validation_de_conge(request):
    """
    Vue de validation de conges par le superieur hierarchique.
    1- Si l'employe appartient à un département, le congé est validé par le chef de département.
    2- Si l'employé n'appartient pas à un département, le congé est validé par le chef de projet.
    """
    request_data = json.loads(request.body)
    conge_id = request_data.get("id_conge", None)
    try:
        conge = Conge.objects.get(id=conge_id)
    except conge.DoesNotExist:
        return JsonResponse({"message": "Le congé selectionné n'existe pas."})
    
    if request.method == "POST":
        validation_hierarchique = request_data.get("validation_hierarchique", None)
        validation_direction = request_data.get("validation_direction", None)
        motif_refus = request_data.get("motif_refus", "")

        if validation_hierarchique is not None:
            conge.validation_hierarchique = True if validation_hierarchique == "valide" else False
            if validation_hierarchique == "refuse" and not motif_refus:
                return JsonResponse({"message": "Veuillez fournir un motif de refus."})
            conge.motif_refus = motif_refus if validation_hierarchique == "refuse" else ""
        
        if validation_direction is not None:
            conge.validation_direction = True if validation_direction == "valide" else False
            if validation_direction == "refuse" and not motif_refus:
                return JsonResponse({"message": "Veuillez fournir un motif de refus."})
            conge.motif_refus = motif_refus if validation_direction == "refuse" else ""

        conge.save()
        return JsonResponse({"message": "La décision a été enregistrée avec succès."})