from app.comp import moy_sem
from app.pe.pe_tabletags import TableTag, MoyenneTag
from app.pe.pe_etudiant import EtudiantsJuryPE
from app.pe.pe_rcs import RCS, RCSsJuryPE
from app.pe.pe_rcstag import RCSTag


import pandas as pd
import numpy as np


class RCSInterclasseTag(TableTag):
    # -------------------------------------------------------------------------------------------------------------------
    def __init__(
        self,
        nom_rcs: str,
        etudiants: EtudiantsJuryPE,
        rcss_jury_pe: RCSsJuryPE,
        rcss_tags: dict[tuple, RCSTag],
    ):
        """
        Interclasse l'ensemble des étudiants diplômés à une année
        donnée (celle du jury), pour un RCS donné (par ex: 'S2', '3S')
        en reportant :

        * les moyennes obtenues sur la trajectoire qu'il ont suivi pour atteindre le numéro de semestre de fin de l'aggrégat (indépendamment de son
        formsemestres)
        * calculant le classement sur les étudiants diplômes
        """
        TableTag.__init__(self)

        self.nom_rcs = nom_rcs
        """Le nom du RCS interclassé"""

        self.nom = self.get_repr()

        """Les étudiants diplômés et leurs rcss"""  # TODO
        self.diplomes_ids = etudiants.etudiants_diplomes
        self.etudiants_diplomes = {etudid for etudid in self.diplomes_ids}
        # pour les exports sous forme de dataFrame
        self.etudiants = {
            etudid: etudiants.identites[etudid].etat_civil
            for etudid in self.diplomes_ids
        }

        # Les trajectoires (et leur version tagguées), en ne gardant que celles associées à l'aggrégat
        self.rcss: dict[int, RCS] = {}
        """Ensemble des trajectoires associées à l'aggrégat"""
        for trajectoire_id in rcss_jury_pe.rcss:
            trajectoire = rcss_jury_pe.rcss[trajectoire_id]
            if trajectoire_id[0] == nom_rcs:
                self.rcss[trajectoire_id] = trajectoire

        self.trajectoires_taggues: dict[int, RCS] = {}
        """Ensemble des trajectoires tagguées associées à l'aggrégat"""
        for trajectoire_id in self.rcss:
            self.trajectoires_taggues[trajectoire_id] = rcss_tags[
                trajectoire_id
            ]

        # Les trajectoires suivies par les étudiants du jury, en ne gardant que
        # celles associées aux diplomés
        self.suivi: dict[int, RCS] = {}
        """Association entre chaque étudiant et la trajectoire tagguée à prendre en
        compte pour l'aggrégat"""
        for etudid in self.diplomes_ids:
            self.suivi[etudid] = rcss_jury_pe.suivi[etudid][nom_rcs]

        self.tags_sorted = self.do_taglist()
        """Liste des tags (triés par ordre alphabétique)"""

        # Construit la matrice de notes
        self.notes = self.compute_notes_matrice()
        """Matrice des notes de l'aggrégat"""

        # Synthétise les moyennes/classements par tag
        self.moyennes_tags: dict[str, MoyenneTag] = {}
        for tag in self.tags_sorted:
            moy_gen_tag = self.notes[tag]
            self.moyennes_tags[tag] = MoyenneTag(tag, moy_gen_tag)

        # Est significatif ? (aka a-t-il des tags et des notes)
        self.significatif = len(self.tags_sorted) > 0

    def get_repr(self) -> str:
        """Une représentation textuelle"""
        return f"Aggrégat {self.nom_rcs}"

    def do_taglist(self):
        """Synthétise les tags à partir des trajectoires_tagguées

        Returns:
            Une liste de tags triés par ordre alphabétique
        """
        tags = []
        for trajectoire in self.trajectoires_taggues.values():
            tags.extend(trajectoire.tags_sorted)
        return sorted(set(tags))

    def compute_notes_matrice(self):
        """Construit la matrice de notes (etudid x tags)
        retraçant les moyennes obtenues par les étudiants dans les semestres associés à
        l'aggrégat (une trajectoire ayant pour numéro de semestre final, celui de l'aggrégat).
        """
        # nb_tags = len(self.tags_sorted)   unused ?
        # nb_etudiants = len(self.diplomes_ids)

        # Index de la matrice (etudids -> dim 0, tags -> dim 1)
        etudids = list(self.diplomes_ids)
        tags = self.tags_sorted

        # Partant d'un dataframe vierge
        df = pd.DataFrame(np.nan, index=etudids, columns=tags)

        for trajectoire in self.trajectoires_taggues.values():
            # Charge les moyennes par tag de la trajectoire tagguée
            notes = trajectoire.notes
            # Etudiants/Tags communs entre la trajectoire_tagguée et les données interclassées
            etudids_communs = df.index.intersection(notes.index)
            tags_communs = df.columns.intersection(notes.columns)

            # Injecte les notes par tag
            df.loc[etudids_communs, tags_communs] = notes.loc[
                etudids_communs, tags_communs
            ]

        return df
