from datetime import datetime

import rfc3339
from flask import json
from flask.testing import FlaskClient

from tests.conftest import AuthActions


def test_get_users_happy_path(auth: AuthActions, client: FlaskClient):
    with auth:
        auth_header = auth.get_authorization_header_token()
        result = client.get(
            '/user',
            headers={
                auth_header[0]: auth_header[1]
            })
        assert 200 == result.status_code
        assert result.json is not None
        assert result.json['page'] == 1
        assert result.json['lastPage'] == 1
        assert result.json['count'] == 1
        assert result.json['totalCount'] == 1
        assert result.json['items'][0]['name'] == auth.username


def test_get_users_nonexistent_page(auth: AuthActions, client: FlaskClient):
    with auth:
        auth_header = auth.get_authorization_header_token()
        result = client.get(
            '/user?page=2',
            headers={
                auth_header[0]: auth_header[1]
            })
        assert 404 == result.status_code
        assert result.json is not None


def test_get_users_bad_page_parameters(auth: AuthActions, client: FlaskClient):
    with auth:
        auth_header = auth.get_authorization_header_token()
        result = client.get(
            '/user?page=a',
            headers={
                auth_header[0]: auth_header[1]
            })
        assert 400 == result.status_code
        assert result.json is not None


def test_get_user_happy_path(auth: AuthActions, client: FlaskClient):
    with auth:
        auth_header = auth.get_authorization_header_token()
        result = client.get(
            '/user/{}'.format(client.application.config['test_username']),
            headers={
                auth_header[0]: auth_header[1]
            })
        assert 200 == result.status_code
        assert result.json is not None
        assert result.json['name'] == client.application.config[
            'test_username']


def test_patch_user_happy_path(auth: AuthActions, client: FlaskClient):
    with auth:
        auth_header = auth.get_authorization_header_token()
        last_login_time = rfc3339.format(datetime.now())

        user = client.get(
            '/user/{}'.format(client.application.config['test_username']),
            headers={
                auth_header[0]: auth_header[1]
            })

        patched_user = client.patch(
            '/user/{}'.format(client.application.config['test_username']),
            data=json.dumps({
                'version': user.json['version'],
                'lastLoginTime': last_login_time
            }),
            headers={
                auth_header[0]: auth_header[1],
                'Content-Type': 'application/json'
            })

        assert 200 == patched_user.status_code
        assert patched_user.json['version'] == user.json['version'] + 1
        assert patched_user.json['lastLoginTime'] == last_login_time


def test_register_user_happy_path(auth: AuthActions, client: FlaskClient):
    with auth:
        auth_header = auth.get_authorization_header_token()
        result = client.post(
            '/user',
            data=json.dumps({
                'name': 'test_registered_user'
            }),
            headers={
                auth_header[0]: auth_header[1],
                'Content-Type': 'application/json'
            })
        assert 200 == result.status_code
        assert result.json is not None
        assert result.json['name'] == 'test_registered_user'


def test_register_user_invalid_password(
        auth: AuthActions, client: FlaskClient):
    with auth:
        auth_header = auth.get_authorization_header_token()
        result = client.post(
            '/user',
            data=json.dumps({
                'name': 'test_registered_user',
                'password': ''
            }),
            headers={
                auth_header[0]: auth_header[1],
                'Content-Type': 'application/json'
            })
        assert 400 == result.status_code
        assert result.json is not None
        assert 'message' in result.json


def test_register_user_twice_failure(auth: AuthActions, client: FlaskClient):
    with auth:
        auth_header = auth.get_authorization_header_token()
        result1 = client.post(
            '/user',
            data=json.dumps({
                'name': 'test_registered_user'
            }),
            headers={
                auth_header[0]: auth_header[1],
                'Content-Type': 'application/json'
            })
        result2 = client.post(
            '/user',
            data=json.dumps({
                'name': 'test_registered_user'
            }),
            headers={
                auth_header[0]: auth_header[1],
                'Content-Type': 'application/json'
            })
        assert 200 == result1.status_code
        assert result1.json is not None
        assert result1.json['name'] == 'test_registered_user'
        assert 400 == result2.status_code
        assert result2.json is not None
        assert result2.json['message'] == 'User name is already taken.'


def test_delete_user_happy_path(auth: AuthActions, client: FlaskClient):
    with auth:
        auth_header = auth.get_authorization_header_token()
        result1 = client.post(
            '/user',
            data=json.dumps({
                'name': 'test_registered_user'
            }),
            headers={
                auth_header[0]: auth_header[1],
                'Content-Type': 'application/json'
            })
        result2 = client.delete(
            '/user/'+result1.json['name'],
            headers={
                auth_header[0]: auth_header[1]
            })
        assert 200 == result1.status_code
        assert result1.json is not None
        assert result1.json['name'] == 'test_registered_user'
        assert 200 == result2.status_code
        assert result2.json is not None
        assert 'message' in result2.json