from django.shortcuts import render,get_object_or_404,get_list_or_404
from .models import RegistrationForm, Student, Guardian, Sibling
import time
from datetime import date, datetime, timedelta
from zoneinfo import ZoneInfo
from django.conf import settings
from N3wtSchool import renderers
from N3wtSchool import bdd

from io import BytesIO
from django.core.files import File
from pathlib import Path
import os
from enum import Enum

import random
import string
from rest_framework.parsers import JSONParser
import pymupdf

def recupereListeFichesInscription():
    """
    Retourne la liste complète des fiches d’inscription.
    """
    context = {
        "ficheInscriptions_list": bdd.getAllObjects(RegistrationForm),
    }
    return context

def recupereListeFichesInscriptionEnAttenteSEPA():
    """
    Retourne les fiches d’inscription avec paiement SEPA en attente.
    """
    ficheInscriptionsSEPA_list = RegistrationForm.objects.filter(modePaiement="Prélèvement SEPA").filter(etat=RegistrationForm.RegistrationFormStatus['SEPA_ENVOYE'])
    return ficheInscriptionsSEPA_list

def _now():
    """
    Retourne la date et l’heure en cours, avec fuseau.
    """
    return datetime.now(ZoneInfo(settings.TZ_APPLI))

def convertToStr(dateValue, dateFormat):
    """
    Convertit un objet datetime en chaîne selon un format donné.
    """
    return dateValue.strftime(dateFormat)

def convertToDate(date_time):
    """
    Convertit une chaîne en objet datetime selon le format '%d-%m-%Y %H:%M'.
    """
    format = '%d-%m-%Y %H:%M'
    datetime_str = datetime.strptime(date_time, format)

    return datetime_str

def convertTelephone(telephoneValue, separator='-'):
    """
    Reformate un numéro de téléphone en y insérant un séparateur donné.
    """
    return f"{telephoneValue[:2]}{separator}{telephoneValue[2:4]}{separator}{telephoneValue[4:6]}{separator}{telephoneValue[6:8]}{separator}{telephoneValue[8:10]}"

def genereRandomCode(length):
    """
    Génère un code aléatoire de longueur spécifiée.
    """
    return ''.join(random.choice(string.ascii_letters) for i in range(length))

def calculeDatePeremption(_start, nbDays):
    """
    Calcule la date de fin à partir d’un point de départ et d’un nombre de jours.
    """
    return convertToStr(_start + timedelta(days=nbDays), settings.DATE_FORMAT)

# Fonction permettant de retourner la valeur du QueryDict
# QueryDict [ index ] -> Dernière valeur d'une liste
# dict (QueryDict [ index ]) -> Toutes les valeurs de la liste
def _(liste):
    """
    Retourne la première valeur d’une liste extraite d’un QueryDict.
    """
    return liste[0]

def getArgFromRequest(_argument, _request):
    """
    Extrait la valeur d’un argument depuis la requête (JSON).
    """
    resultat = None
    data=JSONParser().parse(_request)
    resultat = data[_argument]
    return resultat

def merge_files_pdf(filenames, output_filename):
    """
    Fusionne plusieurs fichiers PDF en un seul document.
    Vérifie l'existence des fichiers sources avant la fusion.
    """
    merger = pymupdf.open()
    valid_files = []

    # Vérifier l'existence des fichiers et ne garder que ceux qui existent
    for filename in filenames:
        if os.path.exists(filename):
            valid_files.append(filename)

    # Fusionner les fichiers valides
    for filename in valid_files:
        merger.insert_file(filename)

    # S'assurer que le dossier de destination existe
    os.makedirs(os.path.dirname(output_filename), exist_ok=True)

    # Sauvegarder le fichier fusionné
    merger.save(output_filename)
    merger.close()

    return output_filename

def rfToPDF(registerForm, filename):
    """
    Génère le PDF d'un dossier d'inscription et l'associe au RegistrationForm.
    """
    data = {
        'pdf_title': f"Dossier d'inscription de {registerForm.student.first_name}",
        'signatureDate': convertToStr(_now(), '%d-%m-%Y'),
        'signatureTime': convertToStr(_now(), '%H:%M'),
        'student': registerForm.student,
    }

    # S'assurer que le dossier parent existe
    os.makedirs(os.path.dirname(filename), exist_ok=True)

    # Générer le PDF
    pdf = renderers.render_to_pdf('pdfs/dossier_inscription.html', data)

    # Écrire le fichier directement
    with open(filename, 'wb') as f:
        f.write(pdf.content)

    # Mettre à jour le champ registration_file du registerForm
    with open(filename, 'rb') as f:
        registerForm.registration_file.save(
            os.path.basename(filename),
            File(f),
            save=True
        )

    return registerForm.registration_file