import pytest
from django.contrib.auth.models import User
from django.urls import reverse

from core.models import ConsoleAuthSettings, UsernameLoginAuthCheck
from core.tasks import check_for_users_end_of_timeouts
from core.utils import dtnow

TEST_USERNAME = 'foo'
TEST_PASSWORD = 'bar'
LOGIN_URL_NAME = 'api_login'


@pytest.mark.django_db
class TestAssetPagesAccess(object):

    @pytest.fixture(autouse=True)
    def setup_tests(self, client, django_user_model, add_user_with_permissions):
        add_user_with_permissions(username=TEST_USERNAME, password=TEST_PASSWORD, is_superuser=True)

    @pytest.mark.unit
    def test_success_log(self, caplog, client):
        client.post(reverse(LOGIN_URL_NAME),
                    data={'username': TEST_USERNAME, 'password': TEST_PASSWORD})
        assert f'[{TEST_USERNAME}] has been successfully authenticated' in caplog.text

    # TODO: Strange test, unlock user only after login try
    @pytest.mark.unit
    @pytest.mark.django_db
    def test_unlock_user_task(self, client, caplog):
        client.post(reverse(LOGIN_URL_NAME),
                    data={'username': TEST_USERNAME, 'password': TEST_PASSWORD})
        test_user = User.objects.get(username=TEST_USERNAME)
        test_user_authentication_settings = UsernameLoginAuthCheck.objects.get(user=test_user)
        test_user_authentication_settings.is_username_auth_blocked = True
        test_user_authentication_settings.username_unlock_time = dtnow(days=-1)
        test_user_authentication_settings.save()
        response = client.post(reverse(LOGIN_URL_NAME),
                               data={'username': TEST_USERNAME, 'password': TEST_PASSWORD})

        assert response.status_code == 400
        assert f'[{TEST_USERNAME}] account is blocked until' in caplog.text
        check_for_users_end_of_timeouts()
        assert not UsernameLoginAuthCheck.objects.get(user=test_user).is_username_auth_blocked

    @pytest.mark.unit
    @pytest.mark.django_db
    def test_block(self, caplog, client):
        auth_settings = ConsoleAuthSettings.get_solo()
        for i in range(0, auth_settings.login_attempts_limit):
            client.post(reverse(LOGIN_URL_NAME),
                        data={'username': TEST_USERNAME, 'password': 'BAD_PASSWORD'})

        test_user = User.objects.get(username=TEST_USERNAME)
        test_user_authentication_settings = UsernameLoginAuthCheck.objects.get(user=test_user)
        assert test_user_authentication_settings.is_username_auth_blocked

    @pytest.mark.unit
    @pytest.mark.django_db
    def test_limit_reset_after_correct_authentication_data(self, caplog, client):
        auth_settings = ConsoleAuthSettings.get_solo()
        for i in range(0, auth_settings.login_attempts_limit - 1):
            client.post(reverse(LOGIN_URL_NAME),
                        data={'username': TEST_USERNAME, 'password': 'BAD_PASSWORD'})

        response = client.post(reverse(LOGIN_URL_NAME),
                               data={'username': TEST_USERNAME, 'password': TEST_PASSWORD})
        test_user = User.objects.get(username=TEST_USERNAME)
        test_user_authentication_settings = UsernameLoginAuthCheck.objects.get(user=test_user)
        assert response.status_code == 200
        assert not test_user_authentication_settings.is_username_auth_blocked
        assert test_user_authentication_settings.failed_login_attempts == 0
