from urllib.parse import quote

from django.conf import settings as s
from django.test import TestCase, override_settings
from django.urls import reverse

from epdb.logic import PackageManager
from epdb.models import Package, User

_LOGIN_REQUIRED_MW = "epdb.middleware.login_required_middleware.LoginRequiredMiddleware"


def _middleware_with_login_required():
    mw = list(s.MIDDLEWARE)
    return mw if _LOGIN_REQUIRED_MW in mw else [*mw, _LOGIN_REQUIRED_MW]


@override_settings(MODEL_DIR=s.FIXTURE_DIRS[0] / "models", CELERY_TASK_ALWAYS_EAGER=True)
class UserViewTest(TestCase):
    fixtures = ["test_fixtures_incl_model.jsonl.gz"]

    @classmethod
    def setUpClass(cls):
        super(UserViewTest, cls).setUpClass()
        cls.user = User.objects.get(username="anonymous")
        cls.package = PackageManager.create_package(cls.user, "Anon Test Package", "No Desc")
        cls.BBD_SUBSET = Package.objects.get(name="Fixtures")

    def test_login_with_valid_credentials(self):
        response = self.client.post(
            reverse("login"),
            {
                "username": "user0",
                "password": "SuperSafe",
            },
        )
        self.assertRedirects(response, reverse("index"))
        self.assertTrue(response.wsgi_request.user.is_authenticated)

    def test_login_with_invalid_credentials(self):
        response = self.client.post(
            reverse("login"),
            {
                "username": "user0",
                "password": "wrongpassword",
            },
        )
        self.assertEqual(response.status_code, 200)
        self.assertFalse(response.wsgi_request.user.is_authenticated)

    @override_settings(ADMIN_APPROVAL_REQUIRED=True)
    def test_register(self):
        response = self.client.post(
            reverse("register"),
            {
                "username": "user1",
                "email": "user1@envipath.com",
                "password": "SuperSafe",
                "rpassword": "SuperSafe",
            },
        )
        self.assertEqual(response.status_code, 200)
        self.assertContains(
            response,
            "Your account has been created! An admin will activate it soon!",
        )

    def test_register_password_mismatch(self):
        response = self.client.post(
            reverse("register"),
            {
                "username": "user1",
                "email": "user1@envipath.com",
                "password": "SuperSafe",
                "rpassword": "SuperSaf3",
            },
        )
        self.assertEqual(response.status_code, 200)
        self.assertContains(response, "Registration failed, provided passwords differ")

    def test_logout(self):
        response = self.client.post(
            reverse("login"), {"username": "user0", "password": "SuperSafe", "login": "true"}
        )
        self.assertTrue(response.wsgi_request.user.is_authenticated)

        response = self.client.post(
            reverse("logout"),
            {
                "logout": "true",
            },
        )
        self.assertFalse(response.wsgi_request.user.is_authenticated)

    @override_settings(MIDDLEWARE=_middleware_with_login_required())
    def test_next_param_properly_handled(self):
        packages_url = reverse("packages")
        response = self.client.get(packages_url)
        self.assertRedirects(
            response,
            f"{s.LOGIN_URL}?next={quote(packages_url)}",
            fetch_redirect_response=False,
        )

        response = self.client.post(
            reverse("login"),
            {"username": "user0", "password": "SuperSafe", "login": "true", "next": packages_url},
        )

        self.assertRedirects(response, packages_url)
