# Standard Library
from unittest.mock import Mock

# Django
from django.test import RequestFactory

# Alliance Auth (Core)
from allianceauth.utils.testing import NoSocketsTestCase

from incursions.api import categories as categories_api
from incursions.models.waitlist import WaitlistCategory


class FakeAPI:
    def __init__(self) -> None:
        self.routes: dict[str, object] = {}

    def get(self, path: str, **kwargs: object):
        def decorator(func):
            self.routes[path] = func
            return func
        return decorator


def _routes() -> dict[str, object]:
    api = FakeAPI()
    categories_api.setup(api)
    return api.routes


def _user(**perms: bool) -> Mock:
    return Mock(has_perm=Mock(side_effect=lambda perm: perms.get(perm, False)))


class TestListCategories(NoSocketsTestCase):
    def setUp(self) -> None:
        self.factory = RequestFactory()
        self.routes = _routes()
        self.view = self.routes["/categories"]

    def test_denies_without_permission(self) -> None:
        request = self.factory.get("/categories")
        request.user = _user()

        response = self.view(request)

        self.assertEqual(response, (403, {"error": "Permission denied"}))

    def test_returns_categories(self) -> None:
        category = WaitlistCategory.objects.create(name="SPONGE")
        request = self.factory.get("/categories")
        request.user = _user(**{"incursions.basic_waitlist": True})

        status_code, response = self.view(request)

        self.assertEqual(status_code, 200)
        self.assertEqual(len(response.categories), 1)
        self.assertEqual(response.categories[0].id, category.pk)
        self.assertEqual(response.categories[0].name, "SPONGE")
