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

"""Jury BUT: table synthèse résultats semestre / PV
"""
from flask import g, request, url_for

from openpyxl.styles import Font, Border, Side, Alignment, PatternFill

from app import log
from app.but import jury_but
from app.but.cursus_but import but_ects_valides
from app.models.etudiants import Identite
from app.models.formsemestre import FormSemestre
from app.scodoc.gen_tables import GenTable
from app.scodoc import sco_excel
from app.scodoc.sco_exceptions import ScoValueError
from app.scodoc import sco_preferences
from app.scodoc import sco_utils as scu


def _descr_cursus_but(etud: Identite) -> str:
    "description de la liste des semestres BUT suivis"
    # prend simplement tous les semestre de type APC, ce qui sera faux si
    # l'étudiant change de spécialité au sein du même département
    # (ce qui ne peut normalement pas se produire)
    inscriptions = sorted(
        [
            ins
            for ins in etud.formsemestre_inscriptions
            if ins.formsemestre.formation.is_apc()
        ],
        key=lambda i: i.formsemestre.date_debut,
    )
    indices = [
        ins.formsemestre.semestre_id if ins.formsemestre.semestre_id is not None else -1
        for ins in inscriptions
    ]

    return ", ".join(f"S{indice}" for indice in indices)


def pvjury_page_but(formsemestre_id: int, fmt="html"):
    """Page récapitulant les décisions de jury BUT
    formsemestre peut être pair ou impair
    """
    formsemestre = FormSemestre.get_formsemestre(formsemestre_id)
    assert formsemestre.formation.is_apc()
    title = "Procès-verbal de jury BUT"
    if fmt == "html":
        line_sep = "<br>"
    else:
        line_sep = "\n"
    rows, titles = pvjury_table_but(formsemestre, line_sep=line_sep)
    if fmt.startswith("xls"):
        titles.update(
            {
                "etudid": "etudid",
                "code_nip": "nip",
                "code_ine": "ine",
                "ects_but": "Total ECTS BUT",
                "civilite": "Civ.",
                "nom": "Nom",
                "prenom": "Prénom",
            }
        )
    # Style excel... passages à la ligne sur \n
    xls_style_base = sco_excel.excel_make_style()
    xls_style_base["alignment"] = Alignment(wrapText=True, vertical="top")
    tab = GenTable(
        base_url=f"{request.base_url}?formsemestre_id={formsemestre_id}",
        caption=title,
        columns_ids=titles.keys(),
        html_caption=title,
        html_class="pvjury_table_but table_leftalign",
        html_title=f"""<div style="margin-bottom: 8px;"><span
            style="font-size: 120%; font-weight: bold;">{title}</span>
        <span style="padding-left: 20px;">
        <a href="{url_for("notes.pvjury_page_but",
        scodoc_dept=g.scodoc_dept, formsemestre_id=formsemestre_id, fmt="xlsx")}"
         class="stdlink">version excel</a></span></div>

        """,
        html_with_td_classes=True,
        origin=f"Généré par {scu.sco_version.SCONAME} le {scu.timedate_human_repr()}",
        page_title=title,
        pdf_title=title,
        preferences=sco_preferences.SemPreferences(),
        rows=rows,
        table_id="formation_table_recap",
        titles=titles,
        xls_columns_width={
            "nom": 32,
            "cursus": 12,
            "ues": 32,
            "niveaux": 32,
            "decision_but": 14,
            "diplome": 17,
            "devenir": 8,
            "observations": 12,
        },
        xls_style_base=xls_style_base,
    )
    return tab.make_page(fmt=fmt, javascripts=["js/etud_info.js"], init_qtip=True)


def pvjury_table_but(
    formsemestre: FormSemestre,
    etudids: list[int] = None,
    line_sep: str = "\n",
    only_diplome=False,
    anonymous=False,
    with_paragraph_nom=False,
) -> tuple[list[dict], dict]:
    """Table avec résultats jury BUT pour PV.
    Si etudids est None, prend tous les étudiants inscrits.
    """
    # remplace pour le BUT la fonction sco_pv_forms.pvjury_table
    annee_but = (formsemestre.semestre_id + 1) // 2
    referentiel_competence_id = formsemestre.formation.referentiel_competence_id
    if referentiel_competence_id is None:
        raise ScoValueError(
            "pas de référentiel de compétences associé à la formation de ce semestre !"
        )
    titles = {
        "nom_pv": "Code" if anonymous else "Nom",
        "cursus": "Cursus",
        "ects": "ECTS",
        "ues": "UE validées",
        "niveaux": "Niveaux de compétences validés",
        "decision_but": f"Décision BUT{annee_but}",
        "diplome": "Résultat au diplôme",
        "devenir": "Devenir",
        "observations": "Observations",
    }
    rows = []
    formsemestre_etudids = formsemestre.etuds_inscriptions.keys()
    if etudids is None:
        etudids = formsemestre_etudids
    for etudid in etudids:
        if not etudid in formsemestre_etudids:
            continue  # garde fou
        etud = Identite.get_etud(etudid)
        try:
            deca = jury_but.DecisionsProposeesAnnee(etud, formsemestre)
            if deca.annee_but != annee_but:  # wtf ?
                log(
                    f"pvjury_table_but: inconsistent annee_but {deca.annee_but} != {annee_but}"
                )
                continue
        except ScoValueError:
            deca = None

        ects_but_valides = but_ects_valides(etud, referentiel_competence_id)
        row = {
            "nom_pv": (
                etud.code_ine or etud.code_nip or etud.id
                if anonymous  # Mode anonyme: affiche INE ou sinon NIP, ou id
                else etud.etat_civil_pv(
                    line_sep=line_sep, with_paragraph=with_paragraph_nom
                )
            ),
            "_nom_pv_order": etud.sort_key,
            "_nom_pv_target_attrs": f'class="etudinfo" id="{etud.id}"',
            "_nom_pv_td_attrs": f'id="{etud.id}" class="etudinfo"',
            "_nom_pv_target": url_for(
                "scolar.fiche_etud",
                scodoc_dept=g.scodoc_dept,
                etudid=etud.id,
            ),
            "cursus": _descr_cursus_but(etud),
            "ects": f"""{deca.ects_annee():g}<br><br>Tot. {ects_but_valides:g}""",
            "_ects_xls": deca.ects_annee(),
            "ects_but": ects_but_valides,
            "ues": deca.descr_ues_validation(line_sep=line_sep) if deca else "-",
            "niveaux": (
                deca.descr_niveaux_validation(line_sep=line_sep) if deca else "-"
            ),
            "decision_but": deca.code_valide if deca else "",
            "devenir": (
                ", ".join([f"S{i}" for i in deca.get_autorisations_passage()])
                if deca
                else ""
            ),
            # pour exports excel seulement:
            "civilite": etud.civilite_etat_civil_str,
            "nom": etud.nom,
            "prenom": etud.prenom_etat_civil or etud.prenom or "",
            "etudid": etud.id,
            "code_nip": etud.code_nip,
            "code_ine": etud.code_ine,
        }
        if deca.valide_diplome() or not only_diplome:
            rows.append(row)

    rows.sort(key=lambda x: x["_nom_pv_order"])
    return rows, titles