"""
Configurations for API server tests.

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

import http
from unittest import mock

import pytest_bdd as bdd
import requests
from pytest_bdd import parsers

from tests import utils


@bdd.given(parsers.parse('I am a valid user'))
def auth_token_headers(api_base_uri, db):

    user, password = utils.generate_test_user(db)
    token = requests.post(
        url=f'{api_base_uri}/auth',
        json={
            'username': user.username,
            'password': password,
        }
    ).json()['access_token']

    return {'Authorization': f'JWT {token}'}


@bdd.given(parsers.parse('I am a visitor'), target_fixture='auth_token_headers')
def no_auth_token_headers():
    return {}


@bdd.then(parsers.parse('I get an unauthorized response'))
def assert_unauthorized_response(api_response):
    actual_response = utils.extract_response(api_response)
    expected_response_json = {
        'error': {
            'status_code': http.HTTPStatus.UNAUTHORIZED.value,
            'message': 'Not authorized to access this resource.',
            'resource': actual_response.request.url,
        }
    }

    assert actual_response.status_code == http.HTTPStatus.UNAUTHORIZED
    assert actual_response.json() == expected_response_json


@bdd.then(parsers.parse('I get a conflict response about an existing resource'))
def assert_conflicting_resource_found_response(api_response):
    actual_response = utils.extract_response(api_response)
    expected_response_json = {
        'error': {
            'status_code': http.HTTPStatus.CONFLICT.value,
            'message': 'Existing resource already found.  PUT to the resource to update it.',
            'resource': actual_response.request.url,
        },
    }

    assert actual_response.status_code == http.HTTPStatus.CONFLICT
    assert actual_response.json() == expected_response_json


@bdd.then(parsers.parse('I get a bad request response'))
def assert_bad_request_response(api_response):
    actual_response = utils.extract_response(api_response)
    expected_response_json = {
        'error': {
            'status_code': http.HTTPStatus.BAD_REQUEST.value,
            'message': mock.ANY,
        }
    }

    assert actual_response.json() == expected_response_json
    assert actual_response.status_code == http.HTTPStatus.BAD_REQUEST


@bdd.then(parsers.parse('I get a response indicating the deletion was successful'))
def assert_resource_deleted_response(api_response):
    actual_response = utils.extract_response(api_response)
    assert actual_response.status_code == http.HTTPStatus.NO_CONTENT
    assert not actual_response.content
    assert len(actual_response.content) == 0
