"""
Functional tests for the managing sites.

: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


# TODO: Rework site management and testing.
bdd.scenarios('site_access.feature')
# TODO: Rework modification to only allow changes to layout and children...
# bdd.scenarios('site_modification.feature')


@bdd.given(parsers.parse('I try to modify the site with a non-json request'), target_fixture='api_response')
def invalid_non_json_modify_site_response(api_response, auth_token_headers, api_base_uri):
    return requests.put(
        url=f'{api_base_uri}/api/site',
        data='',
        headers=auth_token_headers,
    )


@bdd.given(parsers.parse('I try to modify the site with an empty retest_sitequest'), target_fixture='api_response')
def invalid_empty_modify_site_response(api_response, auth_token_headers, api_base_uri):
    return requests.put(
        url=f'{api_base_uri}/api/site',
        json={},
        headers=auth_token_headers,
    )


@bdd.given(parsers.parse('I get the site'), target_fixture='api_response')
def get_site_request(test_site, auth_token_headers, api_base_uri):
    response = requests.get(
        url=f'{api_base_uri}/api/site',
        headers=auth_token_headers,
    )
    return utils.ResponseSampleBundle(response, test_site)


@bdd.then(parsers.parse('I get a valid site with a menu and landing page'))
def assert_site_response(api_response):

    actual_response = utils.extract_response(api_response)
    assert actual_response.status_code == http.HTTPStatus.OK

    expected_json = {
        'name': 'Rookeries',
        'urls': {'self': '/api/site'},
        'config': mock.ANY,
        # TODO: Make sure to test against a real test landing page.
        'landingPage': mock.ANY,
        'menu': []
    }
    assert expected_json == actual_response.json()


@bdd.given(parsers.parse('I try to modify the site'), target_fixture='api_response')
def modify_site_response(test_site, api_response, auth_token_headers, api_base_uri):
    test_site = api_response.sample
    site_modification_request = {}

    response = requests.put(
        url=f'{api_base_uri}/api/site',
        json=site_modification_request,
        headers=auth_token_headers,
    )
    return utils.ResponseSampleBundle(response, test_site)


@bdd.given(parsers.parse('I try to modify a site that does not exist'), target_fixture='api_response')
def modify_non_existent_site_request(test_site, auth_token_headers, api_base_uri):
    site_modification_request = {
    }

    return requests.put(
        url=f'{api_base_uri}/api/site',
        json=site_modification_request,
        headers=auth_token_headers,
    )


@bdd.then(parsers.parse('my updates are reflected in the site'))
def assert_updated_site_response(api_response, api_base_uri):
    actual_response = utils.extract_response(api_response)
    assert actual_response.status_code == http.HTTPStatus.OK

    expected_json = {}
    assert expected_json == actual_response.json()
    assert f'{api_base_uri}/api/site' == actual_response.json()['urls']['self']


@bdd.then(parsers.parse('I get a site can not be found message'))
def assert_resource_not_found_response(api_response):
    actual_response = utils.extract_response(api_response)
    expected_response_json = {
        'error': {
            'status_code': http.HTTPStatus.NOT_FOUND.value,
            'message': 'Resource not found.',
            'resource': actual_response.request.url,
        },
    }

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