import pytest
from betamax import Betamax

from credmgr.exceptions import Conflict, InitializationError, NotFound
from credmgr.models import DatabaseCredential, RedditApp, SentryToken, User

data = {
    "username": "username",
    "password": "password",
    "reddit_username": "reddit_username",
    "default_settings": {"database_flavor": "postgres", "user_agent": "user_agent"},
}


def test_create_user(recorder, credential_manager):
    data = {
        "username": "username",
        "password": "password",
        "reddit_username": "reddit_username",
        "default_settings": {"database_flavor": "postgres", "user_agent": "user_agent"},
    }
    user = credential_manager.user.create(**data)
    data.pop("password")
    for key, value in data.items():
        assert getattr(user, key) == value


def test_create_user_bad_params(recorder, credential_manager):
    data = {"username": "te"}
    with pytest.raises(TypeError):
        _ = credential_manager.user.create(**data)


def test_create_user_existing(recorder, credential_manager):
    data = {"username": "username", "password": "password"}
    with pytest.raises(Conflict):
        _ = credential_manager.user.create(**data)


def test_delete_user(recorder, credential_manager):
    user = credential_manager.user(12)
    user.delete()
    with pytest.raises(NotFound):
        _ = credential_manager.user(12)


def test_edit_user(recorder, credential_manager):
    user = credential_manager.user("test2")
    data = {
        "username": "new_username",
        "reddit_username": "new_reddit_username",
        "default_settings": {
            "database_host": "localhost",
            "database_flavor": "postgres",
            "user_agent": "user_agent",
        },
    }
    user.edit(**data)
    modified_user = credential_manager.user("new_username")
    for key, value in data.items():
        assert getattr(modified_user, key) == value


def test_edit_user_conflicting_data(recorder, credential_manager):
    user = credential_manager.user(6)
    with pytest.raises(Conflict):
        user.edit(username="username")


def test_list_users(recorder, credential_manager):
    users = credential_manager.users()
    for user in users:
        assert isinstance(user, User)


def test_list_users_with_user(recorder, credential_manager):
    with pytest.raises(InitializationError):
        _ = credential_manager.user()


def test_apps(recorder, credential_manager):
    user = credential_manager.current_user
    all_apps = user.apps()
    assert isinstance(all_apps, dict)
    for apps in all_apps.values():
        for app in apps:
            assert isinstance(app, (DatabaseCredential, RedditApp, SentryToken))


def test_apps_only(credential_manager):
    with Betamax(credential_manager._requestor._session).use_cassette(
        "TestUser.test_apps"
    ):
        user = credential_manager.current_user
        sentry_tokens = user.apps("sentry_tokens")
        assert isinstance(sentry_tokens, list)
        for token in sentry_tokens:
            assert isinstance(token, SentryToken)


def test_apps_only_invalid(credential_manager):
    with Betamax(credential_manager._requestor._session).use_cassette(
        "TestUser.test_apps"
    ):
        user = credential_manager.current_user
        with pytest.raises(InitializationError):
            _ = user.apps("invalid")
