"""Test Groups API"""

from django.urls.base import reverse
from rest_framework.test import APITestCase

from authentik.core.models import Group
from authentik.core.tests.utils import create_test_admin_user, create_test_user
from authentik.lib.generators import generate_id


class TestGroupsAPI(APITestCase):
    """Test Groups API"""

    def setUp(self) -> None:
        self.login_user = create_test_user()
        self.user = create_test_user()

    def test_list_with_users(self):
        """Test listing with users"""
        admin = create_test_admin_user()
        self.client.force_login(admin)
        response = self.client.get(reverse("authentik_api:group-list"), {"include_users": "true"})
        self.assertEqual(response.status_code, 200)

    def test_retrieve_with_users(self):
        """Test retrieve with users"""
        admin = create_test_admin_user()
        group = Group.objects.create(name=generate_id())
        self.client.force_login(admin)
        response = self.client.get(
            reverse("authentik_api:group-detail", kwargs={"pk": group.pk}),
            {"include_users": "true"},
        )
        self.assertEqual(response.status_code, 200)

    def test_add_user(self):
        """Test add_user"""
        group = Group.objects.create(name=generate_id())
        self.login_user.assign_perms_to_managed_role("authentik_core.add_user_to_group", group)
        self.login_user.assign_perms_to_managed_role("authentik_core.view_user")
        self.client.force_login(self.login_user)
        res = self.client.post(
            reverse("authentik_api:group-add-user", kwargs={"pk": group.pk}),
            data={
                "pk": self.user.pk,
            },
        )
        self.assertEqual(res.status_code, 204)
        group.refresh_from_db()
        self.assertEqual(list(group.users.all()), [self.user])

    def test_add_user_404(self):
        """Test add_user"""
        group = Group.objects.create(name=generate_id())
        self.login_user.assign_perms_to_managed_role("authentik_core.add_user_to_group", group)
        self.login_user.assign_perms_to_managed_role("authentik_core.view_user")
        self.client.force_login(self.login_user)
        res = self.client.post(
            reverse("authentik_api:group-add-user", kwargs={"pk": group.pk}),
            data={
                "pk": self.user.pk + 3,
            },
        )
        self.assertEqual(res.status_code, 404)

    def test_remove_user(self):
        """Test remove_user"""
        group = Group.objects.create(name=generate_id())
        self.login_user.assign_perms_to_managed_role("authentik_core.remove_user_from_group", group)
        self.login_user.assign_perms_to_managed_role("authentik_core.view_user")
        group.users.add(self.user)
        self.client.force_login(self.login_user)
        res = self.client.post(
            reverse("authentik_api:group-remove-user", kwargs={"pk": group.pk}),
            data={
                "pk": self.user.pk,
            },
        )
        self.assertEqual(res.status_code, 204)
        group.refresh_from_db()
        self.assertEqual(list(group.users.all()), [])

    def test_remove_user_404(self):
        """Test remove_user"""
        group = Group.objects.create(name=generate_id())
        self.login_user.assign_perms_to_managed_role("authentik_core.remove_user_from_group", group)
        self.login_user.assign_perms_to_managed_role("authentik_core.view_user")
        group.users.add(self.user)
        self.client.force_login(self.login_user)
        res = self.client.post(
            reverse("authentik_api:group-remove-user", kwargs={"pk": group.pk}),
            data={
                "pk": self.user.pk + 3,
            },
        )
        self.assertEqual(res.status_code, 404)

    def test_superuser_no_perm(self):
        """Test creating a superuser group without permission"""
        self.login_user.assign_perms_to_managed_role("authentik_core.add_group")
        self.client.force_login(self.login_user)
        res = self.client.post(
            reverse("authentik_api:group-list"),
            data={"name": generate_id(), "is_superuser": True},
        )
        self.assertEqual(res.status_code, 400)
        self.assertJSONEqual(
            res.content,
            {"is_superuser": ["User does not have permission to set superuser status to True."]},
        )

    def test_superuser_no_perm_no_superuser(self):
        """Test creating a group without permission and without superuser flag"""
        self.login_user.assign_perms_to_managed_role("authentik_core.add_group")
        self.client.force_login(self.login_user)
        res = self.client.post(
            reverse("authentik_api:group-list"),
            data={"name": generate_id(), "is_superuser": False},
        )
        self.assertEqual(res.status_code, 201)

    def test_superuser_update_no_perm(self):
        """Test updating a superuser group without permission"""
        group = Group.objects.create(name=generate_id(), is_superuser=True)
        self.login_user.assign_perms_to_managed_role("authentik_core.view_group", group)
        self.login_user.assign_perms_to_managed_role("authentik_core.change_group", group)
        self.client.force_login(self.login_user)
        res = self.client.patch(
            reverse("authentik_api:group-detail", kwargs={"pk": group.pk}),
            data={"is_superuser": False},
        )
        self.assertEqual(res.status_code, 400)
        self.assertJSONEqual(
            res.content,
            {"is_superuser": ["User does not have permission to set superuser status to False."]},
        )

    def test_superuser_update_no_change(self):
        """Test updating a superuser group without permission
        and without changing the superuser status"""
        group = Group.objects.create(name=generate_id(), is_superuser=True)
        self.login_user.assign_perms_to_managed_role("authentik_core.view_group", group)
        self.login_user.assign_perms_to_managed_role("authentik_core.change_group", group)
        self.client.force_login(self.login_user)
        res = self.client.patch(
            reverse("authentik_api:group-detail", kwargs={"pk": group.pk}),
            data={"name": generate_id(), "is_superuser": True},
        )
        self.assertEqual(res.status_code, 200)

    def test_superuser_create(self):
        """Test creating a superuser group with permission"""
        self.login_user.assign_perms_to_managed_role("authentik_core.add_group")
        self.login_user.assign_perms_to_managed_role("authentik_core.enable_group_superuser")
        self.client.force_login(self.login_user)
        res = self.client.post(
            reverse("authentik_api:group-list"),
            data={"name": generate_id(), "is_superuser": True},
        )
        self.assertEqual(res.status_code, 201)
