########################################## Formsemestres ##############################################################
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_permission_required
from app.api.tools import get_etu_from_etudid_or_nip_or_ine
from app.models import FormSemestre, FormSemestreEtape
from app.scodoc.sco_bulletins import get_formsemestre_bulletin_etud_json
from app.scodoc.sco_bulletins_json import make_json_formsemestre_bulletinetud
from app.scodoc.sco_permissions import Permission
from app.scodoc.sco_pvjury import formsemestre_pvjury


@bp.route("/formsemestre/<int:formsemestre_id>", methods=["GET"])
@token_permission_required(Permission.APIView)
def formsemestre(formsemestre_id: int):
    """
    Retourne l'information sur le formsemestre correspondant au formsemestre_id

    formsemestre_id : l'id d'un formsemestre

    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 tous les formsemestres
    formsemetre = models.FormSemestre.query.filter_by(id=formsemestre_id).first_or_404()

    # Mise en forme des données
    data = formsemetre.to_dict()

    return jsonify(data)


@bp.route("/formsemestre/apo/<string:etape_apo>", methods=["GET"])
@token_permission_required(Permission.APIView)
def formsemestre_apo(etape_apo: str):
    """
    Retourne les informations sur les formsemestres

    etape_apo : l'id d'une étape apogée

    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": []
        }
    """
    formsemestres = FormSemestre.query.filter(
        FormSemestreEtape.etape_apo == etape_apo,
        FormSemestreEtape.formsemestre_id == FormSemestre.id,
    )

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


@bp.route(
    "/formsemestre/<int:formsemestre_id>/etudiant/etudid/<int:etudid>/bulletin",
    methods=["GET"],
)
@bp.route(
    "/formsemestre/<int:formsemestre_id>/etudiant/nip/<int:nip>/bulletin",
    methods=["GET"],
)
@bp.route(
    "/formsemestre/<int:formsemestre_id>/etudiant/ine/<int:ine>/bulletin",
    methods=["GET"],
)
@token_permission_required(Permission.APIView)
def etudiant_bulletin(
    formsemestre_id,
    etudid: int = None,
    nip: int = None,
    ine: int = None,
):
    """
    Retourne le bulletin de note d'un étudiant

    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 :
        {
           "etudid":1,
           "formsemestre_id":1,
           "date":"2022-04-27T10:44:47.448094",
           "publie":true,
           "etapes":[

           ],
           "etudiant":{
              "etudid":1,
              "code_nip":"1",
              "code_ine":"1",
              "nom":"COSTA",
              "prenom":"Sacha",
              "civilite":"",
              "photo_url":"/ScoDoc/TAPI/Scolarite/get_photo_image?etudid=1&amp;size=small",
              "email":"SACHA.COSTA@example.com",
              "emailperso":"",
              "sexe":""
           },
           "note":{
              "value":"10.60",
              "min":"-",
              "max":"-",
              "moy":"-"
           },
           "rang":{
              "value":"10",
              "ninscrits":16
           },
           "rang_group":[
              {
                 "group_type":"TD",
                 "group_name":"",
                 "value":"",
                 "ninscrits":""
              }
           ],
           "note_max":{
              "value":20
           },
           "bonus_sport_culture":{
              "value":0.0
           },
           "ue":[
              {
                 "id":1,
                 "numero":"1",
                 "acronyme":"RT1.1",
                 "titre":"Administrer les r\u00e9seaux et l\u2019Internet",
                 "note":{
                    "value":"08.50",
                    "min":"06.00",
                    "max":"16.50",
                    "moy":"11.31"
                 },
                 "rang":"12",
                 "effectif":16,
                 "ects":"12",
                 "code_apogee":"",
                 "module":[
                    {
                       "id":1,
                       "code":"R101",
                       "coefficient":1.0,
                       "numero":10,
                       "titre":"Initiation aux r\u00e9seaux informatiques",
                       "abbrev":"Init aux r\u00e9seaux informatiques",
                       "note":{
                          "value":"12.00",
                          "moy":"-",
                          "max":"-",
                          "min":"-",
                          "nb_notes":"-",
                          "nb_missing":"-",
                          "nb_valid_evals":"-"
                       },
                       "code_apogee":"",
                       "evaluation":[
                          {
                             "jour":"2022-04-20",
                             "heure_debut":"08:00:00",
                             "heure_fin":"09:00:00",
                             "coefficient":1.0,
                             "evaluation_type":0,
                             "evaluation_id":1,
                             "description":"eval1",
                             "note":"12.00"
                          }
                       ]
                    },
                    ...
                 ]
              }
           ],
           "ue_capitalisee":[],
           "absences":{
              "nbabs":2,
              "nbabsjust":1
           },
           "appreciation":[]
        }
    """
    # Fonction utilisée : app.scodoc.sco_bulletins_json.make_json_formsemestre_bulletinetud()

    try:
        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)
    except:
        return error_response(
            409,
            message="La requête ne peut être traitée en l’état actuel.\n "
            "Veilliez vérifier que le nom de département est valide",
        )
    if etudid is None:
        # Récupération de l'étudiant
        try:
            etu = get_etu_from_etudid_or_nip_or_ine(etudid, nip, ine)
            etudid = etu.etudid
        except AttributeError:
            return error_response(
                409,
                message="La requête ne peut être traitée en l’état actuel.\n "
                "Veilliez vérifier que l'id de l'étudiant (etudid, nip, ine) est valide",
            )

    data = make_json_formsemestre_bulletinetud(formsemestre_id, etudid)

    return data


@bp.route("/formsemestre/<int:formsemestre_id>/bulletins", methods=["GET"])
@token_permission_required(Permission.APIView)
def bulletins(formsemestre_id: int):
    """
    Retourne les bulletins d'un formsemestre donné

    formsemestre_id : l'id d'un formesemestre

    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
                }
              }
            },
            ...
        ]
    """
    # Fonction utilisée : app.scodoc.sco_bulletins.get_formsemestre_bulletin_etud_json()

    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)

    etuds = formsemestre.etuds

    data = []
    for etu in etuds:
        bul_etu = get_formsemestre_bulletin_etud_json(formsemestre, etu)
        data.append(bul_etu.json)

    return jsonify(data)


@bp.route("/formsemestre/<int:formsemestre_id>/jury", methods=["GET"])
@token_permission_required(Permission.APIView)
def jury(formsemestre_id: int):
    """
    Retourne le récapitulatif des décisions jury

    formsemestre_id : l'id d'un formsemestre

    Exemple de résultat :

    """
    # Fonction utilisée : app.scodoc.sco_pvjury.formsemestre_pvjury()

    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)

    data = formsemestre_pvjury(formsemestre_id)

    # try:
    #     # Utilisation de la fonction formsemestre_pvjury
    #     data = formsemestre_pvjury(formsemestre_id)
    # except AttributeError:
    #     return error_response(
    #         409,
    #         message="La requête ne peut être traitée en l’état actuel. \n"
    #         "Veillez vérifier la conformité du 'formation_id'",
    #     )

    return jsonify(data)


@bp.route(
    "/formsemestre/<int:formsemestre_id>/programme",
    methods=["GET"],
)
@token_permission_required(Permission.APIView)
def semestre_index(formsemestre_id: int):
    """
    Retourne la liste des Ues, ressources et SAE d'un semestre

    dept : l'acronym d'un département
    formsemestre_id : l'id d'un formesemestre

    Exemple de résultat :
        {
          "ues": [
            {
              "type": 0,
              "formation_id": 1,
              "ue_code": "UCOD11",
              "id": 1,
              "ects": 12.0,
              "acronyme": "RT1.1",
              "is_external": false,
              "numero": 1,
              "code_apogee": "",
              "titre": "Administrer les r\u00e9seaux et l\u2019Internet",
              "coefficient": 0.0,
              "semestre_idx": 1,
              "color": "#B80004",
              "ue_id": 1
            },
            ...
          ],
          "ressources": [
            {
              "titre": "Fondamentaux de la programmation",
              "coefficient": 1.0,
              "module_type": 2,
              "id": 17,
              "ects": null,
              "abbrev": null,
              "ue_id": 3,
              "code": "R107",
              "formation_id": 1,
              "heures_cours": 0.0,
              "matiere_id": 3,
              "heures_td": 0.0,
              "semestre_id": 1,
              "heures_tp": 0.0,
              "numero": 70,
              "code_apogee": "",
              "module_id": 17
            },
            ...
          ],
          "saes": [
            {
              "titre": "Se pr\u00e9senter sur Internet",
              "coefficient": 1.0,
              "module_type": 3,
              "id": 14,
              "ects": null,
              "abbrev": null,
              "ue_id": 3,
              "code": "SAE14",
              "formation_id": 1,
              "heures_cours": 0.0,
              "matiere_id": 3,
              "heures_td": 0.0,
              "semestre_id": 1,
              "heures_tp": 0.0,
              "numero": 40,
              "code_apogee": "",
              "module_id": 14
            },
            ...
          ]
        }
    """

    formsemestre = models.FormSemestre.query.filter_by(
        id=formsemestre_id
    ).first_or_404()

    ues = formsemestre.query_ues()

    ues_dict = []
    ressources = []
    saes = []

    for ue in ues:
        ues_dict.append(ue.to_dict())
        ressources = ue.get_ressources()
        saes = ue.get_saes()

    data_ressources = []
    for ressource in ressources:
        data_ressources.append(ressource.to_dict())

    data_saes = []
    for sae in saes:
        data_saes.append(sae.to_dict())

    data = {
        "ues": ues_dict,
        "ressources": data_ressources,
        "saes": data_saes,
    }

    return data
