"""ITs for the Brief sprint C3.a — Note.grant_if_new spawns Line + Brief.

Per the per-category Post model: the user has a single "Note Unlocks" Post;
each unlock appends a Line ("Stargazer, 5:21pm") and spawns a Brief FKing
the appended Line. Briefs of kind=NOTE_UNLOCK live on Posts of kind=
NOTE_UNLOCK.
"""

from django.test import TestCase

from apps.billboard.models import Brief, Line, Post
from apps.drama.models import Note
from apps.lyric.models import User


class GrantIfNewSpawnsBriefTest(TestCase):
    def setUp(self):
        self.user = User.objects.create(email="brief-grant@test.io")

    def test_first_grant_creates_post_line_and_brief(self):
        note, created, brief = Note.grant_if_new(self.user, "stargazer")
        self.assertTrue(created)
        self.assertIsNotNone(brief)
        # Note Unlocks Post created on user
        post = Post.objects.get(owner=self.user, kind=Post.KIND_NOTE_UNLOCK)
        # Brief points at that Post + the appended Line
        self.assertEqual(brief.post_id, post.id)
        self.assertEqual(brief.kind, Brief.KIND_NOTE_UNLOCK)
        self.assertTrue(brief.is_unread)
        self.assertEqual(brief.owner, self.user)
        # The Brief's line is one of the Post's lines
        self.assertIn(brief.line, list(post.lines.all()))
        # Brief title matches Note display name (the Note's name — used in the
        # banner's title slot and inline "the {name}" attribution).
        self.assertEqual(brief.title, note.display_name)

    def test_second_grant_same_slug_returns_no_brief(self):
        Note.grant_if_new(self.user, "stargazer")
        note, created, brief = Note.grant_if_new(self.user, "stargazer")
        self.assertFalse(created)
        self.assertIsNone(brief)
        # Still only one Brief / Line for the user (idempotent)
        self.assertEqual(
            Brief.objects.filter(owner=self.user, kind=Brief.KIND_NOTE_UNLOCK).count(), 1
        )

    def test_two_different_grants_share_one_post(self):
        """Per-category Post: stargazer + schizo unlocks both append Lines to
        the same "Notes & recognitions" Post (one growing thread)."""
        Note.grant_if_new(self.user, "stargazer")
        Note.grant_if_new(self.user, "schizo")
        posts = Post.objects.filter(owner=self.user, kind=Post.KIND_NOTE_UNLOCK)
        self.assertEqual(posts.count(), 1, "Only one Note Unlocks Post per user")
        post = posts.first()
        # 2 Briefs, one per unlock
        self.assertEqual(Brief.objects.filter(post=post).count(), 2)
        # 2 distinct Lines on the Post — one per grant. The standalone
        # "Look! — new Note unlocked" header Line was dropped in the May-8b
        # refactor; the standard format now embeds that text inline per Line.
        line_texts = list(post.lines.values_list("text", flat=True))
        self.assertEqual(len(set(line_texts)), 2)

    def test_brief_line_text_includes_note_title(self):
        _, _, brief = Note.grant_if_new(self.user, "stargazer")
        self.assertIn("Stargazer", brief.line.text)

    def test_post_kind_is_note_unlock_for_grant(self):
        Note.grant_if_new(self.user, "stargazer")
        post = Post.objects.get(owner=self.user, kind=Post.KIND_NOTE_UNLOCK)
        self.assertEqual(post.kind, Post.KIND_NOTE_UNLOCK)


class PostKindFieldTest(TestCase):
    """Post gains a `kind` enum so the per-category lookup (e.g. find the
    user's Note Unlocks Post) is deterministic; user-authored Posts default
    to KIND_USER_POST."""

    def test_post_default_kind_is_user_post(self):
        u = User.objects.create(email="kind@test.io")
        p = Post.objects.create(owner=u)
        self.assertEqual(p.kind, Post.KIND_USER_POST)

    def test_post_kind_choices_include_three_values(self):
        choices = dict(Post._meta.get_field("kind").choices)
        self.assertIn(Post.KIND_NOTE_UNLOCK, choices)
        self.assertIn(Post.KIND_USER_POST, choices)
        self.assertIn(Post.KIND_SHARE_INVITE, choices)
