"""
Functional tests for the user authentication feature.

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

import collections
import http

import jwt
import pytest_bdd as bdd
from pytest_bdd import parsers
import requests


TEST_USERS = {
    'valid': {
        'valid': 'password',
        'invalid': '123',
    },
    'invalid': {'some': 'login'},
}


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


@bdd.scenario('user_authentication.feature', 'Valid user can authenticate against site with valid credentials')
def test_authentication_with_valid_credentials():
    pass


@bdd.scenario('user_authentication.feature', 'Valid user cannot authenticate against site with invalid credentials')
def test_authentication_with_invalid_credentials():
    pass


@bdd.scenario('user_authentication.feature', 'Invalid user cannot authenticate against site with credentials')
def test_authentication_with_invalid_user():
    pass


@bdd.given(parsers.parse('I am a {user_type} user with {login_type} credentials'))
def user_credentials(user_type, login_type):
    user_name = 'random_user'
    if user_type == 'valid':
        user_name = 'admin'
    password = TEST_USERS.get(user_type, {}).get(login_type, '')
    return Credentials(username=user_name, password=password, response={})


@bdd.when('I post my credentials against the auth endpoint')
def posted_response_from_auth_endpoint(user_credentials, api_base_uri):
    response = requests.post(f'{api_base_uri}/auth', json={
        'username': user_credentials.username,
        'password': user_credentials.password,
    })
    user_credentials.response['status'] = response.status_code
    user_credentials.response['json'] = response.json()


@bdd.then('I get a valid JWT')
def assert_valid_user_json_web_token(user_credentials):
    assert user_credentials.response['status'] == http.HTTPStatus.OK

    jwt_token = user_credentials.response['json']['token']
    assert jwt_token is not None

    validated_user_credentials = user_credentials.response['json']['user']
    assert user_credentials.username == validated_user_credentials.get('username')
    decoded_jwt = jwt.decode(jwt_token, verify=False)
    assert 'identity' in decoded_jwt


@bdd.then('I get an unauthorized response')
def assert_unauthorized_response(user_credentials):
    assert user_credentials.response['status'] == http.HTTPStatus.UNAUTHORIZED
    assert user_credentials.response['json']['status_code'] == http.HTTPStatus.UNAUTHORIZED
    assert user_credentials.response['json']['error'] == 'Bad Request'
    assert user_credentials.response['json']['description'] == 'Invalid credentials'
