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

from apps.core.permissions.access import can_manage_users, sync_user_role_group
from apps.core.permissions.roles import UserRole


@pytest.mark.django_db
def test_sync_user_role_group_adds_matching_group(django_user_model):
    u = django_user_model.objects.create_user(email="a@x.com", password="x", role=UserRole.REVIEWER)
    sync_user_role_group(u)
    assert u.groups.filter(name=UserRole.REVIEWER).exists()
    assert u.groups.filter(name__in=[r.value for r in UserRole]).count() == 1


@pytest.mark.django_db
def test_sync_user_role_group_clears_when_role_blank(django_user_model):
    u = django_user_model.objects.create_user(email="b@x.com", password="x", role=UserRole.REVIEWER)
    sync_user_role_group(u)
    u.role = ""
    u.save()
    sync_user_role_group(u)
    assert not u.groups.filter(name=UserRole.REVIEWER).exists()


@pytest.mark.django_db
def test_can_manage_users_admin_role(django_user_model):
    u = django_user_model.objects.create_user(email="c@x.com", password="x", role=UserRole.ADMIN)
    assert can_manage_users(u)


@pytest.mark.django_db
def test_user_manage_list_forbidden_for_learner(client, django_user_model):
    u = django_user_model.objects.create_user(email="d@x.com", password="x", role=UserRole.LEARNER)
    client.force_login(u)
    r = client.get(reverse("core:user_manage_list"))
    assert r.status_code == 403


@pytest.mark.django_db
def test_user_manage_list_ok_for_superuser(client, django_user_model):
    u = django_user_model.objects.create_user(
        email="e@x.com",
        password="x",
        is_superuser=True,
        is_staff=True,
    )
    client.force_login(u)
    # /access/users/ now redirects to the staff Manage users surface.
    r = client.get(reverse("core:user_manage_list"))
    assert r.status_code == 302
    assert r.url.startswith(reverse("accounts:manage_users"))


@pytest.mark.django_db
def test_role_permissions_edit_allows_custom_group(client, django_user_model):
    """Custom groups created via the role-create flow are editable by admins.

    This used to forbid non-IILMP-enum groups, but the role-create UI now
    intentionally lets admins define custom roles whose permissions still
    need to be configurable here.
    """
    su = django_user_model.objects.create_user(
        email="su@x.com",
        password="x",
        is_superuser=True,
        is_staff=True,
    )
    client.force_login(su)
    g = Group.objects.create(name="custom_not_a_role")
    r = client.get(reverse("core:role_permissions_edit", kwargs={"group_id": g.pk}))
    assert r.status_code == 200


@pytest.mark.django_db
def test_role_create_creates_group_and_redirects(client, django_user_model):
    su = django_user_model.objects.create_user(
        email="ru@x.com",
        password="x",
        is_superuser=True,
        is_staff=True,
    )
    client.force_login(su)
    r = client.post(reverse("core:role_create"), {"name": "Marketing reviewer"})
    assert r.status_code == 302
    g = Group.objects.get(name="Marketing reviewer")
    assert r.url == reverse("core:role_permissions_edit", kwargs={"group_id": g.pk})


@pytest.mark.django_db
def test_role_create_rejects_duplicate_name(client, django_user_model):
    su = django_user_model.objects.create_user(
        email="rd@x.com",
        password="x",
        is_superuser=True,
        is_staff=True,
    )
    client.force_login(su)
    Group.objects.create(name="Existing role")
    r = client.post(reverse("core:role_create"), {"name": "existing role"})
    assert r.status_code == 200
    assert b"already exists" in r.content
