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

"""
  ScoDoc 9 API : jury   WIP à compléter avec enregistrement décisions
"""

from flask import g, url_for
from flask_json import as_json
from flask_login import current_user, login_required

import app
from app import db, log
from app.api import api_bp as bp, api_web_bp, tools
from app.decorators import scodoc, permission_required
from app.scodoc.sco_exceptions import ScoException
from app.but import jury_but_results
from app.models import (
    ApcValidationAnnee,
    ApcValidationRCUE,
    FormSemestre,
    Identite,
    ScolarAutorisationInscription,
    ScolarFormSemestreValidation,
    ScolarNews,
)
from app.scodoc import sco_cache
from app.scodoc.sco_permissions import Permission
from app.scodoc.sco_utils import json_error


@bp.route("/formsemestre/<int:formsemestre_id>/decisions_jury")
@api_web_bp.route("/formsemestre/<int:formsemestre_id>/decisions_jury")
@login_required
@scodoc
@permission_required(Permission.ScoView)
@as_json
def decisions_jury(formsemestre_id: int):
    """Décisions du jury des étudiants du formsemestre."""
    # APC, pair:
    formsemestre: FormSemestre = FormSemestre.query.get(formsemestre_id)
    if formsemestre.formation.is_apc():
        app.set_sco_dept(formsemestre.departement.acronym)
        rows = jury_but_results.get_jury_but_results(formsemestre)
        return rows
    else:
        raise ScoException("non implemente")


def _news_delete_jury_etud(etud: Identite):
    "génère news sur effacement décision"
    # n'utilise pas g.scodoc_dept, pas toujours dispo en mode API
    url = url_for(
        "scolar.ficheEtud", scodoc_dept=etud.departement.acronym, etudid=etud.id
    )
    ScolarNews.add(
        typ=ScolarNews.NEWS_JURY,
        obj=etud.id,
        text=f"""Suppression décision jury pour <a href="{url}">{etud.nomprenom}</a>""",
        url=url,
    )


@bp.route(
    "/etudiant/<int:etudid>/jury/validation_ue/<int:validation_id>/delete",
    methods=["POST"],
)
@api_web_bp.route(
    "/etudiant/<int:etudid>/jury/validation_ue/<int:validation_id>/delete",
    methods=["POST"],
)
@login_required
@scodoc
@permission_required(Permission.ScoView)
@as_json
def validation_ue_delete(etudid: int, validation_id: int):
    "Efface cette validation"
    return _validation_ue_delete(etudid, validation_id)


@bp.route(
    "/etudiant/<int:etudid>/jury/validation_formsemestre/<int:validation_id>/delete",
    methods=["POST"],
)
@api_web_bp.route(
    "/etudiant/<int:etudid>/jury/validation_formsemestre/<int:validation_id>/delete",
    methods=["POST"],
)
@login_required
@scodoc
@permission_required(Permission.ScoView)
@as_json
def validation_formsemestre_delete(etudid: int, validation_id: int):
    "Efface cette validation"
    # c'est la même chose (formations classiques)
    return _validation_ue_delete(etudid, validation_id)


def _validation_ue_delete(etudid: int, validation_id: int):
    "Efface cette validation (semestres classiques ou UEs)"
    etud = tools.get_etud(etudid)
    if etud is None:
        return "étudiant inconnu", 404
    validation = ScolarFormSemestreValidation.query.filter_by(
        id=validation_id, etudid=etudid
    ).first_or_404()
    # Vérification de la permission:
    # A le droit de supprimer cette validation: le chef de dept ou quelqu'un ayant
    # le droit de saisir des décisions de jury dans le formsemestre concerné s'il y en a un
    # (c'est le cas pour les validations de jury, mais pas pour les "antérieures" non
    # rattachées à un formsemestre)
    if not g.scodoc_dept:  # accès API
        if not current_user.has_permission(Permission.ScoEtudInscrit):
            return json_error(403, "opération non autorisée (117)")
    else:
        if validation.formsemestre:
            if (
                validation.formsemestre.dept_id != g.scodoc_dept_id
            ) or not validation.formsemestre.can_edit_jury():
                return json_error(403, "opération non autorisée (123)")
        elif not current_user.has_permission(Permission.ScoEtudInscrit):
            # Validation non rattachée à un semestre: on doit être chef
            return json_error(403, "opération non autorisée (126)")

    log(f"validation_ue_delete: etuid={etudid} {validation}")
    db.session.delete(validation)
    sco_cache.invalidate_formsemestre_etud(etud)
    db.session.commit()
    _news_delete_jury_etud(etud)
    return "ok"


@bp.route(
    "/etudiant/<int:etudid>/jury/autorisation_inscription/<int:validation_id>/delete",
    methods=["POST"],
)
@api_web_bp.route(
    "/etudiant/<int:etudid>/jury/autorisation_inscription/<int:validation_id>/delete",
    methods=["POST"],
)
@login_required
@scodoc
@permission_required(Permission.ScoEtudInscrit)
@as_json
def autorisation_inscription_delete(etudid: int, validation_id: int):
    "Efface cette validation"
    etud = tools.get_etud(etudid)
    if etud is None:
        return "étudiant inconnu", 404
    validation = ScolarAutorisationInscription.query.filter_by(
        id=validation_id, etudid=etudid
    ).first_or_404()
    log(f"autorisation_inscription_delete: etuid={etudid} {validation}")
    db.session.delete(validation)
    sco_cache.invalidate_formsemestre_etud(etud)
    db.session.commit()
    _news_delete_jury_etud(etud)
    return "ok"


@bp.route(
    "/etudiant/<int:etudid>/jury/validation_rcue/<int:validation_id>/delete",
    methods=["POST"],
)
@api_web_bp.route(
    "/etudiant/<int:etudid>/jury/validation_rcue/<int:validation_id>/delete",
    methods=["POST"],
)
@login_required
@scodoc
@permission_required(Permission.ScoEtudInscrit)
@as_json
def validation_rcue_delete(etudid: int, validation_id: int):
    "Efface cette validation"
    etud = tools.get_etud(etudid)
    if etud is None:
        return "étudiant inconnu", 404
    validation = ApcValidationRCUE.query.filter_by(
        id=validation_id, etudid=etudid
    ).first_or_404()
    log(f"validation_ue_delete: etuid={etudid} {validation}")
    db.session.delete(validation)
    sco_cache.invalidate_formsemestre_etud(etud)
    db.session.commit()
    _news_delete_jury_etud(etud)
    return "ok"


@bp.route(
    "/etudiant/<int:etudid>/jury/validation_annee_but/<int:validation_id>/delete",
    methods=["POST"],
)
@api_web_bp.route(
    "/etudiant/<int:etudid>/jury/validation_annee_but/<int:validation_id>/delete",
    methods=["POST"],
)
@login_required
@scodoc
@permission_required(Permission.ScoEtudInscrit)
@as_json
def validation_annee_but_delete(etudid: int, validation_id: int):
    "Efface cette validation"
    etud = tools.get_etud(etudid)
    if etud is None:
        return "étudiant inconnu", 404
    validation = ApcValidationAnnee.query.filter_by(
        id=validation_id, etudid=etudid
    ).first_or_404()
    log(f"validation_annee_but: etuid={etudid} {validation}")
    db.session.delete(validation)
    sco_cache.invalidate_formsemestre_etud(etud)
    db.session.commit()
    _news_delete_jury_etud(etud)
    return "ok"
