#################################################### Etudiants ########################################################

from flask import jsonify

import app
from app import models
from app.api import bp
from app.api.errors import error_response
from app.api.auth import token_auth, token_permission_required
from app.api.tools import get_etud_from_etudid_or_nip_or_ine
from app.models import FormSemestreInscription, FormSemestre, Identite
from app.scodoc import sco_bulletins
from app.scodoc import sco_groups
from app.scodoc.sco_permissions import Permission


@bp.route("/etudiants/courant", defaults={"long": False})
@bp.route("/etudiants/courant/long", defaults={"long": True})
@token_auth.login_required
@token_permission_required(Permission.APIView)
def etudiants_courant(long=False):
    """
    Liste des étudiants inscrits dans un formsemestre actuellement en cours.

    Exemple de résultat :
        [
            {
                "id": 1,
                "nip": 1,
                "nom": "MOREL",
                "prenom": "JACQUES",
                "civilite": "X",
            },
            {
                "id": 2,
                "nip": 2,
                "nom": "GILLES",
                "prenom": "MAXIME",
                "civilite": "X",
            },
            ...
        ]
    """
    etuds = Identite.query.filter(
        Identite.id == FormSemestreInscription.etudid,
        FormSemestreInscription.formsemestre_id == FormSemestre.id,
        FormSemestre.date_debut <= app.db.func.now(),
        FormSemestre.date_fin >= app.db.func.now(),
    )
    if long:
        data = [etud.to_dict_bul(include_urls=False) for etud in etuds]
    else:
        data = [etud.to_dict_short() for etud in etuds]
    return jsonify(data)


@bp.route("/etudiant/etudid/<int:etudid>", methods=["GET"])
@bp.route("/etudiant/nip/<string:nip>", methods=["GET"])
@bp.route("/etudiant/ine/<string:ine>", methods=["GET"])
@token_auth.login_required
@token_permission_required(Permission.APIView)
def etudiant(etudid: int = None, nip: int = None, ine: int = None):
    """
    Retourne les informations de l'étudiant correspondant à l'id passé en paramètres.

    etudid : l'etudid d'un étudiant
    nip : le code nip d'un étudiant
    ine : le code ine d'un étudiant

    Exemple de résultat :
        {
          "civilite": "X",
          "code_ine": "1",
          "code_nip": "1",
          "date_naissance": "",
          "email": "SACHA.COSTA@example.com",
          "emailperso": "",
          "etudid": 1,
          "nom": "COSTA",
          "prenom": "SACHA",
          "nomprenom": "Sacha COSTA",
          "lieu_naissance": "",
          "dept_naissance": "",
          "nationalite": "",
          "boursier": "",
          "id": 1,
          "codepostaldomicile": "",
          "paysdomicile": "",
          "telephonemobile": "",
          "typeadresse": "domicile",
          "domicile": "",
          "villedomicile": "",
          "telephone": "",
          "fax": "",
          "description": ""
        }
    """
    # Récupération de l'étudiant
    etud = get_etud_from_etudid_or_nip_or_ine(etudid, nip, ine)
    if etud is None:
        return error_response(
            404,
            message="id de l'étudiant (etudid, nip, ine) inconnu",
        )
    # Mise en forme des données
    data = etud.to_dict_bul(include_urls=False)

    return jsonify(data)


@bp.route("/etudiant/etudid/<int:etudid>/formsemestres")
@bp.route("/etudiant/nip/<string:nip>/formsemestres")
@bp.route("/etudiant/ine/<string:ine>/formsemestres")
@token_auth.login_required
@token_permission_required(Permission.APIView)
def etudiant_formsemestres(etudid: int = None, nip: int = None, ine: int = None):
    """
    Retourne la liste des semestres qu'un étudiant a suivis, triés par ordre chronologique.

    etudid : l'etudid d'un étudiant
    nip : le code nip d'un étudiant
    ine : le code ine d'un étudiant

    Exemple de résultat :
        [
            {
              "date_fin": "31/08/2022",
              "resp_can_edit": false,
              "dept_id": 1,
              "etat": true,
              "resp_can_change_ens": true,
              "id": 1,
              "modalite": "FI",
              "ens_can_edit_eval": false,
              "formation_id": 1,
              "gestion_compensation": false,
              "elt_sem_apo": null,
              "semestre_id": 1,
              "bul_hide_xml": false,
              "elt_annee_apo": null,
              "titre": "Semestre test",
              "block_moyennes": false,
              "scodoc7_id": null,
              "date_debut": "01/09/2021",
              "gestion_semestrielle": false,
              "bul_bgcolor": "white",
              "formsemestre_id": 1,
              "titre_num": "Semestre test semestre 1",
              "date_debut_iso": "2021-09-01",
              "date_fin_iso": "2022-08-31",
              "responsables": []
            },
             ...
        ]
    """
    # Récupération de l'étudiant
    etud = get_etud_from_etudid_or_nip_or_ine(etudid, nip, ine)
    if etud is None:
        return error_response(
            404,
            message="id de l'étudiant (etudid, nip, ine) inconnu",
        )

    formsemestres = models.FormSemestre.query.filter(
        models.FormSemestreInscription.etudid == etud.id,
        models.FormSemestreInscription.formsemestre_id == models.FormSemestre.id,
    ).order_by(models.FormSemestre.date_debut)

    return jsonify([formsemestre.to_dict() for formsemestre in formsemestres])


@bp.route(
    "/etudiant/etudid/<int:etudid>/formsemestre/<int:formsemestre_id>/bulletin",
    methods=["GET"],
    defaults={"version": "long"},
)
@bp.route(
    "/etudiant/nip/<string:nip>/formsemestre/<int:formsemestre_id>/bulletin",
    methods=["GET"],
    defaults={"version": "long"},
)
@bp.route(
    "/etudiant/ine/<string:ine>/formsemestre/<int:formsemestre_id>/bulletin",
    methods=["GET"],
    defaults={"version": "long"},
)
@bp.route(
    "/etudiant/etudid/<int:etudid>/formsemestre/<int:formsemestre_id>/bulletin/short",
    methods=["GET"],
    defaults={"version": "short"},
)
@bp.route(
    "/etudiant/nip/<string:nip>/formsemestre/<int:formsemestre_id>/bulletin/short",
    methods=["GET"],
    defaults={"version": "short"},
)
@bp.route(
    "/etudiant/ine/<string:ine>/formsemestre/<int:formsemestre_id>/bulletin/short",
    methods=["GET"],
    defaults={"version": "short"},
)
@token_auth.login_required
@token_permission_required(Permission.APIView)
def etudiant_bulletin_semestre(
    formsemestre_id,
    etudid: int = None,
    nip: int = None,
    ine: int = None,
    version="long",
):
    """
    Retourne le bulletin d'un étudiant en fonction de son id et d'un semestre donné

    formsemestre_id : l'id d'un formsemestre
    etudid : l'etudid d'un étudiant
    nip : le code nip d'un étudiant
    ine : le code ine d'un étudiant
    Exemple de résultat :
        {
          "version": "0",
          "type": "BUT",
          "date": "2022-04-27T07:18:16.450634Z",
          "publie": true,
          "etudiant": {
            "civilite": "X",
            "code_ine": "1",
            "code_nip": "1",
            "date_naissance": "",
            "email": "SACHA.COSTA@example.com",
            "emailperso": "",
            "etudid": 1,
            "nom": "COSTA",
            "prenom": "SACHA",
            "nomprenom": "Sacha COSTA",
            "lieu_naissance": "",
            "dept_naissance": "",
            "nationalite": "",
            "boursier": "",
            "fiche_url": "/ScoDoc/TAPI/Scolarite/ficheEtud?etudid=1",
            "photo_url": "/ScoDoc/TAPI/Scolarite/get_photo_image?etudid=1&size=small",
            "id": 1,
            "codepostaldomicile": "",
            "paysdomicile": "",
            "telephonemobile": "",
            "typeadresse": "domicile",
            "domicile": "",
            "villedomicile": "",
            "telephone": "",
            "fax": "",
            "description": ""
          },
          "formation": {
            "id": 1,
            "acronyme": "BUT R&amp;T",
            "titre_officiel": "Bachelor technologique r\u00e9seaux et t\u00e9l\u00e9communications",
            "titre": "BUT R&amp;T"
          },
          "formsemestre_id": 1,
          "etat_inscription": "I",
          "options": {
            "show_abs": true,
            "show_abs_modules": false,
            "show_ects": true,
            "show_codemodules": false,
            "show_matieres": false,
            "show_rangs": true,
            "show_ue_rangs": true,
            "show_mod_rangs": true,
            "show_moypromo": false,
            "show_minmax": false,
            "show_minmax_mod": false,
            "show_minmax_eval": false,
            "show_coef": true,
            "show_ue_cap_details": false,
            "show_ue_cap_current": true,
            "show_temporary": true,
            "temporary_txt": "Provisoire",
            "show_uevalid": true,
            "show_date_inscr": true
          },
          "ressources": {
            "R101": {
              "id": 1,
              "titre": "Initiation aux r\u00e9seaux informatiques",
              "code_apogee": null,
              "url": "/ScoDoc/TAPI/Scolarite/Notes/moduleimpl_status?moduleimpl_id=1",
              "moyenne": {},
              "evaluations": [
                {
                  "id": 1,
                  "description": "eval1",
                  "date": "2022-04-20",
                  "heure_debut": "08:00",
                  "heure_fin": "09:00",
                  "coef": "01.00",
                  "poids": {
                    "RT1.1": 1.0,
                  },
                  "note": {
                    "value": "12.00",
                    "min": "00.00",
                    "max": "18.00",
                    "moy": "10.88"
                  },
                  "url": "/ScoDoc/TAPI/Scolarite/Notes/evaluation_listenotes?evaluation_id=1"
                }
              ]
            },
          },
          "saes": {
            "SAE11": {
              "id": 2,
              "titre": "Se sensibiliser \u00e0 l&apos;hygi\u00e8ne informatique et \u00e0 la cybers\u00e9curit\u00e9",
              "code_apogee": null,
              "url": "/ScoDoc/TAPI/Scolarite/Notes/moduleimpl_status?moduleimpl_id=2",
              "moyenne": {},
              "evaluations": []
            },
          },
          "ues": {
            "RT1.1": {
              "id": 1,
              "titre": "Administrer les r\u00e9seaux et l\u2019Internet",
              "numero": 1,
              "type": 0,
              "color": "#B80004",
              "competence": null,
              "moyenne": {
                "value": "08.50",
                "min": "06.00",
                "max": "16.50",
                "moy": "11.31",
                "rang": "12",
                "total": 16
              },
              "bonus": "00.00",
              "malus": "00.00",
              "capitalise": null,
              "ressources": {
                "R101": {
                  "id": 1,
                  "coef": 12.0,
                  "moyenne": "12.00"
                },
              },
              "saes": {
                "SAE11": {
                  "id": 2,
                  "coef": 16.0,
                  "moyenne": "~"
                },
              },
              "ECTS": {
                "acquis": 0.0,
                "total": 12.0
              }
            },
          "semestre": {
            "etapes": [],
            "date_debut": "2021-09-01",
            "date_fin": "2022-08-31",
            "annee_universitaire": "2021 - 2022",
            "numero": 1,
            "inscription": "",
            "groupes": [],
            "absences": {
              "injustifie": 1,
              "total": 2
            },
            "ECTS": {
              "acquis": 0,
              "total": 30.0
            },
            "notes": {
              "value": "10.60",
              "min": "02.40",
              "moy": "11.05",
              "max": "17.40"
            },
            "rang": {
              "value": "10",
              "total": 16
            }
          }
        }
    """
    formsemestre = models.FormSemestre.query.filter_by(
        id=formsemestre_id
    ).first_or_404()

    dept = models.Departement.query.filter_by(id=formsemestre.dept_id).first_or_404()

    app.set_sco_dept(dept.acronym)

    etud = get_etud_from_etudid_or_nip_or_ine(etudid, nip, ine)
    if etud is None:
        return error_response(
            404,
            message="id de l'étudiant (etudid, nip, ine) inconnu",
        )
    return sco_bulletins.get_formsemestre_bulletin_etud_json(
        formsemestre, etud, version
    )


@bp.route(
    "/etudiant/etudid/<int:etudid>/formsemestre/<int:formsemestre_id>/groups",
    methods=["GET"],
)
@bp.route(
    "/etudiant/nip/<string:nip>/formsemestre/<int:formsemestre_id>/groups",
    methods=["GET"],
)
@bp.route(
    "/etudiant/ine/<string:ine>/formsemestre/<int:formsemestre_id>/groups",
    methods=["GET"],
)
@token_auth.login_required
@token_permission_required(Permission.APIView)
def etudiant_groups(
    formsemestre_id: int, etudid: int = None, nip: int = None, ine: int = None
):
    """
    Retourne la liste des groupes auxquels appartient l'étudiant dans le formsemestre indiqué

    formsemestre_id : l'id d'un formsemestre
    etudid : l'etudid d'un étudiant
    nip : le code nip d'un étudiant
    ine : le code ine d'un étudiant

    Exemple de résultat :
                [
                  {
                    "partition_id": 1,
                    "id": 1,
                    "formsemestre_id": 1,
                    "partition_name": null,
                    "numero": 0,
                    "bul_show_rank": false,
                    "show_in_lists": true,
                    "group_id": 1,
                    "group_name": null
                  },
                  {
                    "partition_id": 2,
                    "id": 2,
                    "formsemestre_id": 1,
                    "partition_name": "TD",
                    "numero": 1,
                    "bul_show_rank": false,
                    "show_in_lists": true,
                    "group_id": 2,
                    "group_name": "A"
                  }
                ]
    """
    if etudid is None:
        etud = get_etud_from_etudid_or_nip_or_ine(etudid, nip, ine)
        if etud is None:
            return error_response(
                404,
                message="id de l'étudiant (etudid, nip, ine) inconnu",
            )
        etudid = etud.etudid

    # Récupération du formsemestre
    sem = models.FormSemestre.query.filter_by(id=formsemestre_id).first_or_404()
    dept = models.Departement.query.get(sem.dept_id)
    app.set_sco_dept(dept.acronym)
    data = sco_groups.get_etud_groups(etudid, sem.id)

    return jsonify(data)