##############################################################################
# ScoDoc
# Copyright (c) 1999 - 2024 Emmanuel Viennet.  All rights reserved.
# See LICENSE
##############################################################################

"""Liste simple d'étudiants
"""
import datetime

from app.models import FormSemestre, FormSemestreInscription, Identite
from app.scodoc.sco_exceptions import ScoValueError
from app.tables import table_builder as tb


class TableEtud(tb.Table):
    """Table listant des étudiants
    Peut-être sous-classée pour ajouter des colonnes.
    L'id de la ligne est etuid, et le row stocke etud.
    """

    def __init__(
        self,
        etuds: list[Identite] = None,
        classes: list[str] = None,
        row_class=None,
        with_foot_titles=False,
        **kwargs,
    ):
        etuds = etuds or []
        self.rows: list["RowEtud"] = []  # juste pour que VSCode nous aide sur .rows
        classes = classes or ["gt_table", "gt_left", "with-highlight"]
        super().__init__(
            row_class=row_class or RowEtud,
            classes=classes,
            with_foot_titles=with_foot_titles,
            **kwargs,
        )
        self.add_etuds(etuds)

    def add_etuds(self, etuds: list[Identite]):
        "Ajoute des étudiants à la table"
        for etud in etuds:
            row = self.row_class(self, etud)
            row.add_etud_cols()
            self.add_row(row)


class RowEtud(tb.Row):
    "Ligne de la table d'étudiants"

    # pour le moment très simple, extensible (codes, liens bulletins, ...)
    def __init__(self, table: TableEtud, etud: Identite, *args, **kwargs):
        super().__init__(table, etud.id, *args, **kwargs)
        self.etud = etud
        self.target_url = etud.url_fiche()
        self.target_title = ""  # pour bulle aide sur lien

    def add_etud_cols(self):
        """Ajoute colonnes étudiant: codes, noms"""
        etud = self.etud
        self.table.group_titles.update(
            {
                "etud_codes": "Codes",
                "identite_detail": "",
                "identite_court": "",
            }
        )
        # --- Codes (seront cachés, mais exportés en excel)
        # self.add_cell("etudid", "etudid", etud.id, "etud_codes")
        # self.add_cell(
        #     "code_nip",
        #     "code_nip",
        #     etud.code_nip or "",
        #     "etud_codes",
        # )

        # --- Identité étudiant
        # url_bulletin = url_for(
        #     "notes.formsemestre_bulletinetud",
        #     scodoc_dept=g.scodoc_dept,
        #     formsemestre_id=res.formsemestre.id,
        #     etudid=etud.id,
        # )
        self.add_cell(
            "civilite_str",
            "Civ.",
            etud.civilite_str,
            "identite_detail",
            target=self.target_url,
            target_attrs={"class": "discretelink", "title": self.target_title},
        )
        self.add_cell(
            "nom_disp",
            "Nom",
            etud.nom_disp(),
            "identite_detail",
            data={"order": etud.sort_key},
            target=self.target_url,
            target_attrs={
                "class": "etudinfo discretelink",
                "id": str(etud.id),
                "title": self.target_title,
            },
        )
        self.add_cell(
            "prenom",
            "Prénom",
            etud.prenom,
            "identite_detail",
            target=self.target_url,
            target_attrs={"class": "discretelink", "title": self.target_title},
        )


def etuds_sorted_from_ids(etudids) -> list[Identite]:
    "Liste triée d'etuds à partir d'une collections d'etudids"
    etuds = [Identite.get_etud(etudid) for etudid in etudids]
    return sorted(etuds, key=lambda etud: etud.sort_key)


def html_table_etuds(etudids) -> str:
    """Table HTML simple des étudiants indiqués"""
    etuds = etuds_sorted_from_ids(etudids)
    table = TableEtud(etuds)
    return table.html()


class RowEtudWithInfos(RowEtud):
    """Ligne de la table d'étudiants avec plus d'informations:
    département, formsemestre, codes, boursier
    """

    def __init__(
        self,
        table: TableEtud,
        etud: Identite,
        formsemestre: FormSemestre,
        inscription: FormSemestreInscription,
        *args,
        **kwargs,
    ):
        super().__init__(table, etud, *args, **kwargs)
        self.formsemestre = formsemestre
        self.inscription = inscription

    def add_etud_cols(self):
        """Ajoute colonnes étudiant: codes, noms"""
        self.add_cell("dept", "Dépt.", self.etud.departement.acronym, "identite_detail")
        self.add_cell(
            "formsemestre",
            "Semestre",
            f"""{self.formsemestre.titre_formation()} {
                            ('S'+str(self.formsemestre.semestre_id))
                            if self.formsemestre.semestre_id > 0 else ''}
                        """,
            "identite_detail",
        )
        self.add_cell("code_nip", "NIP", self.etud.code_nip or "", "identite_detail")
        super().add_etud_cols()
        self.add_cell(
            "etat",
            "État",
            self.inscription.etat,
            "inscription",
        )
        self.add_cell(
            "boursier",
            "Boursier",
            "O" if self.etud.boursier else "N",
            "identite_infos",
        )


class TableEtudWithInfos(TableEtud):
    """Table d'étudiants avec formsemestre et inscription"""

    def add_formsemestre(self, formsemestre: FormSemestre):
        "Ajoute les étudiants de ce semestre à la table"
        etuds = formsemestre.get_inscrits(order=True, include_demdef=True)
        for etud in etuds:
            row = self.row_class(
                self, etud, formsemestre, formsemestre.etuds_inscriptions.get(etud.id)
            )
            row.add_etud_cols()
            self.add_row(row)


def table_etudiants_courants(formsemestres: list[FormSemestre]) -> TableEtud:
    """Table des étudiants des formsemestres indiqués"""
    if not formsemestres:
        raise ScoValueError("Aucun semestre en cours")
    table = TableEtudWithInfos(row_class=RowEtudWithInfos)
    for formsemestre in formsemestres:
        table.add_formsemestre(formsemestre)
    return table