"""
Unit tests
"""

import os

from django.contrib.auth.models import User
from django.test import TestCase
from django.urls import reverse
from rest_framework import status
from rest_framework.test import APIRequestFactory, APITestCase

from . import wsgi
from .api_url_inflect import url_deviations
from .api_views import ModelViewSetFactory
from .settings import get_setting


class URLDeviationsTestCase(TestCase):
    """
    Tests for the URL deviations generator.
    """

    def test_simple(self):
        d = url_deviations("Thing")
        self.assertIn("thing", d)
        self.assertIn("things", d)

    def test_two_simple_words(self):
        d = url_deviations("SomeThing")
        self.assertIn("something", d)
        self.assertIn("somethings", d)
        self.assertIn("some_thing", d)
        self.assertIn("some_things", d)

    def test_acronyms(self):
        d = url_deviations("PCSystem")
        self.assertIn("pcsystem", d)
        self.assertIn("pcsystems", d)
        self.assertIn("pc_system", d)
        self.assertIn("pc_systems", d)


class WsgiTestCase(TestCase):
    """
    Test WSGI doesn't fail.
    """

    def test_wsgi_simple(self):
        self.assertTrue(wsgi.application)


class ModelViewSetFactoryTestCase(TestCase):
    """
    Testing that the viewset factory works with various configuration options.
    """

    def setUp(self):
        self.user_admin_viewset_factory = ModelViewSetFactory(
            default_enable=False,
            default_use_admin=True,
            admin_site=get_setting("AUTOREST_ADMIN_SITE"),
            config={"auth": {"User": {"use_admin_site": True}}},
        )
        self.user_model = User

    def test_build_user_admin_viewset(self):
        viewset = self.user_admin_viewset_factory.build(self.user_model)
        self.assertTrue(viewset)


class APITestCase(APITestCase):
    """
    Tests for the autogenerated API.
    """

    def setUp(self):
        self.factory = APIRequestFactory()
        self.user = User.objects.create_superuser(
            username="greg_schmit",
            email="greg_schmit@example.com",
            password="top_secret",
        )
        self.other_user = User.objects.create_superuser(
            username="john_doe", email="john_doe@example.com", password="bottom_secret"
        )
        self.plain_user = User.objects.create_user(
            username="johnny_doe",
            email="johnny_doe@example.com",
            password="plain_secret",
        )

    def test_unauthorized_group_list(self):
        url = reverse("group-list")
        response = self.client.get(url)
        self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)

    def test_authorized_group_list(self):
        url = reverse("group-list")
        self.client.login(username="greg_schmit", password="top_secret")
        response = self.client.get(url)
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.client.logout()

    def test_create_user(self):
        url = reverse("user-list")
        self.client.login(username="greg_schmit", password="top_secret")
        response = self.client.post(
            url,
            {
                "username": "testuser",
                "password_first": "test_secret",
                "password_confirmation": "test_secret",
                "email": "testuser@example.com",
            },
        )
        self.assertEqual(response.status_code, status.HTTP_201_CREATED)
        self.client.logout()

    def test_create_user_failure(self):
        url = reverse("user-list")
        self.client.login(username="greg_schmit", password="top_secret")
        response = self.client.post(
            url,
            {
                "username": "testuserfail",
                "password_first": "test_secret",
                "password_confirmation": "test_sedret",
                "email": "testuserfail@example.com",
            },
        )
        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
        self.client.logout()

    def test_update_user(self):
        url = reverse("user-detail", args=[self.plain_user.pk])
        self.client.login(username="greg_schmit", password="top_secret")
        response = self.client.patch(url, {"email": "mr_johnny_doe@example.com"})
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.plain_user.refresh_from_db()
        self.assertEqual(self.plain_user.email, "mr_johnny_doe@example.com")
        self.client.logout()

    def test_update_user_password(self):
        url = reverse("user-detail", args=[self.plain_user.pk])
        self.client.login(username="greg_schmit", password="top_secret")
        old_password = self.plain_user.password
        response = self.client.patch(
            url,
            {
                "password_first": "new_plain_secret",
                "password_confirmation": "new_plain_secret",
            },
        )
        self.plain_user.refresh_from_db()
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertNotEqual(old_password, self.plain_user.password)
        self.client.logout()
