from django.http.response import JsonResponse
from drf_yasg.utils import swagger_auto_schema
from drf_yasg import openapi
from rest_framework.parsers import MultiPartParser, FormParser, JSONParser
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework import status

from Subscriptions.serializers import RegistrationParentFileMasterSerializer
from Subscriptions.models import (
    RegistrationForm,
    RegistrationParentFileMaster
)
from N3wtSchool import bdd
import logging
import Subscriptions.util as util

logger = logging.getLogger(__name__)

class RegistrationParentFileMasterView(APIView):
    parser_classes = [MultiPartParser, FormParser, JSONParser]

    @swagger_auto_schema(
        operation_description="Récupère tous les fichiers parents pour un établissement donné",
        manual_parameters=[
            openapi.Parameter(
                'establishment_id',
                openapi.IN_QUERY,
                description="ID de l'établissement",
                type=openapi.TYPE_INTEGER,
                required=True
            )
        ],
        responses={200: RegistrationParentFileMasterSerializer(many=True)}
    )
    def get(self, request):
        establishment_id = request.GET.get('establishment_id')
        if not establishment_id:
            return Response({'error': "Paramètre 'establishment_id' requis"}, status=status.HTTP_400_BAD_REQUEST)

        # Filtrer les fichiers parents liés à l'établissement
        templates = RegistrationParentFileMaster.objects.filter(
            groups__establishment__id=establishment_id
        ).distinct()
        serializer = RegistrationParentFileMasterSerializer(templates, many=True)
        return Response(serializer.data)

    @swagger_auto_schema(
        operation_description="Crée un nouveau fichier parent",
        request_body=RegistrationParentFileMasterSerializer,
        responses={
            201: RegistrationParentFileMasterSerializer,
            400: "Données invalides"
        }
    )
    def post(self, request):
        logger.info(f"raw request.data: {request.data}")

        payload, resp = util.build_payload_from_request(request)
        if resp:
            return resp

        logger.info(f"payload for serializer: {payload}")
        serializer = RegistrationParentFileMasterSerializer(data=payload, partial=True)
        if serializer.is_valid():
            obj = serializer.save()

            # Propager la création des templates côté serveur pour les RegistrationForm
            try:
                groups_qs = obj.groups.all()
                if groups_qs.exists():
                    rfs = RegistrationForm.objects.filter(fileGroup__in=groups_qs).distinct()
                    for rf in rfs:
                        try:
                            util.create_templates_for_registration_form(rf)
                        except Exception as e:
                            logger.exception("Error creating templates for RF %s from parent master %s: %s", getattr(rf, 'pk', None), getattr(obj, 'pk', None), e)
            except Exception:
                logger.exception("Error while propagating templates after parent master creation %s", getattr(obj, 'pk', None))

            return Response(RegistrationParentFileMasterSerializer(obj).data, status=status.HTTP_201_CREATED)

        logger.error(f"serializer errors: {serializer.errors}")
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

class RegistrationParentFileMasterSimpleView(APIView):
    parser_classes = [MultiPartParser, FormParser, JSONParser]
    @swagger_auto_schema(
        operation_description="Récupère un fichier parent spécifique",
        responses={
            200: RegistrationParentFileMasterSerializer,
            404: "Fichier parent non trouvé"
        }
    )
    def get(self, request, id):
        template = bdd.getObject(_objectName=RegistrationParentFileMaster, _columnName='id', _value=id)
        if template is None:
            return JsonResponse({"errorMessage":'Le fichier parent n\'a pas été trouvé'}, safe=False, status=status.HTTP_404_NOT_FOUND)
        serializer = RegistrationParentFileMasterSerializer(template)
        return JsonResponse(serializer.data, safe=False)

    @swagger_auto_schema(
        operation_description="Met à jour un fichier parent existant",
        request_body=RegistrationParentFileMasterSerializer,
        responses={
            200: RegistrationParentFileMasterSerializer,
            400: "Données invalides",
            404: "Fichier parent non trouvé"
        }
    )
    def put(self, request, id):
        master = bdd.getObject(_objectName=RegistrationParentFileMaster, _columnName='id', _value=id)
        if master is None:
            return JsonResponse({'erreur': "Le master de fichier parent n'a pas été trouvé"}, safe=False, status=status.HTTP_404_NOT_FOUND)

        # snapshot des groups avant update
        old_group_ids = set(master.groups.values_list('id', flat=True))

        # Normaliser payload (supporte form-data avec champ 'data' JSON ou fichier JSON)
        payload, resp = util.build_payload_from_request(request)
        if resp:
            return resp

        logger.info(f"payload for update serializer: {payload}")
        serializer = RegistrationParentFileMasterSerializer(master, data=payload, partial=True)
        if serializer.is_valid():
            obj = serializer.save()

            # groups après update
            new_group_ids = set(obj.groups.values_list('id', flat=True))

            removed_group_ids = old_group_ids - new_group_ids
            added_group_ids = new_group_ids - old_group_ids

            # Pour chaque RF appartenant aux groupes retirés -> nettoyer les templates (idempotent)
            if removed_group_ids:
                try:
                    rfs_removed = RegistrationForm.objects.filter(fileGroup__in=list(removed_group_ids)).distinct()
                    for rf in rfs_removed:
                        try:
                            util.create_templates_for_registration_form(rf)
                        except Exception as e:
                            logger.exception("Error cleaning templates for RF %s after parent master %s group removal: %s", getattr(rf, 'pk', None), getattr(obj, 'pk', None), e)
                except Exception:
                    logger.exception("Error while processing RFs for removed groups after parent master update %s", getattr(obj, 'pk', None))

            # Pour chaque RF appartenant aux groupes ajoutés -> créer les templates manquants
            if added_group_ids:
                try:
                    rfs_added = RegistrationForm.objects.filter(fileGroup__in=list(added_group_ids)).distinct()
                    for rf in rfs_added:
                        try:
                            util.create_templates_for_registration_form(rf)
                        except Exception as e:
                            logger.exception("Error creating templates for RF %s after parent master %s group addition: %s", getattr(rf, 'pk', None), getattr(obj, 'pk', None), e)
                except Exception:
                    logger.exception("Error while processing RFs for added groups after parent master update %s", getattr(obj, 'pk', None))

            return Response(serializer.data, status=status.HTTP_200_OK)

        logger.error(f"serializer errors on put: {serializer.errors}")
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    @swagger_auto_schema(
        operation_description="Supprime un fichier parent",
        responses={
            204: "Suppression réussie",
            404: "Fichier parent non trouvé"
        }
    )
    def delete(self, request, id):
        template = bdd.getObject(_objectName=RegistrationParentFileMaster, _columnName='id', _value=id)
        if template is not None:
            template.delete()
            return JsonResponse({'message': 'La suppression du fichier parent a été effectuée avec succès'}, safe=False, status=status.HTTP_204_NO_CONTENT)
        else:
            return JsonResponse({'erreur': 'Le fichier parent n\'a pas été trouvé'}, safe=False, status=status.HTTP_404_NOT_FOUND)
