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

##############################################################################
#
# Gestion scolarite IUT
#
# Copyright (c) 1999 - 2024 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
#
##############################################################################

"""Ajout/Modification/Suppression matieres
"""
import flask
from flask import flash, g, render_template, request, url_for

from app import db, log
from app.models import Matiere, UniteEns

import app.scodoc.sco_utils as scu

from app.scodoc.TrivialFormulator import TrivialFormulator, tf_error_message
from app.scodoc.sco_exceptions import (
    ScoValueError,
    ScoLockedFormError,
    ScoNonEmptyFormationObject,
)


def matiere_create(ue_id=None):
    """Formulaire création d'une matiere"""
    ue: UniteEns = UniteEns.query.get_or_404(ue_id)
    default_numero = max([mat.numero for mat in ue.matieres] or [9]) + 1
    H = [
        f"""<h2>Création d'une matière dans l'UE {ue.titre or ''} ({ue.acronyme})</h2>
        <p class="help">Les matières sont des groupes de modules dans une UE
d'une formation donnée. Les matières servent surtout pour la
présentation (bulletins, etc) mais <em>n'ont pas de rôle dans le calcul
des notes.</em>
</p>

<p class="help">Si votre formation n'utilise pas la notion de
"matières", créez une matière par UE, et donnez lui le même nom que l'UE
(en effet, tout module doit appartenir à une matière).
</p>

<p class="help">Comme les UE, les matières n'ont pas de coefficient
associé.
</p>""",
    ]
    tf = TrivialFormulator(
        request.base_url,
        scu.get_request_args(),
        (
            ("ue_id", {"input_type": "hidden", "default": ue_id}),
            (
                "titre",
                {
                    "size": 30,
                    "explanation": "nom de la matière.",
                },
            ),
            (
                "numero",
                {
                    "size": 2,
                    "explanation": "numéro (1,2,3,4...) pour affichage",
                    "type": "int",
                    "default": default_numero,
                    "allow_null": False,
                },
            ),
        ),
        submitlabel="Créer cette matière",
    )

    dest_url = url_for(
        "notes.ue_table", scodoc_dept=g.scodoc_dept, formation_id=ue.formation_id
    )

    if tf[0] == 0:
        return render_template(
            "sco_page.j2", title="Création d'une matière", content="\n".join(H) + tf[1]
        )
    if tf[0] == -1:
        return flask.redirect(dest_url)
    # check unicity
    nb_mats = Matiere.query.filter_by(ue_id=ue_id, titre=tf[2]["titre"]).count()
    if nb_mats:
        return render_template(
            "sco_page.j2",
            title="Création d'une matière",
            content=(
                "\n".join(H)
                + tf_error_message("Titre de matière déjà existant dans cette UE")
                + tf[1]
            ),
        )
    Matiere.create_from_dict(tf[2])
    return flask.redirect(dest_url)


def matiere_delete(matiere_id=None):
    """Form delete matière"""
    matiere = Matiere.get_instance(matiere_id)
    if not matiere.can_be_deleted():
        # il y a au moins un modimpl dans un module de cette matière
        raise ScoNonEmptyFormationObject(
            "Matière",
            matiere.titre,
            dest_url=url_for(
                "notes.ue_table",
                formation_id=matiere.ue.formation_id,
                semestre_idx=matiere.ue.semestre_idx,
                scodoc_dept=g.scodoc_dept,
            ),
        )

    H = [
        f"""<h2>Suppression de la matière {matiere.titre}
        dans l'UE {matiere.ue.acronyme}</h2>""",
    ]
    dest_url = url_for(
        "notes.ue_table",
        scodoc_dept=g.scodoc_dept,
        formation_id=matiere.ue.formation_id,
    )
    tf = TrivialFormulator(
        request.base_url,
        scu.get_request_args(),
        (("matiere_id", {"input_type": "hidden"}),),
        initvalues=matiere.to_dict(),
        submitlabel="Confirmer la suppression",
        cancelbutton="Annuler",
    )
    if tf[0] == 0:
        return render_template(
            "sco_page.j2",
            title="Suppression d'une matière",
            content="\n".join(H) + tf[1],
        )
    if tf[0] == -1:
        return flask.redirect(dest_url)

    matiere.delete()
    return flask.redirect(dest_url)


def matiere_edit(matiere_id=None):
    """Form edit matiere"""
    matiere: Matiere = Matiere.get_instance(matiere_id)
    if matiere.is_locked():
        raise ScoLockedFormError()
    ue = matiere.ue
    formation = ue.formation
    ues = matiere.ue.formation.ues
    ue_names = [f"{u.acronyme} ({u.titre or ''})" for u in ues]
    ue_ids = [u.id for u in ues]
    H = [
        f"""<h2>Modification de la matière {matiere.titre or 'sans titre'}
        (formation ({formation.acronyme}, version {formation.version})</h2>""",
    ]
    help_msg = """<p class="help">Les matières sont des groupes de modules dans une UE
d'une formation donnée. Les matières servent surtout pour la
présentation (bulletins, etc) mais <em>n'ont pas de rôle dans le calcul
des notes.</em>
</p>

<p class="help">Si votre formation n'utilise pas la notion de
"matières", créez une matière par UE, et donnez lui le même nom que l'UE
(en effet, tout module doit appartenir à une matière).
</p>

<p class="help">Comme les UE, les matières n'ont pas de coefficient
associé.
</p>"""
    tf = TrivialFormulator(
        request.base_url,
        scu.get_request_args(),
        (
            ("matiere_id", {"input_type": "hidden"}),
            (
                "ue_id",
                {
                    "input_type": "menu",
                    "allowed_values": ue_ids,
                    "labels": ue_names,
                    "title": "UE",
                },
            ),
            ("titre", {"size": 30, "explanation": "nom de cette matière"}),
            (
                "numero",
                {
                    "size": 2,
                    "explanation": "numéro (1,2,3,4...) pour affichage",
                    "type": "int",
                },
            ),
        ),
        initvalues=matiere.to_dict(),
        submitlabel="Modifier les valeurs",
    )

    dest_url = url_for(
        "notes.ue_table",
        scodoc_dept=g.scodoc_dept,
        formation_id=formation.id,
    )
    if tf[0] == 0:
        return render_template(
            "sco_page.j2",
            title="Modification d'une matière",
            content="\n".join(H) + tf[1] + help_msg,
        )
    elif tf[0] == -1:
        return flask.redirect(dest_url)
    else:
        # check unicity
        mats = Matiere.query.filter_by(ue_id=tf[2]["ue_id"], titre=tf[2]["titre"]).all()
        if len(mats) > 1 or (len(mats) == 1 and mats[0].id != matiere_id):
            return render_template(
                "sco_page.j2",
                title="Modification d'une matière",
                content=(
                    "\n".join(H)
                    + tf_error_message("Titre de matière déjà existant dans cette UE")
                    + tf[1]
                ),
            )

        modif = False
        # changement d'UE ?
        if tf[2]["ue_id"] != ue.id:
            log(f"attaching mat {matiere_id} to new UE id={tf[2]['ue_id']}")
            new_ue = UniteEns.get_ue(tf[2]["ue_id"])
            if new_ue.formation_id != formation.id:
                raise ScoValueError("UE does not belong to the same formation")
            matiere.ue = new_ue
            modif = True
        modif |= matiere.from_dict(tf[2])
        if modif:
            db.session.commit()
            matiere.ue.formation.invalidate_cached_sems()
            flash("Matière modifiée", "info")
        return flask.redirect(dest_url)