import json

from django.test import TestCase

from apps.drama.models import GameEvent, record
from apps.epic.models import Room
from apps.lyric.models import User


class WebFingerTest(TestCase):

    def setUp(self):
        self.user = User.objects.create(email="actor@test.io", username="actor")

    def test_returns_jrd_for_known_user(self):
        response = self.client.get(
            "/.well-known/webfinger",
            {"resource": "acct:actor@earthmanrpg.me"},
        )
        self.assertEqual(response.status_code, 200)
        self.assertEqual(response["Content-Type"], "application/jrd+json")

    def test_jrd_links_to_actor_url(self):
        response = self.client.get(
            "/.well-known/webfinger",
            {"resource": "acct:actor@earthmanrpg.me"},
        )
        data = json.loads(response.content)
        hrefs = [link["href"] for link in data["links"]]
        self.assertTrue(any("/ap/users/actor/" in href for href in hrefs))

    def test_returns_404_for_unknown_user(self):
        response = self.client.get(
            "/.well-known/webfinger",
            {"resource": "acct:nobody@earthmanrpg.me"},
        )
        self.assertEqual(response.status_code, 404)

    def test_returns_400_for_missing_resource(self):
        response = self.client.get("/.well-known/webfinger")
        self.assertEqual(response.status_code, 400)


class ActorViewTest(TestCase):

    def setUp(self):
        self.user = User.objects.create(email="actor@test.io", username="actor")

    def test_returns_200_for_known_user(self):
        response = self.client.get("/ap/users/actor/")
        self.assertEqual(response.status_code, 200)

    def test_returns_activity_json_content_type(self):
        response = self.client.get("/ap/users/actor/")
        self.assertEqual(response["Content-Type"], "application/activity+json")

    def test_actor_has_required_fields(self):
        response = self.client.get("/ap/users/actor/")
        data = json.loads(response.content)
        self.assertEqual(data["type"], "Person")
        self.assertIn("id", data)
        self.assertIn("outbox", data)
        self.assertIn("publicKey", data)

    def test_requires_no_authentication(self):
        # AP Actor endpoints must be publicly accessible
        self.client.logout()
        response = self.client.get("/ap/users/actor/")
        self.assertEqual(response.status_code, 200)

    def test_returns_404_for_unknown_user(self):
        response = self.client.get("/ap/users/nobody/")
        self.assertEqual(response.status_code, 404)


class OutboxViewTest(TestCase):

    def setUp(self):
        self.user = User.objects.create(email="actor@test.io", username="actor")
        self.room = Room.objects.create(name="Test Room", owner=self.user)
        record(
            self.room, GameEvent.SLOT_FILLED, actor=self.user,
            slot_number=1, token_type="coin",
            token_display="Coin", renewal_days=7,
        )
        record(
            self.room, GameEvent.ROLE_SELECTED, actor=self.user,
            role="PC", slot_number=1, role_display="Player",
        )
        # INVITE_SENT is unsupported — should be excluded from outbox
        record(self.room, GameEvent.INVITE_SENT, actor=self.user)

    def test_returns_200(self):
        response = self.client.get("/ap/users/actor/outbox/")
        self.assertEqual(response.status_code, 200)

    def test_returns_activity_json_content_type(self):
        response = self.client.get("/ap/users/actor/outbox/")
        self.assertEqual(response["Content-Type"], "application/activity+json")

    def test_outbox_is_ordered_collection(self):
        response = self.client.get("/ap/users/actor/outbox/")
        data = json.loads(response.content)
        self.assertEqual(data["type"], "OrderedCollection")

    def test_total_items_excludes_unsupported_verbs(self):
        response = self.client.get("/ap/users/actor/outbox/")
        data = json.loads(response.content)
        # 2 supported events (SLOT_FILLED + ROLE_SELECTED); INVITE_SENT excluded
        self.assertEqual(data["totalItems"], 2)

    def test_requires_no_authentication(self):
        self.client.logout()
        response = self.client.get("/ap/users/actor/outbox/")
        self.assertEqual(response.status_code, 200)

    def test_returns_404_for_unknown_user(self):
        response = self.client.get("/ap/users/nobody/outbox/")
        self.assertEqual(response.status_code, 404)
