# -*- coding: UTF-8 -*
"""ScoDoc Flask views"""

import datetime
from functools import cached_property

from flask import Blueprint
from flask import g, current_app, request
from flask_login import current_user

from app import db
from app.models import Identite
from app.models.formsemestre import FormSemestre
from app.scodoc import notesdb as ndb
from app.scodoc import sco_assiduites
from app.scodoc import sco_formsemestre_status
from app.scodoc import sco_preferences
from app.scodoc.html_sidebar import retreive_formsemestre_from_request
from app.scodoc.sco_permissions import Permission
from app.scodoc import sco_utils as scu
import sco_version

scodoc_bp = Blueprint("scodoc", __name__)
scolar_bp = Blueprint("scolar", __name__)
notes_bp = Blueprint("notes", __name__)
users_bp = Blueprint("users", __name__)
absences_bp = Blueprint("absences", __name__)
assiduites_bp = Blueprint("assiduites", __name__)


# Cette fonction est bien appelée avant toutes les requêtes
# de tous les blueprints
# mais apparemment elle n'a pas acces aux arguments
@scodoc_bp.before_app_request
def start_scodoc_request():
    """Affecte toutes les requêtes, de tous les blueprints"""
    # current_app.logger.info(f"start_scodoc_request")
    ndb.open_db_connection()
    if current_user and current_user.is_authenticated:
        current_user.last_seen = datetime.datetime.utcnow()
        db.session.commit()
    # caches locaux (durée de vie=la requête en cours)
    g.stored_get_formsemestre = {}
    # g.stored_etud_info = {} optim en cours, voir si utile


@scodoc_bp.teardown_app_request
def close_dept_db_connection(arg):
    # current_app.logger.info("close_db_connection")
    ndb.close_db_connection()


class ScoData:
    """Classe utilisée pour passer des valeurs aux vues (templates)"""

    def __init__(self, etud: Identite = None, formsemestre: FormSemestre = None):
        # Champs utilisés par toutes les pages ScoDoc (sidebar, en-tête)
        self.Permission = Permission
        self.scu = scu
        self.SCOVERSION = sco_version.SCOVERSION
        self._init_etud = etud
        self._init_formsemestre = formsemestre
        # les comptes d'absences sont initialisés lors de l'accès à etud_cur_sem
        self.nb_abs_nj = 0
        self.nb_abs_just = 0
        self.nb_abs = 0
        # .etud, .formsemestre, etc. sont des cached_property
        # car ScoData() est créé par @context_processor
        # AVANT le décorateur scodoc qui initialise g.scodoc_xxx

    @cached_property
    def etud(self) -> Identite | None:
        "Informations étudiant courant, si sélectionné"
        if self._init_etud is None:
            etudid = g.get("etudid", None)
            if etudid is None:
                if request.method == "GET":
                    etudid = request.args.get("etudid", None)
                elif request.method == "POST":
                    etudid = request.form.get("etudid", None)
            if etudid is not None:
                return Identite.get_etud(etudid)
        return self._init_etud

    @cached_property
    def etud_cur_sem(self) -> FormSemestre | None:
        "le semestre courant de l'étudiant courant"
        etud = self.etud
        if etud is None:
            return None
        ins = self.etud.inscription_courante()
        cur_sem = ins.formsemestre
        if ins:
            (
                self.nb_abs_nj,
                self.nb_abs_just,
                self.nb_abs,
            ) = sco_assiduites.get_assiduites_count_in_interval(
                etud.id,
                cur_sem.date_debut.isoformat(),
                cur_sem.date_fin.isoformat(),
                scu.translate_assiduites_metric(
                    sco_preferences.get_preference("assi_metrique")
                ),
            )
            return cur_sem
        return None

    @cached_property
    def formsemestre(self) -> FormSemestre | None:
        "Le formsemestre courant, si sélectionné"
        if self._init_formsemestre is None:
            formsemestre_id = retreive_formsemestre_from_request()
            return (
                FormSemestre.get_formsemestre(formsemestre_id)
                if formsemestre_id is not None
                else None
            )
        return self._init_formsemestre

    @cached_property
    def sem_menu_bar(self) -> str | None:
        "Le html de la bare de menu formsemestre s'il y en a un."
        return (
            sco_formsemestre_status.formsemestre_status_menubar(self.formsemestre)
            if self.formsemestre
            else None
        )

    @cached_property
    def prefs(self):
        "Préférences"
        # prefs fallback to global pref if no current formsemestre:
        return sco_preferences.SemPreferences(
            self.formsemestre.id if self.formsemestre else None
        )

    def formsemestre_status_menu_bar(self) -> str:
        "Le HTML de la barre de menu semestre"
        return sco_formsemestre_status.formsemestre_status_menubar(self.formsemestre)


# Ajout des routes
from app.but import bulletin_but_court  # ne pas enlever: ajoute des routes !
from app.but import jury_dut120  # ne pas enlever: ajoute des routes !
from app.pe import pe_view  # ne pas enlever, ajoute des routes !
from app.views import (
    absences,
    assiduites,
    but_formation,
    groups,
    jury_validations,
    notes_formsemestre,
    notes,
    pn_modules,
    refcomp,
    scodoc,
    scolar,
    users,
    user_board,
)