from django.http.response import JsonResponse
from rest_framework.views import APIView
from rest_framework import status
from drf_yasg.utils import swagger_auto_schema
from django.views.decorators.csrf import ensure_csrf_cookie, csrf_protect
from django.utils.decorators import method_decorator
from Subscriptions.models import StudentCompetency, Student
from Common.models import Domain
from Subscriptions.models import BilanCompetence
from datetime import date
from N3wtSchool.renderers import render_to_pdf
from django.core.files import File
from io import BytesIO
import os
import logging
from django.conf import settings

logger = logging.getLogger(__name__)

@method_decorator(csrf_protect, name='dispatch')
@method_decorator(ensure_csrf_cookie, name='dispatch')
class StudentCompetencyListCreateView(APIView):
    def get(self, request):
        student_id = request.GET.get('student_id')
        period = request.GET.get('period')
        if not student_id:
            return JsonResponse({'error': 'student_id requis'}, status=400)
        try:
            student = Student.objects.get(id=student_id)
        except Student.DoesNotExist:
            return JsonResponse({'error': 'Élève introuvable'}, status=404)

        # Filtrer par student ET period si period est fourni
        filter_kwargs = {'student': student}
        if period:
            filter_kwargs['period'] = period

        student_competencies = StudentCompetency.objects.filter(**filter_kwargs).select_related(
            'establishment_competency',
            'establishment_competency__competency',
            'establishment_competency__competency__category',
            'establishment_competency__competency__category__domain',
            'establishment_competency__custom_category',
            'establishment_competency__custom_category__domain',
        )

        result = []
        total_competencies = 0
        domaines = Domain.objects.all()
        for domaine in domaines:
            domaine_dict = {
                "domaine_id": domaine.id,
                "domaine_nom": domaine.name,
                "categories": []
            }
            categories = domaine.categories.all()
            for categorie in categories:
                categorie_dict = {
                    "categorie_id": categorie.id,
                    "categorie_nom": categorie.name,
                    "competences": []
                }
                # On ne boucle que sur les compétences du student pour cette catégorie
                for sc in student_competencies:
                    ec = sc.establishment_competency
                    # Cas compétence de référence
                    if ec.competency and ec.competency.category_id == categorie.id:
                        comp = ec.competency
                        categorie_dict["competences"].append({
                            "competence_id": ec.id,  # <-- retourne l'id de l'EstablishmentCompetency
                            "nom": comp.name,
                            "score": sc.score,
                            "comment": sc.comment or "",
                            "period":sc.period or ""
                        })
                        total_competencies += 1
                    # Cas compétence custom
                    elif ec.competency is None and ec.custom_category_id == categorie.id:
                        categorie_dict["competences"].append({
                            "competence_id": ec.id,  # <-- retourne l'id de l'EstablishmentCompetency
                            "nom": ec.custom_name,
                            "score": sc.score,
                            "comment": sc.comment or "",
                            "period":sc.period or ""
                        })
                        total_competencies += 1
                if categorie_dict["competences"]:
                    domaine_dict["categories"].append(categorie_dict)
            if domaine_dict["categories"]:
                result.append(domaine_dict)

        return JsonResponse({
            "count": total_competencies,
            "data": result
        }, safe=False, status=200)

    def put(self, request):
        """
        Met à jour en masse les notes des compétences d'un élève.
        Attend une liste d'objets {"competenceId": ..., "grade": ...}
        """
        data = request.data
        if not isinstance(data, list):
            return JsonResponse({"error": "Une liste est attendue."}, status=400)
        updated = []
        errors = []
        updated_competency_ids = set()
        for item in data:
            comp_id = item.get("competenceId")
            grade = item.get("grade")
            student_id = item.get('studentId')
            period = item.get('period')
            if comp_id is None or grade is None:
                errors.append({"competenceId": comp_id, "error": "champ manquant"})
                continue
            try:
                sc = StudentCompetency.objects.get(
                    establishment_competency_id=comp_id,
                    student_id=student_id,
                    period=period
                )
                sc.score = grade
                sc.save()
                updated.append(comp_id)
                updated_competency_ids.add(sc.id)
            except StudentCompetency.DoesNotExist:
                errors.append({"competenceId": comp_id, "error": "not found"})

        # Génération du PDF si au moins une compétence a été mise à jour
        if updated:
            student = Student.objects.get(id=student_id)
            # On ne prend que les StudentCompetency mis à jour pour la génération du PDF
            student_competencies = StudentCompetency.objects.filter(
                student=student,
                period=period,
                id__in=updated_competency_ids
            ).select_related(
                'establishment_competency',
                'establishment_competency__competency',
                'establishment_competency__competency__category',
                'establishment_competency__competency__category__domain',
                'establishment_competency__custom_category',
                'establishment_competency__custom_category__domain',
            )

            result = []
            domaines = Domain.objects.all()
            for domaine in domaines:
                domaine_dict = {
                    "nom": domaine.name,
                    "categories": []
                }
                categories = domaine.categories.all()
                for categorie in categories:
                    categorie_dict = {
                        "nom": categorie.name,
                        "competences": []
                    }
                    for sc in student_competencies:
                        ec = sc.establishment_competency
                        if ec.competency and ec.competency.category_id == categorie.id:
                            comp = ec.competency
                            categorie_dict["competences"].append({
                                "nom": comp.name,
                                "score": sc.score,
                                "comment": sc.comment or "",
                            })
                        elif ec.competency is None and ec.custom_category_id == categorie.id:
                            categorie_dict["competences"].append({
                                "nom": ec.custom_name,
                                "score": sc.score,
                                "comment": sc.comment or "",
                            })
                    if categorie_dict["competences"]:
                        domaine_dict["categories"].append(categorie_dict)
                if domaine_dict["categories"]:
                    result.append(domaine_dict)

            establishment = None
            if student.associated_class and student.associated_class.establishment:
                establishment = student.associated_class.establishment
            else:
                try:
                    establishment = student.registrationform.establishment
                except Exception:
                    establishment = None

            establishment_logo_path = None
            if establishment and establishment.logo:
                try:
                    if establishment.logo.path and os.path.exists(establishment.logo.path):
                        establishment_logo_path = establishment.logo.path
                except Exception:
                    establishment_logo_path = None

            n3wt_logo_path = os.path.join(settings.BASE_DIR, 'static', 'img', 'logo_min.svg')
            if not os.path.exists(n3wt_logo_path):
                n3wt_logo_path = None
            
            context = {
                "student": {
                    "first_name": student.first_name,
                    "last_name": student.last_name,
                    "level": student.level,
                    "class_name": student.associated_class.atmosphere_name if student.associated_class else "Non assignée",
                },
                "establishment": {
                    "name": establishment.name if establishment else "Établissement",
                    "address": establishment.address if establishment else "",
                    "logo_path": establishment_logo_path,
                },
                "product": {
                    "name": "n3wt-school",
                    "logo_path": n3wt_logo_path,
                },
                "period": period,
                "date": date.today().strftime("%d/%m/%Y"),
                "domaines": result,
            }

            pdf_result = render_to_pdf('pdfs/bilan_competences.html', context)

            try:
                filename = f"bilan_competences_{student.last_name}_{student.first_name}_{period}.pdf"
                for existing_bilan in BilanCompetence.objects.filter(student=student, period=period):
                    if existing_bilan.file and existing_bilan.file.name:
                        file_path = existing_bilan.file.path
                        if os.path.exists(file_path):
                            os.remove(file_path)
                    existing_bilan.delete()

                bilan = BilanCompetence.objects.create(
                    student=student,
                    period=period
                )
                bilan.file.save(
                    os.path.basename(filename),
                    File(BytesIO(pdf_result.content)),
                    save=True
                )
            except Exception as e:
                logger.error(f"Erreur lors de la sauvegarde du fichier PDF : {e}")
                raise
        return JsonResponse({"updated": updated, "errors": errors}, status=200)

@method_decorator(csrf_protect, name='dispatch')
@method_decorator(ensure_csrf_cookie, name='dispatch')
class StudentCompetencySimpleView(APIView):
    def get(self, request, id):        
        return JsonResponse("ok", safe=False, status=status.HTTP_200_OK)