"""
Functional tests for the managing users.

:copyright: Copyright 2013-2016, Dorian Pula <dorian.pula@amber-penguin-software.ca>
:license: AGPL v3+
"""

import http
import uuid

import pytest
import pytest_bdd as bdd
import requests
from pytest import mark
from pytest_bdd import parsers


# TODO: Figure out how to generate a JWT using the correct hash.
# TODO: Add tests to make sure users can't modify each other's profiles, etc.
# TODO: Add in a new role that is super-admin, maybe?
USER_ROLE_JWT_MAPPING = {
    'admin': 'password',
    'editor': 'some_other_login',
}


SAMPLE_USERS_REQUEST = {
    'admin': {},
    'editor': {},
}


SAMPLE_USERS_RESPONSE = {
    'admin': {},
    'editor': {},
}


@pytest.fixture(scope='module')
def api_site_key():
    return str(uuid.uuid4())


@mark.skip(reason="Test scenarios need work")
@bdd.scenario('user_management.feature', 'Admin user can create a new admin user')
def test_admin_user_creation_by_admin():
    pass


@mark.skip(reason="Test scenarios need work")
@bdd.scenario('user_management.feature', 'Admin user can create a new editor user')
def test_editor_user_creation_by_admin():
    pass


@mark.skip(reason="Test scenarios need work")
@bdd.scenario('user_management.feature', 'Editor user can not create a new admin user')
def test_admin_user_creation_by_editor():
    pass


@mark.skip(reason="Test scenarios need work")
@bdd.scenario('user_management.feature', 'Editor user can not create a new editor user')
def test_editor_user_creation_by_editor():
    pass


@mark.skip(reason="Test scenarios need work")
@bdd.scenario('user_management.feature', 'Admin user can get an existing admin user')
def test_admin_user_fetch_by_admin():
    pass


@mark.skip(reason="Test scenarios need work")
@bdd.scenario('user_management.feature', 'Admin user can get an existing editor user')
def test_editor_user_fetch_by_admin():
    pass


@mark.skip(reason="Test scenarios need work")
@bdd.scenario('user_management.feature', 'Any user can not get an existing admin user')
def test_admin_user_fetch_by_anyone():
    pass


@mark.skip(reason="Test scenarios need work")
@bdd.scenario('user_management.feature', 'Any user can not get an existing editor user')
def test_editor_user_fetch_by_anyone():
    pass


@mark.skip(reason="Test scenarios need work")
@bdd.scenario('user_management.feature', 'Editor user can not get an existing admin user')
def test_admin_user_fetch_by_editor():
    pass


@mark.skip(reason="Test scenarios need work")
@bdd.scenario('user_management.feature', 'Editor user can not get an existing editor user that is not me')
def test_editor_user_fetch_by_editor():
    pass


@mark.skip(reason="Test scenarios need work")
@bdd.scenario('user_management.feature', 'Admin user can modify an admin user')
def test_admin_user_modification_by_admin():
    pass


@mark.skip(reason="Test scenarios need work")
@bdd.scenario('user_management.feature', 'Admin user can modify an editor user')
def test_editor_user_modification_by_admin():
    pass


@mark.skip(reason="Test scenarios need work")
@bdd.scenario('user_management.feature', 'Editor user can not modify an editor user that is not self')
def test_editor_user_modification_by_editor():
    pass


@mark.skip(reason="Test scenarios need work")
@bdd.scenario('user_management.feature', 'Editor user can modify their own user')
def test_self_user_modification_by_editor():
    pass


@mark.skip(reason="Test scenarios need work")
@bdd.scenario('user_management.feature', 'Admin user can delete an admin user')
def test_admin_user_deletion_by_admin():
    pass


@mark.skip(reason="Test scenarios need work")
@bdd.scenario('user_management.feature', 'Admin user can delete an editor user')
def test_editor_user_deletion_by_admin():
    pass


@mark.skip(reason="Test scenarios need work")
@bdd.scenario('user_management.feature', 'Editor user can not delete an editor user')
def test_editor_user_deletion_by_editor():
    pass


# Step definitions here.

@bdd.given(parsers.parse('I am an {user_role} user'))
def user_credentials(user_role):
    return USER_ROLE_JWT_MAPPING[user_role]


@bdd.given(parsers.parse('I create an {user_role} user'))
def create_user_response(user_role, user_credentials, api_base_uri, api_site_key):
    user_creation_request = SAMPLE_USERS_REQUEST[user_role]
    return requests.post(
        url=f'{api_base_uri}/api/users',
        json=user_creation_request,
        headers={
            'Authentication-Bearer': user_credentials,
            'ROOKERIES_API_KEY': api_site_key,
        },
    )


@bdd.given(parsers.parse('I get an {user_role} user'))
def get_user_response(user_role, user_credentials, api_base_uri, api_site_key):
    # TODO Add in mapping for kind of user/username
    test_user_id = '1'
    return requests.get(
        url=f'{api_base_uri}/api/users/{test_user_id}',
        headers={
            'Authentication-Bearer': user_credentials,
            'ROOKERIES_API_KEY': api_site_key,
        },
    )


# TODO: Figure out how to get response from the request.
@bdd.then(parsers.parse('I get a new {user_role} user'))
def assert_create_user_response(user_role, create_user_response):
    assert create_user_response.status_code == http.HTTPStatus.CREATED
    expected_user_creation_response = SAMPLE_USERS_RESPONSE[user_role]
    assert create_user_response.json() == expected_user_creation_response


# TODO: Figure out how to get response from the request.
@bdd.then(parsers.parse('I can get an {user_role} user profile'))
def assert_user_profile(user_role, get_user_response):
    assert get_user_response.status_code == http.HTTPStatus.OK
    expected_user_creation_response = SAMPLE_USERS_RESPONSE[user_role]
    assert get_user_response.json() == expected_user_creation_response

    # TODO: Do look up on user profile.
