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

"""Initialise une base pour les tests de l'API ScoDoc 9

 Création des départements, formations, semestres, étudiants, groupes...

 utilisation:
 1) modifier le .env pour indiquer 
    SCODOC_DATABASE_URI="postgresql:///SCO_TEST_API"
 
 2) En tant qu'utilisateur scodoc, lancer:
 tools/create_database.sh SCO_TEST_API
 flask db upgrade
 flask sco-db-init --erase
 flask init-test-database

 3) relancer ScoDoc:
   flask run --host 0.0.0.0

 4) lancer client de test (ou vérifier dans le navigateur)

"""
import datetime
import random

random.seed(12345678)  # tests reproductibles

from flask_login import login_user

from app import auth
from app import models
from app import db
from app.scodoc import (
    sco_formations,
    sco_formsemestre,
    sco_formsemestre_inscriptions,
    sco_groups,
)
from tools.fakeportal.gen_nomprenoms import nomprenom

# La formation à utiliser:
FORMATION_XML_FILENAME = "tests/ressources/formations/scodoc_formation_RT_BUT_RT_v1.xml"


def init_departement(acronym):
    "Create dept, and switch context into it."
    import app as mapp

    dept = models.Departement(acronym=acronym)
    db.session.add(dept)
    mapp.set_sco_dept(acronym)
    db.session.commit()
    return dept


def import_formation() -> models.Formation:
    """Import formation from XML.
    Returns formation_id
    """
    with open(FORMATION_XML_FILENAME) as f:
        doc = f.read()
    # --- Création de la formation
    f = sco_formations.formation_import_xml(doc)
    return models.Formation.query.get(f[0])


def create_user(dept):
    """créé les utilisaterurs nécessaires aux tests"""
    user = auth.models.User(
        user_name="test", nom="Doe", prenom="John", dept=dept.acronym
    )
    db.session.add(user)
    db.session.commit()
    return user


def create_fake_etud(dept):
    """Créé un faux étudiant et l'insère dans la base"""
    civilite = random.choice(("M", "F", "X"))
    nom, prenom = nomprenom(civilite)
    etud = models.Identite(civilite=civilite, nom=nom, prenom=prenom, dept_id=dept.id)
    db.session.add(etud)
    db.session.commit()
    adresse = models.Adresse(
        etudid=etud.id, email=f"{etud.prenom}.{etud.nom}@example.com"
    )
    db.session.add(adresse)
    admission = models.Admission(etudid=etud.id)
    db.session.add(admission)
    db.session.commit()
    return etud


def create_etuds(dept, nb=16):
    "create nb etuds"
    return [create_fake_etud(dept) for _ in range(nb)]


def create_formsemestre(formation, user, semestre_idx=1):
    """Create formsemestre and moduleimpls"""
    formsemestre = models.FormSemestre(
        dept_id=formation.dept_id,
        semestre_id=semestre_idx,
        titre="Semestre test",
        date_debut=datetime.datetime(2021, 9, 1),
        date_fin=datetime.datetime(2022, 1, 31),
        modalite="FI",
        formation=formation,
    )
    db.session.add(formsemestre)
    db.session.commit()
    # Crée un modulimpl par module de ce semestre:
    for module in formation.modules.filter_by(semestre_id=semestre_idx):
        modimpl = models.ModuleImpl(
            module_id=module.id, formsemestre_id=formsemestre.id, responsable_id=user.id
        )
        db.session.add(modimpl)
    db.session.commit()
    partition_id = sco_groups.partition_create(
        formsemestre.id, default=True, redirect=False
    )
    _group_id = sco_groups.create_group(partition_id, default=True)
    return formsemestre


def inscrit_etudiants(etuds, formsemestre):
    """Inscrit les etudiants aux semestres et à tous ses modules"""
    for etud in etuds:
        sco_formsemestre_inscriptions.do_formsemestre_inscription_with_modules(
            formsemestre.id,
            etud.id,
            group_ids=[],
            etat="I",
            method="init db test",
        )


def init_test_database():
    dept = init_departement("TAPI")
    user = create_user(dept)
    etuds = create_etuds(dept)
    formation = import_formation()
    formsemestre = create_formsemestre(formation, user)
    inscrit_etudiants(etuds, formsemestre)
    # à compléter
    # - groupes
    # - absences
    # - notes
    # - décisions de jury
    # ...