import pytest
from django.contrib.auth.models import AnonymousUser
from django.core.exceptions import PermissionDenied
from django.http import HttpResponse
from django.test import RequestFactory
from django.views import View

from apps.core.permissions.mixins import RoleRequiredMixin
from apps.core.permissions.roles import UserRole


class DummyView(RoleRequiredMixin, View):
    allowed_roles = (UserRole.ADMIN,)

    def get(self, request):
        return HttpResponse("ok")


@pytest.mark.django_db
def test_role_mixin_allows_admin():
    from django.contrib.auth import get_user_model

    User = get_user_model()
    user = User.objects.create_user(email="a@example.com", password="x", role=UserRole.ADMIN)
    rf = RequestFactory()
    req = rf.get("/")
    req.user = user
    resp = DummyView.as_view()(req)
    assert resp.status_code == 200


@pytest.mark.django_db
def test_role_mixin_blocks_wrong_role():
    from django.contrib.auth import get_user_model

    User = get_user_model()
    user = User.objects.create_user(email="b@example.com", password="x", role=UserRole.LEARNER)
    rf = RequestFactory()
    req = rf.get("/")
    req.user = user
    with pytest.raises(PermissionDenied):
        DummyView.as_view()(req)


@pytest.mark.django_db
def test_role_mixin_blocks_staff_without_allowed_role():
    from django.contrib.auth import get_user_model

    User = get_user_model()
    user = User.objects.create_user(email="staff@example.com", password="x", role=UserRole.LEARNER)
    user.is_staff = True
    user.save(update_fields=["is_staff"])
    rf = RequestFactory()
    req = rf.get("/")
    req.user = user
    with pytest.raises(PermissionDenied):
        DummyView.as_view()(req)


def test_role_mixin_redirects_anonymous():
    rf = RequestFactory()
    req = rf.get("/")
    req.user = AnonymousUser()
    resp = DummyView.as_view()(req)
    assert resp.status_code in (302, 301)
