from django.http.response import JsonResponse
from rest_framework.views import APIView
from rest_framework.parsers import JSONParser
from django.conf import settings
from rest_framework.response import Response
from rest_framework import status
from django.db.models import Q
from .models import Messagerie
from Auth.models import Profile, ProfileRole
from GestionMessagerie.serializers import MessageSerializer
from School.models import Teacher

from School.serializers import TeacherSerializer

import N3wtSchool.mailManager as mailer
from N3wtSchool import bdd
from drf_yasg.utils import swagger_auto_schema
from drf_yasg import openapi
from rest_framework.exceptions import NotFound

class MessagerieView(APIView):
    def get(self, request, profile_id):
        messagesList = bdd.getObjects(_objectName=Messagerie, _columnName='destinataire__id', _value=profile_id)
        messages_serializer = MessageSerializer(messagesList, many=True)
        return JsonResponse(messages_serializer.data, safe=False)

class MessageView(APIView):
    def post(self, request):
        message_data=JSONParser().parse(request)
        message_serializer = MessageSerializer(data=message_data)

        if message_serializer.is_valid():
            message_serializer.save()

            return JsonResponse('Nouveau Message ajouté', safe=False)

        return JsonResponse(message_serializer.errors, safe=False)

class MessageSimpleView(APIView):
    def get(self, request, id):
        message=bdd.getObject(Messagerie, "id", id)
        message_serializer=MessageSerializer(message)
        return JsonResponse(message_serializer.data, safe=False)

class SendEmailView(APIView):
    """
    API pour envoyer des emails aux parents et professeurs.
    """
    def post(self, request):
        data = request.data
        recipients = data.get('recipients', [])
        cc = data.get('cc', [])
        bcc = data.get('bcc', [])
        subject = data.get('subject', 'Notification')
        message = data.get('message', '')
        establishment_id = data.get('establishment_id', '')

        if not recipients or not message:
            return Response({'error': 'Les destinataires et le message sont requis.'}, status=status.HTTP_400_BAD_REQUEST)

        try:
            # Récupérer la connexion SMTP
            connection = mailer.getConnection(establishment_id)

            # Envoyer l'email
            return mailer.sendMail(
                subject=subject,
                message=message,
                recipients=recipients,
                cc=cc,
                bcc=bcc,
                attachments=[],
                connection=connection
            )
        except NotFound as e:
            return Response({'error': str(e)}, status=status.HTTP_404_NOT_FOUND)
        except Exception as e:
            return Response({'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

class ContactsView(APIView):
    """
    API pour récupérer les contacts associés à un établissement.
    """
    def get(self, request, establishment_id):
        try:
            # Récupérer les enseignants associés à l'établissement
            teachers = Teacher.objects.filter(profile_role__establishment_id=establishment_id)
            teachers_serializer = TeacherSerializer(teachers, many=True)

            # Ajouter un contact pour l'administration
            admin_contact = {
                "id": "admin",
                "name": "Administration",
                "email": "admin@etablissement.com",
                "profilePic": "https://www.gravatar.com/avatar/admin"
            }

            contacts = [admin_contact] + teachers_serializer.data
            return Response(contacts, status=status.HTTP_200_OK)
        except Exception as e:
            return Response({"error": str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

def search_recipients(request):
    """
    API pour rechercher des destinataires en fonction d'un terme de recherche et d'un établissement.
    """
    query = request.GET.get('q', '').strip()  # Récupérer le terme de recherche depuis les paramètres GET
    establishment_id = request.GET.get('establishment_id', None)  # Récupérer l'ID de l'établissement

    if not query:
        return JsonResponse([], safe=False)  # Retourner une liste vide si aucun terme n'est fourni

    if not establishment_id:
        return JsonResponse({'error': 'establishment_id est requis'}, safe=False, status=status.HTTP_400_BAD_REQUEST)

    # Rechercher dans les champs pertinents (nom, prénom, email) et filtrer par establishment_id
    profiles = Profile.objects.filter(
        Q(first_name__icontains=query) |
        Q(last_name__icontains=query) |
        Q(email__icontains=query),
        roles__establishment_id=establishment_id,  # Utiliser 'roles' au lieu de 'profilerole'
        roles__is_active=True  # Filtrer uniquement les ProfileRole actifs
    ).distinct()

    # Construire la réponse avec les rôles associés
    results = []
    for profile in profiles:
        profile_roles = ProfileRole.objects.filter(
            profile=profile,
            establishment_id=establishment_id,
            is_active=True  # Inclure uniquement les ProfileRole actifs
        ).values(
            'id', 'role_type', 'establishment__name', 'is_active'
        )
        results.append({
            'id': profile.id,
            'first_name': profile.first_name,
            'last_name': profile.last_name,
            'email': profile.email,
            'roles': list(profile_roles)  # Inclure tous les rôles actifs associés pour cet établissement
        })

    return JsonResponse(results, safe=False)

class ConversationListView(APIView):
    """
    Liste les conversations d'un utilisateur (parent ou enseignant).
    Retourne la liste des interlocuteurs et le dernier message échangé.
    """
    @swagger_auto_schema(
        operation_description="Liste les conversations d'un utilisateur (parent ou enseignant).",
        responses={200: openapi.Response('Liste des conversations')}
    )
    def get(self, request, profile_id):
        # Récupérer toutes les conversations où l'utilisateur est émetteur ou destinataire
        messages = Messagerie.objects.filter(Q(emetteur_id=profile_id) | Q(destinataire_id=profile_id))
        # Grouper par conversation_id
        conversations = {}
        for msg in messages.order_by('-date_envoi'):
            conv_id = msg.conversation_id or f"{min(msg.emetteur_id, msg.destinataire_id)}_{max(msg.emetteur_id, msg.destinataire_id)}"
            if conv_id not in conversations:
                conversations[conv_id] = msg
        # Préparer la réponse
        data = []
        for conv_id, last_msg in conversations.items():
            interlocuteur = last_msg.emetteur if last_msg.destinataire_id == int(profile_id) else last_msg.destinataire
            data.append({
                'conversation_id': conv_id,
                'last_message': MessageSerializer(last_msg).data,
                'interlocuteur': {
                    'id': interlocuteur.id,
                    'first_name': interlocuteur.first_name,
                    'last_name': interlocuteur.last_name,
                    'email': interlocuteur.email,
                }
            })
        return Response(data, status=status.HTTP_200_OK)

class ConversationMessagesView(APIView):
    """
    Récupère tous les messages d'une conversation donnée.
    """
    @swagger_auto_schema(
        operation_description="Récupère tous les messages d'une conversation donnée.",
        responses={200: openapi.Response('Liste des messages')}
    )
    def get(self, request, conversation_id):
        messages = Messagerie.objects.filter(conversation_id=conversation_id).order_by('date_envoi')
        serializer = MessageSerializer(messages, many=True)
        return Response(serializer.data, status=status.HTTP_200_OK)

class MarkAsReadView(APIView):
    """
    Marque tous les messages reçus dans une conversation comme lus pour l'utilisateur connecté.
    """
    @swagger_auto_schema(
        operation_description="Marque tous les messages reçus dans une conversation comme lus pour l'utilisateur connecté.",
        request_body=openapi.Schema(
            type=openapi.TYPE_OBJECT,
            properties={
                'profile_id': openapi.Schema(type=openapi.TYPE_INTEGER, description='ID du profil utilisateur')
            },
            required=['profile_id']
        ),
        responses={200: openapi.Response('Statut OK')}
    )
    def post(self, request, conversation_id):
        profile_id = request.data.get('profile_id')
        Messagerie.objects.filter(conversation_id=conversation_id, destinataire_id=profile_id, is_read=False).update(is_read=True)
        return Response({'status': 'ok'}, status=status.HTTP_200_OK)

