# -*- coding: UTF-8 -*

"""Notes, décisions de jury, évènements scolaires
"""

import sqlalchemy as sa
from app import db
from app.scodoc import safehtml
import app.scodoc.sco_utils as scu


class BulAppreciations(db.Model):
    """Appréciations sur bulletins"""

    __tablename__ = "notes_appreciations"
    id = db.Column(db.Integer, primary_key=True)
    date = db.Column(db.DateTime(timezone=True), server_default=db.func.now())
    etudid = db.Column(
        db.Integer,
        db.ForeignKey("identite.id", ondelete="CASCADE"),
        index=True,
    )
    formsemestre_id = db.Column(
        db.Integer,
        db.ForeignKey("notes_formsemestre.id"),
    )
    author = db.Column(db.Text)  # le pseudo (user_name), sans contrainte
    comment = db.Column(db.Text)  # texte libre

    @classmethod
    def get_appreciations_list(
        cls, formsemestre_id: int, etudid: int
    ) -> list["BulAppreciations"]:
        "Liste des appréciations pour cet étudiant dans ce semestre"
        return (
            BulAppreciations.query.filter_by(
                etudid=etudid, formsemestre_id=formsemestre_id
            )
            .order_by(BulAppreciations.date)
            .all()
        )

    @classmethod
    def summarize(cls, appreciations: list["BulAppreciations"]) -> list[str]:
        "Liste de chaines résumant une liste d'appréciations, pour bulletins"
        return [
            f"{x.date.strftime('%d/%m/%Y') if x.date else ''}: {x.comment or ''}"
            for x in appreciations
        ]

    def comment_safe(self) -> str:
        "Le comment, safe pour inclusion dans HTML (None devient '')"
        return safehtml.html_to_safe_html(self.comment or "")


class NotesNotes(db.Model):
    """Une note"""

    __tablename__ = "notes_notes"
    __table_args__ = (db.UniqueConstraint("etudid", "evaluation_id"),)
    id = db.Column(db.Integer, primary_key=True)
    etudid = db.Column(
        db.Integer,
        db.ForeignKey("identite.id", ondelete="CASCADE"),
    )
    evaluation_id = db.Column(
        db.Integer, db.ForeignKey("notes_evaluation.id"), index=True
    )
    value = db.Column(db.Float)
    # infos sur saisie de cette note:
    comment = db.Column(db.Text)  # texte libre
    date = db.Column(db.DateTime(timezone=True), server_default=db.func.now())
    uid = db.Column(db.Integer, db.ForeignKey("user.id"))

    def to_dict(self) -> dict:
        "dict"
        d = dict(self.__dict__)
        d.pop("_sa_instance_state", None)
        return d

    def __repr__(self):
        "pour debug"
        from app.models.evaluations import Evaluation

        return f"""<{self.__class__.__name__} {self.id} etudid={self.etudid} v={self.value} {self.date.isoformat()
            } {db.session.get(Evaluation, self.evaluation_id) if self.evaluation_id else "X" }>"""


class NotesNotesLog(db.Model):
    """Historique des modifs sur notes (anciennes entrees de notes_notes)"""

    __tablename__ = "notes_notes_log"
    id = db.Column(db.Integer, primary_key=True)

    etudid = db.Column(
        db.Integer,
        db.ForeignKey("identite.id", ondelete="CASCADE"),
    )
    evaluation_id = db.Column(
        db.Integer,
        # db.ForeignKey("notes_evaluation.id"),
        index=True,
    )
    value = db.Column(db.Float)
    # infos sur saisie de cette note:
    comment = db.Column(db.Text)  # texte libre
    date = db.Column(db.DateTime(timezone=True), server_default=db.func.now())
    uid = db.Column(db.Integer, db.ForeignKey("user.id"))


def etud_has_notes_attente(etudid, formsemestre_id):
    """Vrai si cet etudiant a au moins une note en attente dans ce semestre.
    (ne compte que les notes en attente dans des évaluations avec coef. non nul).
    """
    cursor = db.session.execute(
        sa.text(
            """SELECT COUNT(*)
        FROM notes_notes n, notes_evaluation e, notes_moduleimpl m,
        notes_moduleimpl_inscription i
        WHERE n.etudid = :etudid
        and n.value = :code_attente
        and n.evaluation_id = e.id
        and e.moduleimpl_id = m.id
        and m.formsemestre_id = :formsemestre_id
        and e.coefficient != 0
        and m.id = i.moduleimpl_id
        and i.etudid = :etudid
        """
        ),
        {
            "formsemestre_id": formsemestre_id,
            "etudid": etudid,
            "code_attente": scu.NOTES_ATTENTE,
        },
    )
    return cursor.fetchone()[0] > 0
