from datetime import datetime, timedelta

import pytest
from mock import MagicMock, patch

from atheneum import errors
from atheneum.model import UserToken, User
from atheneum.service import patch_service, role_service

service_module = 'atheneum.service.patch_service'


@patch(service_module + '.db.session.commit')
def test_patch_models(
        mock_db_session_commit: MagicMock):
    request_user = User()
    request_user.role = role_service.Role.ADMIN

    user = User()
    user.name = 'TestUser'
    user.version = 1
    user.last_login_time = datetime.now() - timedelta(days=1)

    user_patch = User()
    user_patch.name = 'TestUser'
    user_patch.version = 1
    user_patch.last_login_time = datetime.now()

    patched_user = patch_service.patch(request_user, user, user_patch)
    assert patched_user.version > 1
    assert patched_user.last_login_time == user_patch.last_login_time
    mock_db_session_commit.assert_called_once()


def test_patch_of_different_types():
    request_user = User()
    request_user.role = role_service.Role.ADMIN

    user = User()
    user_token = UserToken()

    with pytest.raises(errors.ValidationError) as error_info:
        patch_service.patch(request_user, user, user_token)


def test_patch_different_ids():
    request_user = User()
    request_user.role = role_service.Role.ADMIN

    user1 = User()
    user1.id = 1

    user2 = User()
    user2.id = 2

    with pytest.raises(errors.ValidationError) as error_info:
        patch_service.patch(request_user, user1, user2)


def test_patch_different_versions():
    request_user = User()
    request_user.role = role_service.Role.ADMIN

    user1 = User()
    user1.version = 1

    user2 = User()
    user2.version = 2

    with pytest.raises(errors.ValidationError) as error_info:
        patch_service.patch(request_user, user1, user2)


def test_patch_restricted_attributes():
    request_user = User()
    request_user.role = role_service.Role.USER

    user1 = User()
    user1.version = 1
    user1.name = 'Bob'

    user2 = User()
    user2.version = 1
    user2.name = 'Chris'

    with pytest.raises(errors.ValidationError) as error_info:
        patch_service.patch(request_user, user1, user2)