from django.contrib.auth import get_user_model
from django.test import Client, TestCase
from django.urls import reverse, reverse_lazy
from django.utils import timezone

from gestion.models import ErnestoUser
from pads.models import Pad

User = get_user_model()


def new_user(username):
    u = User.objects.create_user(username=username)
    ErnestoUser.objects.create(user=u, slug=username, is_ernesto=True)
    return u


class PadListTest(TestCase):
    url = reverse_lazy("pads:list")

    def setUp(self):
        for name in ["foo", "bar", "baz"]:
            Pad.objects.create(
                nom=name, url="example.com/{}".format(name), date=timezone.now()
            )

    def test_anonymous_cannot_get(self):
        response = Client().get(self.url)
        self.assertRedirects(response, "/login?next={}".format(self.url))

    def test_ernesto_user_can_get(self):
        client = Client()
        client.force_login(new_user("toto"))

        response = client.get(self.url)
        self.assertEqual(response.status_code, 200)


class PadCreateTest(TestCase):
    url = reverse_lazy("pads:add")

    def test_anonymous_cannot_get(self):
        response = Client().get(self.url)
        self.assertRedirects(response, "/login?next={}".format(self.url))

    def test_anonymous_cannot_post(self):
        response = Client().post(self.url, {"nom": "foo", "url": "http://example.com"})
        self.assertRedirects(response, "/login?next={}".format(self.url))

    def test_ernesto_cannot_get(self):
        client = Client()
        client.force_login(new_user("toto"))
        response = client.get(self.url)
        self.assertEqual(response.status_code, 403)

    def test_ernesto_cannot_post(self):
        client = Client()
        client.force_login(new_user("toto"))
        response = client.post(self.url, {"nom": "foo", "url": "http://example.com"})
        self.assertEqual(response.status_code, 403)

    def test_chef_can_get(self):
        user = new_user("toto")
        user.profile.is_chef = True
        user.profile.save()
        client = Client()
        client.force_login(user)

        response = client.get(self.url)
        self.assertEqual(response.status_code, 200)

    def test_chef_can_post(self):
        user = new_user("toto")
        user.profile.is_chef = True
        user.profile.save()
        client = Client()
        client.force_login(user)

        client.post(self.url, {"nom": "foo", "url": "http://example.com"})
        pads = Pad.objects.all()
        self.assertEqual(pads.count(), 1)
        pad = pads.get()
        self.assertEqual(pad.nom, "foo")
        self.assertEqual(pad.url, "http://example.com")


class PadUpdateTest(TestCase):
    def setUp(self):
        pad = Pad.objects.create(
            nom="bar", url="http://djangoproject.com", date=timezone.now()
        )
        self.url = reverse("pads:edit", args=(pad.id,))

    def test_anonymous_cannot_get(self):
        response = Client().get(self.url)
        self.assertRedirects(response, "/login?next={}".format(self.url))

    def test_anonymous_cannot_post(self):
        response = Client().post(self.url, {"nom": "foo", "url": "http://example.com"})
        self.assertRedirects(response, "/login?next={}".format(self.url))

    def test_ernesto_cannot_get(self):
        client = Client()
        client.force_login(new_user("toto"))
        response = client.get(self.url)
        self.assertEqual(response.status_code, 403)

    def test_ernesto_cannot_post(self):
        client = Client()
        client.force_login(new_user("toto"))
        response = client.post(self.url, {"nom": "foo", "url": "http://example.com"})
        self.assertEqual(response.status_code, 403)

    def test_chef_can_get(self):
        user = new_user("toto")
        user.profile.is_chef = True
        user.profile.save()
        client = Client()
        client.force_login(user)

        response = client.get(self.url)
        self.assertEqual(response.status_code, 200)

    def test_chef_can_post(self):
        user = new_user("toto")
        user.profile.is_chef = True
        user.profile.save()
        client = Client()
        client.force_login(user)

        client.post(self.url, {"nom": "foo", "url": "http://example.com"})
        pads = Pad.objects.all()
        self.assertEqual(pads.count(), 1)
        pad = pads.get()
        self.assertEqual(pad.nom, "foo")
        self.assertEqual(pad.url, "http://example.com")


class PadDeleteTest(TestCase):
    def setUp(self):
        pad = Pad.objects.create(
            nom="bar", url="http://djangoproject.com", date=timezone.now()
        )
        self.url = reverse("pads:delete", args=(pad.id,))

    def test_anonymous_cannot_get(self):
        response = Client().get(self.url)
        self.assertRedirects(response, "/login?next={}".format(self.url))

    def test_anonymous_cannot_post(self):
        response = Client().post(self.url, {})
        self.assertRedirects(response, "/login?next={}".format(self.url))

    def test_ernesto_cannot_get(self):
        client = Client()
        client.force_login(new_user("toto"))
        response = client.get(self.url)
        self.assertEqual(response.status_code, 403)

    def test_ernesto_cannot_post(self):
        client = Client()
        client.force_login(new_user("toto"))
        response = client.post(self.url, {})
        self.assertEqual(response.status_code, 403)

    def test_chef_can_get(self):
        user = new_user("toto")
        user.profile.is_chef = True
        user.profile.save()
        client = Client()
        client.force_login(user)

        response = client.get(self.url)
        self.assertEqual(response.status_code, 200)

    def test_chef_can_post(self):
        user = new_user("toto")
        user.profile.is_chef = True
        user.profile.save()
        client = Client()
        client.force_login(user)

        client.post(self.url, {})
        self.assertFalse(Pad.objects.exists())
