# Standard Library
from unittest.mock import Mock, patch

# Django
from django.test import RequestFactory

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

from incursions.api import auth as auth_api


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()
    auth_api.setup(api)
    return api.routes


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

    @patch("incursions.api.auth.get_main_character_from_user")
    def test_returns_404_when_no_main_character(self, mock_main_char: Mock) -> None:
        mock_main_char.side_effect = Exception("no main character")
        request = self.factory.get("/auth/whoami")
        request.user = Mock(get_all_permissions=Mock(return_value=set()))

        response = self.view(request)

        self.assertEqual(response, (404, {"error": "User has no Main Character Set"}))

    @patch("incursions.api.auth.get_all_characters_from_user")
    @patch("incursions.api.auth.get_main_character_from_user")
    def test_returns_whoami_response(self, mock_main_char: Mock, mock_alts: Mock) -> None:
        main_character = EveCharacter.objects.create(character_id=1001, character_name="Main Pilot")
        alt = EveCharacter.objects.create(character_id=1002, character_name="Alt Pilot")
        mock_main_char.return_value = main_character
        mock_alts.return_value = [main_character, alt]
        request = self.factory.get("/auth/whoami")
        request.user = Mock(get_all_permissions=Mock(return_value={"incursions.basic_waitlist", "other_app.some_perm"}))

        status_code, response = self.view(request)

        self.assertEqual(status_code, 200)
        self.assertEqual(response.main_character_id, main_character.character_id)
        self.assertEqual(response.access, ["incursions.basic_waitlist"])
        self.assertEqual(len(response.characters), 2)
