# -*- coding: UTF-8 -*

"""Unit tests for auth (users/roles/permission management)

Ré-écriture de test_users avec pytest.

Usage: pytest tests/unit/test_users.py
"""

import pytest
from tests.conftest import test_client
from flask import current_app

from app import db
from app.auth.models import User, Role, Permission
from app.scodoc.sco_roles_default import SCO_ROLES_DEFAULTS


DEPT = "XX"


def test_password_hashing(test_client):
    u = User(user_name="susan")
    db.session.add(u)
    db.session.commit()
    # nota: default attributes values, like active,
    # are not set before the first commit()
    assert u.active
    u.set_password("cat")
    assert not u.check_password("dog")
    assert u.check_password("cat")


def test_roles_permissions(test_client):
    perm = Permission.AbsChange  # une permission au hasard
    role = Role(name="test")
    assert not role.has_permission(perm)
    role.add_permission(perm)
    assert role.has_permission(perm)
    role.remove_permission(perm)
    assert not role.has_permission(perm)
    # Default roles:
    Role.reset_standard_roles_permissions()
    # Bien présents ?
    role_names = [r.name for r in Role.query.filter_by().all()]
    assert len(role_names) == len(SCO_ROLES_DEFAULTS)
    assert "Ens" in role_names
    assert "Secr" in role_names
    assert "Admin" in role_names
    # Les permissions de "Ens":
    role = Role.query.filter_by(name="Ens").first()
    assert role
    assert role.has_permission(Permission.ScoView)
    assert role.has_permission(Permission.AbsChange)
    # Permissions de Admin
    role = Role.query.filter_by(name="Admin").first()
    assert role.has_permission(Permission.EtudChangeAdr)
    # Permissions de Secr
    role = Role.query.filter_by(name="Secr").first()
    assert role.has_permission(Permission.EtudChangeAdr)
    assert not role.has_permission(Permission.EditAllNotes)


def test_users_roles(test_client):
    dept = DEPT
    perm = Permission.AbsChange
    perm2 = Permission.ScoView
    u = User(user_name="un_enseignant")
    db.session.add(u)
    assert not u.has_permission(perm, dept)
    r = Role.get_named_role("Ens")
    if not r:
        r = Role(name="Ens", permissions=perm)
    u.add_role(r, dept)
    assert u.has_permission(perm, dept)
    u = User(user_name="un_autre")
    u.add_role(r, dept)
    db.session.add(u)
    db.session.commit()
    assert u.has_permission(perm, dept)
    r2 = Role.get_named_role("Secr")
    if not r2:
        r2 = Role(name="Secr", dept=dept, permissions=perm2)
    u.add_roles([r, r2], dept)
    assert len(u.roles) == 2
    u = User(user_name="encore_un")
    db.session.add(u)
    db.session.commit()
    u.set_roles([r, r2], dept)
    print(u.roles)
    assert len(u.roles) == 2
    assert u.has_permission(perm, dept)
    assert u.has_permission(perm2, dept)
    # et pas accès aux autres dept:
    assert not u.has_permission(perm, dept + "X")
    assert not u.has_permission(perm, None)


def test_user_admin(test_client):
    dept = DEPT
    perm = 0x1234  # a random perm
    u = User(user_name="un_admin", email=current_app.config["SCODOC_ADMIN_MAIL"])
    db.session.add(u)
    assert len(u.roles) == 1
    assert u.has_permission(perm, dept)
    # Le grand admin a accès à tous les départements:
    assert u.has_permission(perm, dept + DEPT)
    assert u.roles[0].name == "SuperAdmin"


def test_create_delete(test_client):
    u = User(user_name="dupont", nom="Dupont", prenom="Pierre")
    db.session.add(u)
    db.session.commit()
    u = User(user_name="dupond", nom="Dupond", prenom="Pierre")
    db.session.add(u)
    db.session.commit()
    ul = User.query.filter_by(prenom="Pierre").all()
    assert len(ul) == 2
    ul = User.query.filter_by(user_name="dupont").all()
    assert len(ul) == 1
    db.session.delete(ul[0])
    db.session.commit()
    ul = User.query.filter_by(prenom="Pierre").all()
    assert len(ul) == 1


def test_edit(test_client):
    "test edition object utlisateur"
    args = {
        "prenom": "No Totoro",
        "edt_id": "totorito",
        "cas_allow_login": 1,  # boolean
        "irrelevant": "..",  # intentionnellement en dehors des attributs
    }
    u = User(user_name="Tonari")
    u.from_dict(args)
    db.session.add(u)
    db.session.commit()
    db.session.refresh(u)
    assert u.edt_id == "totorito"
    assert u.nom == ""
    assert u.cas_allow_login is True
    d = u.to_dict()
    assert d["nom"] == ""
    args["cas_allow_login"] = 0
    u.from_dict(args)
    db.session.commit()
    db.session.refresh(u)
    assert u.cas_allow_login is False
    db.session.delete(u)
    db.session.commit()