import json
from datetime import datetime, timedelta

FICHIER_JSON = "eleves_disponibilites.json"

def convertir_heure_en_minutes(heure_str):
    """Convertit une heure au format hh:mm en minutes depuis minuit."""
    if isinstance(heure_str, int):
        # Si l'entrée est déjà un entier (minutes), nous la retournons directement
        return heure_str
    heures, minutes = map(int, heure_str.split(':'))
    return heures * 60 + minutes

def convertir_minutes_en_heure(minutes):
    """Convertit des minutes depuis minuit en une chaîne de caractères hh:mm."""
    heures = minutes // 60
    minutes = minutes % 60
    return f"{heures:02d}:{minutes:02d}"

def sauvegarder_donnees(eleves):
    """Enregistre les données des élèves dans un fichier JSON."""
    # Convertir les heures en format lisible (hh:mm) pour l'enregistrement
    for eleve, info in eleves.items():
        for jour, plages in info['disponibilites'].items():
            eleves[eleve]['disponibilites'][jour] = [(convertir_minutes_en_heure(debut), convertir_minutes_en_heure(fin)) for debut, fin in plages]
    
    with open(FICHIER_JSON, 'w') as fichier:
        json.dump(eleves, fichier, indent=4)
    print(f"\nDonnées enregistrées dans {FICHIER_JSON}.")

def charger_donnees():
    """Charge les données des élèves depuis un fichier JSON, si disponible."""
    try:
        with open(FICHIER_JSON, 'r') as fichier:
            eleves = json.load(fichier)
        print(f"\nDonnées chargées depuis {FICHIER_JSON}.")
        
        # Convertir les heures chargées du fichier JSON en format minute pour les calculs
        for eleve, info in eleves.items():
            for jour, plages in info['disponibilites'].items():
                eleves[eleve]['disponibilites'][jour] = [(convertir_heure_en_minutes(debut), convertir_heure_en_minutes(fin)) for debut, fin in plages]
        
        return eleves
    except FileNotFoundError:
        print(f"\n{FICHIER_JSON} introuvable. Aucune donnée à charger.")
        return {}

def entrer_disponibilites(eleves):
    """Fonction pour entrer les disponibilités de tous les élèves."""
    while True:
        nom = input("Entrez le nom de l'élève : ")

        jours = input("Entrez les jours de disponibilités (ex: lundi, mardi) séparés par des virgules : ").split(',')

        disponibilites = {}
        for jour in jours:
            jour = jour.strip().lower()
            heures = input(f"Entrez les plages horaires disponibles pour {jour} (ex: 14:00-16:30 pour 14h à 16h30) séparées par des virgules : ").split(',')
            disponibilites[jour] = []
            for heure in heures:
                debut_str, fin_str = heure.split('-')
                debut = convertir_heure_en_minutes(debut_str)
                fin = convertir_heure_en_minutes(fin_str)
                disponibilites[jour].append((debut, fin))

        duree_cours = int(input("Entrez la durée du cours en minutes (60, 90 ou 120) : "))

        eleves[nom] = {'disponibilites': disponibilites, 'duree_cours': duree_cours}

        continuer = input("Souhaitez-vous ajouter un autre élève ? (oui/non) : ").strip().lower()
        if continuer != 'oui':
            break

    return eleves

def trouver_creneaux(eleves):
    """Fonction pour trouver les créneaux disponibles en fonction des disponibilités et de la durée des cours."""
    creneaux_occupes = []  # Liste pour suivre les créneaux déjà occupés par d'autres élèves
    planning = {}  # Planning final pour chaque élève

    for nom, info in eleves.items():
        duree_cours = info['duree_cours']
        disponibilites = info['disponibilites']
        planning[nom] = []

        # Parcours des disponibilités de chaque élève
        for jour, plages in disponibilites.items():
            for debut, fin in plages:
                # Assurez-vous que 'debut' et 'fin' sont des entiers (minutes depuis minuit)
                if isinstance(debut, str):
                    debut = convertir_heure_en_minutes(debut)
                if isinstance(fin, str):
                    fin = convertir_heure_en_minutes(fin)

                heure_debut = debut

                # Trouver tous les créneaux possibles dans cette plage
                while heure_debut + duree_cours <= fin:
                    creneau = (jour, heure_debut, heure_debut + duree_cours)

                    # Vérifier que le créneau n'est pas déjà occupé
                    conflit = False
                    for creneau_occupe in creneaux_occupes:
                        if creneau[0] == creneau_occupe[0]:  # Même jour
                            # Vérifier s'il y a un chevauchement
                            if not (creneau[2] <= creneau_occupe[1] or creneau[1] >= creneau_occupe[2]):
                                conflit = True
                                break

                    if not conflit:
                        planning[nom].append(creneau)
                        creneaux_occupes.append(creneau)

                    heure_debut += 30  # Avancer par pas de 30 minutes pour trouver le prochain créneau possible

    return planning


def afficher_creneaux(planning):
    """Fonction pour afficher les créneaux de cours."""
    print("\nCréneaux de cours proposés :")
    for nom, creneaux in planning.items():
        print(f"\n{nom} :")
        for creneau in creneaux:
            jour, debut, fin = creneau
            debut_str = convertir_minutes_en_heure(debut)
            fin_str = convertir_minutes_en_heure(fin)
            print(f"  {jour.capitalize()} de {debut_str} à {fin_str}")

def main():
    """Fonction principale."""
    print("Programme de gestion des cours par webcam\n")

    # Charger les données existantes depuis le fichier JSON
    eleves = charger_donnees()

    # Entrer les disponibilités et durées de cours des élèves
    eleves = entrer_disponibilites(eleves)

    # Enregistrer les données dans un fichier JSON
    sauvegarder_donnees(eleves)

    # Calculer les créneaux de cours disponibles sans conflits
    planning = trouver_creneaux(eleves)

    # Afficher les créneaux proposés
    afficher_creneaux(planning)

if __name__ == "__main__":
    main()
