"""
Functional tests for the user authentication feature.

:copyright: Copyright 2013-2017, Dorian Puła
    <dorian.pula@amber-penguin-software.ca>
:license: AGPL v3+
"""

import collections
import http

import jwt
import pytest
import requests

from tests import utils


Credentials = collections.namedtuple('Credentials', ['username', 'password'])


@pytest.fixture(scope='module')
def valid_user(db):
    test_user, password = utils.generate_test_user(db)
    return Credentials(test_user.username, password)


def test_valid_user_with_valid_credentials_can_authenticate_on_site(
        api_base_uri, valid_user):

    response = requests.post(f'{api_base_uri}/auth', json={
        'username': valid_user.username,
        'password': valid_user.password,
    })

    assert response.status_code == http.HTTPStatus.OK

    jwt_token = response.json()['access_token']
    assert jwt_token is not None
    decoded_jwt = jwt.decode(jwt_token, verify=False)
    assert 'identity' in decoded_jwt

    actual_user = response.json().get('user')
    assert actual_user['username'] == valid_user.username


def test_valid_user_with_invalid_credentials_cannot_authenticate_on_site(
        api_base_uri, valid_user):

    response = requests.post(f'{api_base_uri}/auth', json={
        'username': valid_user.username,
        'password': 'random_password',
    })
    assert_unauthorized_response(response)


def assert_unauthorized_response(response):
    expected_json = {
        'error': {
            'message': 'Invalid credentials provided.',
            'status_code': http.HTTPStatus.UNAUTHORIZED.value,
        },
    }

    assert response.status_code == http.HTTPStatus.UNAUTHORIZED
    assert response.json() == expected_json
