# -*- mode: python -*-
# -*- coding: utf-8 -*-

##############################################################################
#
# Gestion scolarite IUT
#
# Copyright (c) 1999 - 2023 Emmanuel Viennet.  All rights reserved.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#
#   Emmanuel Viennet      emmanuel.viennet@viennet.net
#
##############################################################################

"""Table recap formation (avec champs éditables)
"""
import io
from zipfile import ZipFile, BadZipfile

from flask import Response
from flask import send_file, url_for
from flask import g, request
from flask_login import current_user

from app.models import Formation, FormSemestre, UniteEns, Module
from app.models.formations import Matiere

from app.scodoc.gen_tables import GenTable
from app.scodoc.sco_permissions import Permission
from app.scodoc import sco_preferences
import app.scodoc.sco_utils as scu


# ---- Table recap formation
def formation_table_recap(formation_id, format="html") -> Response:
    """Table recapitulant formation."""
    T = []
    formation = Formation.query.get_or_404(formation_id)
    ues = formation.ues.order_by(UniteEns.semestre_idx, UniteEns.numero)
    can_edit = current_user.has_permission(Permission.ScoChangeFormation)
    li = 0
    for ue in ues:
        # L'UE
        T.append(
            {
                "sem": f"S{ue.semestre_idx}" if ue.semestre_idx is not None else "-",
                "_sem_order": f"{li:04d}",
                "code": ue.acronyme,
                "titre": ue.titre or "",
                "_titre_target": url_for(
                    "notes.ue_edit",
                    scodoc_dept=g.scodoc_dept,
                    ue_id=ue.id,
                )
                if can_edit
                else None,
                "apo": ue.code_apogee or "",
                "_apo_td_attrs": f""" data-oid="{ue.id}" data-value="{ue.code_apogee or ''}" """,
                "coef": ue.coefficient or "",
                "ects": ue.ects,
                "_css_row_class": "ue",
            }
        )
        li += 1
        matieres = ue.matieres.order_by(Matiere.numero)
        for mat in matieres:
            modules = mat.modules.order_by(Module.numero)
            for mod in modules:
                nb_moduleimpls = mod.modimpls.count()
                # le module (ou ressource ou sae)
                T.append(
                    {
                        "sem": f"S{mod.semestre_id}"
                        if mod.semestre_id is not None
                        else "-",
                        "_sem_order": f"{li:04d}",
                        "code": mod.code,
                        "titre": mod.abbrev or mod.titre,
                        "_titre_target": url_for(
                            "notes.module_edit",
                            scodoc_dept=g.scodoc_dept,
                            module_id=mod.id,
                        )
                        if can_edit
                        else None,
                        "apo": mod.code_apogee,
                        "_apo_td_attrs": f""" data-oid="{mod.id}" data-value="{mod.code_apogee or ''}" """,
                        "coef": mod.coefficient,
                        "nb_moduleimpls": nb_moduleimpls,
                        "heures_cours": mod.heures_cours,
                        "heures_td": mod.heures_td,
                        "heures_tp": mod.heures_tp,
                        "_css_row_class": f"mod {mod.type_abbrv()}",
                    }
                )
    columns_ids = [
        "sem",
        "code",
        "apo",
        # "mat", inutile d'afficher la matière
        "titre",
        "ects",
        "nb_moduleimpls",
        "heures_cours",
        "heures_td",
        "heures_tp",
    ]
    if not formation.is_apc():
        columns_ids.insert(columns_ids.index("ects"), "coef")
    titles = {
        "ue": "UE",
        "mat": "Matière",
        "titre": "Titre",
        "code": "Code",
        "apo": "Apo",
        "coef": "Coef.",
        "sem": "Sem.",
        "nb_moduleimpls": "Nb utilisé",
        "heures_cours": "Cours (h)",
        "heures_td": "TD (h)",
        "heures_tp": "TP (h)",
        "ects": "ECTS",
    }

    title = f"""Formation {formation.titre} ({formation.acronyme})
        [version {formation.version}] code {formation.formation_code}"""
    html_class = "stripe cell-border compact hover order-column formation_table_recap"
    if current_user.has_permission(Permission.ScoEditApo):
        html_class += " apo_editable"

    tab = GenTable(
        columns_ids=columns_ids,
        rows=T,
        titles=titles,
        origin=f"Généré par {scu.sco_version.SCONAME} le {scu.timedate_human_repr()}",
        caption=title,
        html_caption=title,
        html_class=html_class,
        html_class_ignore_default=True,
        html_table_attrs=f"""
        data-apo_ue_save_url="{url_for('notes.ue_set_apo', scodoc_dept=g.scodoc_dept)}" 
        data-apo_mod_save_url="{url_for('notes.module_set_apo', scodoc_dept=g.scodoc_dept)}" 
        """,
        html_with_td_classes=True,
        base_url=f"{request.base_url}?formation_id={formation_id}",
        page_title=title,
        html_title=f"<h2>{title}</h2>",
        pdf_title=title,
        preferences=sco_preferences.SemPreferences(),
        table_id="formation_table_recap",
    )
    return tab.make_page(format=format, javascripts=["js/formation_recap.js"])


def export_recap_formations_annee_scolaire(annee_scolaire):
    """Exporte un zip des recap (excel) des formatons de tous les semestres
    de l'année scolaire indiquée.
    """
    annee_scolaire = int(annee_scolaire)
    data = io.BytesIO()
    zip_file = ZipFile(data, "w")
    formsemestres = FormSemestre.query.filter_by(dept_id=g.scodoc_dept_id).filter(
        FormSemestre.date_debut >= scu.date_debut_anne_scolaire(annee_scolaire),
        FormSemestre.date_debut <= scu.date_fin_anne_scolaire(annee_scolaire),
    )
    formation_ids = {formsemestre.formation.id for formsemestre in formsemestres}
    for formation_id in formation_ids:
        formation = Formation.query.get(formation_id)
        xls = formation_table_recap(formation_id, format="xlsx").data
        filename = (
            scu.sanitize_filename(formation.get_titre_version()) + scu.XLSX_SUFFIX
        )
        zip_file.writestr(filename, xls)
    zip_file.close()
    data.seek(0)
    return send_file(
        data,
        mimetype="application/zip",
        download_name=f"formations-{g.scodoc_dept}-{annee_scolaire}-{annee_scolaire+1}.zip",
        as_attachment=True,
    )
