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

""" Test jury BUT avec parcours

Ces tests sont généralement lents (construction de la base),
et donc marqués par `@pytest.mark.slow`.

Certains sont aussi marqués par @pytest.mark.lemans ou @pytest.mark.lyon
pour lancer certains tests spécifiques seulement.

Exemple utilisation spécifique:
# test sur "Lyon" seulement:
pytest --pdb -m lyon tests/unit/test_but_jury.py

pytest --pdb -m but_gccd tests/unit/test_but_jury.py
"""

import pytest
from tests.unit import yaml_setup, yaml_setup_but

import app
from app.but.jury_but_validation_auto import formsemestre_validation_auto_but
from app.models import Formation, FormSemestre, UniteEns
from config import TestConfig

DEPT = TestConfig.DEPT_TEST


@pytest.mark.slow
@pytest.mark.but_gb
def test_but_jury_GB(test_client):
    """Tests sur un cursus GB
    - construction des semestres et de leurs étudiants à partir du yaml
    - vérification jury de S1
    - vérification jury de S2
    - vérification jury de S3
    - vérification jury de S1 avec redoublants et capitalisations
    """
    app.set_sco_dept(DEPT)
    # Construit la base de test GB une seule fois
    # puis lance les tests de jury
    doc = yaml_setup.setup_from_yaml("tests/ressources/yaml/cursus_but_gb.yaml")

    # Vérifie les deca de tous les semestres:
    for formsemestre in FormSemestre.query:
        yaml_setup_but.check_deca_fields(formsemestre)

    # Saisie de toutes les décisions de jury
    for formsemestre in FormSemestre.query.order_by(FormSemestre.semestre_id):
        formsemestre_validation_auto_but(formsemestre, only_adm=False)

    # Vérifie résultats attendus:
    S1: FormSemestre = FormSemestre.query.filter_by(titre="S1_SEE").first()
    yaml_setup_but.but_test_jury(S1, doc)
    S2: FormSemestre = FormSemestre.query.filter_by(titre="S2_SEE").first()
    yaml_setup_but.but_test_jury(S2, doc)
    S3: FormSemestre = FormSemestre.query.filter_by(titre="S3").first()
    yaml_setup_but.but_test_jury(S3, doc)
    # _test_but_jury(S1_redoublant, doc)


@pytest.mark.slow
@pytest.mark.lemans
def test_but_jury_GMP_lm(test_client):
    """Tests sur un cursus GMP fourni par Le Mans"""
    app.set_sco_dept(DEPT)
    # Construit la base de test GB une seule fois
    # puis lance les tests de jury
    doc = yaml_setup.setup_from_yaml("tests/ressources/yaml/cursus_but_gmp_iutlm.yaml")

    formsemestres = FormSemestre.query.order_by(
        FormSemestre.date_debut, FormSemestre.semestre_id
    ).all()

    # Vérifie les deca de tous les semestres:
    for formsemestre in formsemestres:
        yaml_setup_but.check_deca_fields(formsemestre)

    # Saisie de toutes les décisions de jury qui ne le seraient pas déjà
    for formsemestre in formsemestres:
        formsemestre_validation_auto_but(formsemestre, only_adm=False)

    # Vérifie résultats attendus:
    for formsemestre in formsemestres:
        yaml_setup_but.but_test_jury(formsemestre, doc)


@pytest.mark.slow
@pytest.mark.lyon
def test_but_jury_GEII_lyon(test_client):
    """Tests sur un cursus GEII fourni par Lyon"""
    app.set_sco_dept(DEPT)
    # Construit la base de test GB une seule fois
    # puis lance les tests de jury
    doc = yaml_setup.setup_from_yaml("tests/ressources/yaml/cursus_but_geii_lyon.yaml")
    formsemestres = FormSemestre.query.order_by(
        FormSemestre.date_debut, FormSemestre.semestre_id
    ).all()

    # Vérifie les champs de DecisionsProposeesAnnee de tous les semestres:
    for formsemestre in formsemestres:
        yaml_setup_but.check_deca_fields(formsemestre)

    # Saisie de toutes les décisions de jury "automatiques"
    # et vérification des résultats attendus:
    for formsemestre in formsemestres:
        formsemestre_validation_auto_but(
            formsemestre, only_adm=False, no_overwrite=False
        )
        yaml_setup_but.but_test_jury(formsemestre, doc)


@pytest.mark.slow
@pytest.mark.but_gccd
def test_but_jury_GCCD_CY(test_client):
    """Tests sur un cursus BUT GCCD de S1 à S6"""
    # WIP
    app.set_sco_dept(DEPT)
    doc = yaml_setup.setup_from_yaml("tests/ressources/yaml/cursus_but_gccd_cy.yaml")
    formsemestres = FormSemestre.query.order_by(
        FormSemestre.date_debut, FormSemestre.semestre_id
    ).all()

    formation: Formation = formsemestres[0].formation
    # Vérifie les UEs du parcours BAT
    parcour_BAT = formation.referentiel_competence.parcours.filter_by(
        code="BAT"
    ).first()
    assert parcour_BAT
    # check le nombre d'UE dans chaque semestre BUT:
    assert [
        len(
            formation.query_ues_parcour(parcour_BAT)
            .filter(UniteEns.semestre_idx == i)
            .all()
        )
        for i in range(1, 7)
    ] == [5, 5, 5, 5, 3, 3]
    # Vérifie les UEs du parcours TP
    parcour_TP = formation.referentiel_competence.parcours.filter_by(code="TP").first()
    assert parcour_TP
    # check le nombre d'UE dans chaque semestre BUT:
    assert [
        len(
            formation.query_ues_parcour(parcour_TP)
            .filter(UniteEns.semestre_idx == i)
            .all()
        )
        for i in range(1, 7)
    ] == [5, 5, 5, 5, 3, 3]