# -*- coding: utf-8 -*-

"""Test modèle étudiant (identite)


Utiliser comme:
    pytest tests/unit/test_etudiants.py

"""
import datetime
from pathlib import Path
import time

from flask import current_app

import app
from app import db
from app.models import Admission, Adresse, Departement, FormSemestre, Identite
from app.scodoc import sco_etud
from app.scodoc import sco_find_etud, sco_import_etuds
from config import TestConfig

from tests.unit import setup, dict_include


def test_identite(test_client):
    "Test de base du modèle identité: création, clonage, ..."
    args = {
        "civilite": "X",
        "code_ine": "code_ine",
        "code_nip": "code_nip",
        "date_naissance": datetime.date(2000, 1, 2),
        "dept_id": 1,
        "dept_naissance": "dept_naissance",
        "lieu_naissance": "lieu_naissance",
        "nationalite": "nationalite",
        "nom_usuel": "nom_usuel",
        "nom": "nom",
        "prenom_etat_civil": "prenom_etat_civil",
        "prenom": "prenom",
    }
    e = Identite.create_etud(**args)
    db.session.add(e)
    db.session.flush()
    #
    assert e.nom == "NOM"
    assert e.nom_usuel == "NOM_USUEL"
    assert e.prenom == "PRENOM"
    assert e.prenom_etat_civil == "PRENOM_ETAT_CIVIL"
    assert e.dept_naissance == "dept_naissance"
    assert e.etat_civil == "PRENOM_ETAT_CIVIL NOM"
    #
    admission_id = e.admission_id
    admission = db.session.get(Admission, admission_id)
    assert admission is not None
    assert e.boursier is False
    assert e.adresses.count() == 1
    adresses_ids = [a.id for a in e.adresses]
    # --- Teste cascade admission:
    db.session.delete(e)
    db.session.flush()
    assert db.session.get(Admission, admission_id) is None
    assert db.session.get(Departement, 1) is not None
    # --- Teste cascade adresses
    for adresse_id in adresses_ids:
        assert db.session.get(Adresse, adresse_id) is None
    # --- Test cascade département
    dept = Departement(acronym="test_identite")
    db.session.add(dept)
    db.session.flush()
    args1 = args | {"dept_id": dept.id}
    e = Identite.create_etud(**args1)
    db.session.add(e)
    db.session.flush()
    etudid = e.id
    db.session.delete(dept)
    db.session.flush()
    assert db.session.get(Identite, etudid) is None


def test_etat_civil(test_client):
    "Test des attributs état civil"
    dept = Departement.query.first()
    args = {"nom": "nom", "prenom": "prénom", "civilite": "M", "dept_id": dept.id}
    # Homme
    e = Identite.create_etud(**args)
    db.session.flush()
    assert e.civilite_etat_civil_str == "M."
    assert e.e == ""
    assert e.etat_civil == "M. PRÉNOM NOM"
    # Femme
    e = Identite.create_etud(**args | {"civilite": "F"})
    db.session.flush()
    assert e.civilite_etat_civil_str == "Mme"
    assert e.e == "e"
    assert e.etat_civil == "Mme PRÉNOM NOM"
    # Homme devenu femme
    e = Identite.create_etud(**(args | {"civilite_etat_civil": "F"}))
    db.session.flush()
    assert e.civilite_etat_civil_str == "Mme"
    assert e.civilite_str == "M."
    assert e.e == ""
    assert e.etat_civil == "Mme PRÉNOM NOM"
    # Femme devenue neutre
    e = Identite.create_etud(**(args | {"civilite": "X", "civilite_etat_civil": "F"}))
    db.session.flush()
    assert e.civilite_etat_civil_str == "Mme"
    assert e.civilite_str == ""
    assert e.e == "(e)"
    assert e.prenom_etat_civil is None
    assert e.etat_civil == "Mme PRÉNOM NOM"
    # La version dict
    e_d = e.to_dict_scodoc7()
    assert e_d["civilite"] == "X"
    assert e_d["civilite_etat_civil"] == "F"
    assert e_d["ne"] == "(e)"


def test_etud_legacy(test_client):
    "Test certaines fonctions scodoc7 (sco_etud)"
    dept = Departement.query.first()
    args = {"nom": "nom", "prenom": "prénom", "civilite": "M", "dept_id": dept.id}
    # Prénom état civil
    e = Identite.create_etud(**(args))
    db.session.add(e)
    db.session.flush()
    e_dict = e.to_dict_bul()
    sco_etud.format_etud_ident(e_dict)
    assert e_dict["nom_disp"] == "NOM"
    assert e_dict["prenom_etat_civil"] == ""


def test_import_etuds_xlsx(test_client):
    "test import étudiant depuis xlsx"
    G, formation_id, (ue1_id, ue2_id, ue3_id), module_ids = setup.build_formation_test(
        acronyme="IMPXLSX"
    )
    formsemestre_id = G.create_formsemestre(
        formation_id=formation_id,
        semestre_id=1,
        date_debut="01/01/2021",
        date_fin="30/06/2021",
    )
    filename = (
        Path(current_app.config["SCODOC_DIR"])
        / "tests/ressources/misc/ImportEtudiants.xlsx"
    )
    with open(filename, mode="rb") as f:
        sco_import_etuds.scolars_import_excel_file(
            f, formsemestre_id=formsemestre_id, exclude_cols=["photo_filename"]
        )
    formsemestre = db.session.get(FormSemestre, formsemestre_id)
    # Vérifie tous les champs du premier étudiant
    e1 = formsemestre.etuds.filter_by(code_ine="ine1").first()
    assert e1
    assert e1.code_nip == "nip1"
    assert e1.code_ine == "ine1"
    assert e1.nom == "NOM1"
    assert e1.nom_usuel == "NOM_USUEL1"
    assert e1.prenom == "PRÉNOM1"
    assert e1.civilite == "M"
    assert e1.prenom_etat_civil == "PRÉNOM_CIVIL1"
    assert e1.civilite_etat_civil == "M"
    assert e1.date_naissance == datetime.date(2001, 5, 1)
    assert e1.lieu_naissance == "Paris"
    assert e1.nationalite == "Belge"
    assert e1.boursier is True
    # Admission
    adm = e1.admission
    assert adm.bac == "C"
    assert adm.specialite == "SPÉ"
    assert adm.annee_bac == 2023
    assert adm.math == "11.0"  # deprecated field
    assert adm.physique == "12.0"  # deprecated field
    assert adm.anglais == "13.0"  # deprecated field
    assert adm.francais == "14.0"  # deprecated field
    assert adm.boursier_prec is False
    assert adm.qualite == 10
    assert adm.rapporteur == "xx"
    assert adm.score == 5
    assert adm.classement == 111
    assert adm.nomlycee == "nomlycée"
    assert adm.codepostallycee == "75005"
    # Adresse
    adresse: Adresse = e1.adresses.first()
    assert adresse.email == "etud1@etud.no"
    assert adresse.emailperso == "etud1@perso.no"
    assert adresse.domicile == "1 rue A"
    assert adresse.codepostaldomicile == "12345"
    assert adresse.villedomicile == "Lima"
    assert adresse.paysdomicile == "Pérou"
    assert adresse.telephone == "102030405"
    assert adresse.telephonemobile == "605040302"
    #
    #
    e2 = formsemestre.etuds.filter_by(code_ine="ine2").first()
    assert e2
    assert e2.civilite == "M"
    assert e2.civilite_etat_civil is None
    assert e2.civilite_str == "M."
    assert e2.civilite_etat_civil_str == "M."
    assert e2.nomprenom == "M. Prénom2 NOM2"
    #
    e3 = formsemestre.etuds.filter_by(code_ine="ine3").first()
    assert e3
    assert e3.civilite == "F"
    assert e3.civilite_etat_civil is None
    assert e3.civilite_str == "Mme"
    assert e3.civilite_etat_civil_str == "Mme"
    assert e3.nomprenom == "Mme Prénom3 NOM3"
    #
    e4 = formsemestre.etuds.filter_by(code_ine="ine4").first()
    assert e4
    assert e4.civilite == "X"
    assert e4.civilite_etat_civil is None
    assert e4.civilite_str == ""
    assert e4.civilite_etat_civil_str == ""
    assert e4.nomprenom == "Prénom4 NOM4"
    #
    e5 = formsemestre.etuds.filter_by(code_ine="ine5").first()
    assert e5
    assert e5.civilite == "M"
    assert e5.civilite_etat_civil == "F"
    assert e5.civilite_str == "M."
    assert e5.civilite_etat_civil_str == "Mme"
    assert e5.nomprenom == "M. Prénom5 NOM5"
    #
    e6 = formsemestre.etuds.filter_by(code_ine="ine6").first()
    assert e6
    assert e6.civilite == "F"
    assert e6.civilite_etat_civil == "F"
    assert e6.civilite_str == "Mme"
    assert e6.civilite_etat_civil_str == "Mme"
    assert e6.nomprenom == "Mme Prénom6 NOM6"
    #
    e7 = formsemestre.etuds.filter_by(code_ine="ine7").first()
    assert e7
    assert e7.civilite == "X"
    assert e7.civilite_etat_civil == "F"
    assert e7.civilite_str == ""
    assert e7.civilite_etat_civil_str == "Mme"
    assert e7.nomprenom == "Prénom7 NOM7"
    #
    e8 = formsemestre.etuds.filter_by(code_ine="ine8").first()
    assert e8
    assert e8.civilite == "X"
    assert e8.civilite_etat_civil == "F"
    assert e8.prenom_etat_civil == "PRÉNOM_CIVIL8"
    assert e8.nomprenom == "Prénom8 NOM8"
    # e9
    e9 = formsemestre.etuds.filter_by(code_ine="ine9").first()
    assert e9
    assert e9.civilite == "X"
    assert e9.civilite_etat_civil is None
    assert e9.prenom == "PRÉNOM9"
    assert e9.prenom_etat_civil == "PRÉNOM_CIVIL9"
    assert e9.nomprenom == "Prénom9 NOM9"
    #
    e10 = formsemestre.etuds.filter_by(code_ine="ine10").first()
    assert e10
    assert e10.nom_usuel == "NOM_USUEL10"
    assert e10.nomprenom == "Prénom10 NOM_USUEL10"
    # Vérification conversion dict
    e10_dict = e10.to_dict_bul()
    assert dict_include(
        e10_dict,
        {
            "boursier": "",
            "civilite_etat_civil": "F",
            "civilite": "X",
            "code_ine": "ine10",
            "code_nip": "1000010",
            "date_naissance": "",
            "dept_acronym": "TEST_",
            "dept_naissance": "",
            "email": "",
            "emailperso": "",
            "etat_civil": "Mme PRÉNOM_CIVIL10 NOM10",
            "etudid": 10,
            "lieu_naissance": "",
            "nationalite": "",
            "nom": "NOM_USUEL10 (NOM10)",
            "nomprenom": "Prénom10 NOM_USUEL10",
            "prenom_etat_civil": "PRÉNOM_CIVIL10",
            "prenom": "PRÉNOM10",
            "domicile": "",
            "villedomicile": "",
            "telephone": "",
            "fax": "",
            "codepostaldomicile": "",
            "paysdomicile": "",
            "telephonemobile": "",
            "typeadresse": "domicile",
        },
    )
    # Test fonction sco_etud ScoDoc7 legacy
    app.set_sco_dept(TestConfig.DEPT_TEST)
    e10_dict["admission_id"] = e10.admission_id
    sco_etud.fill_etuds_info([e10_dict])
    assert dict_include(
        e10_dict,
        {
            "boursier": "",
            "civilite_etat_civil": "F",
            "civilite": "X",
            "code_ine": "ine10",
            "code_nip": "1000010",
            "date_naissance": "",
            "dept_acronym": "TEST_",
            "dept_naissance": "",
            "email": "",
            "emailperso": "",
            "etat_civil": "Mme Prénom_civil10 NOM_USUEL10 (NOM10)",
            "lieu_naissance": "",
            "nationalite": "",
            "nom": "NOM_USUEL10 (NOM10)",
            "nomprenom": "Prénom10 NOM_USUEL10 (NOM10)",
            "prenom_etat_civil": "Prénom_civil10",
            "prenom": "Prénom10",
            "domicile": "",
            "villedomicile": "",
            "telephone": "",
            "fax": "",
            "description": "(infos admission)",
            "id": 10,
            "codepostaldomicile": "",
            "paysdomicile": "",
            "telephonemobile": "",
            "typeadresse": "domicile",
            "admission_id": 10,
            "dept": "TEST_",
            "bac": "",
            "rang": 0,
            "codepostallycee": "",
            "qualite": None,
            "codelycee": "",
            "rapporteur": "",
            "type_admission": "",
            "annee_bac": 0,
            "decision": "",
            "boursier_prec": False,
            "math": "",
            "score": None,
            "classement": 0,
            "physique": "",
            "commentaire": "",
            "apb_groupe": "",
            "anglais": "",
            "nomlycee": "",
            "apb_classement_gr": 0,
            "villelycee": "",
            "annee": time.localtime()[0],  # année courante
            "specialite": "",
            "francais": "",
            "nom_usuel": "",
            "civilite_str": "",
            "civilite_etat_civil_str": "Mme",
            "nom_disp": "NOM_USUEL10 (NOM10)",
            "ne": "(e)",
            "inscription": "ancien",
            "situation": "ancien élève",
            "inscriptionstr": "ancien",
            "inscription_formsemestre_id": None,
            "etatincursem": "?",
        },
    )
    # Test de search_etud_in_dept
    etuds = sco_find_etud.search_etuds_infos_from_exp("NOM10")
    assert len(etuds) == 1
    assert etuds[0]["code_ine"] == "ine10"
    etuds = sco_find_etud.search_etuds_infos_from_exp("NOM")
    assert len(etuds) > 1
    assert all(e["nom"].startswith("NOM") for e in etuds)
    etuds = sco_find_etud.search_etuds_infos_from_exp("1000010")
    assert len(etuds) == 1
    assert etuds[0]["code_ine"] == "ine10"