"""ITs for `apps.billboard.tax.log_tax_debit` — the @taxman-authored
"Debits & credits" ledger (user-spec 2026-05-26).

Mirrors the shape of `apps.drama.tests.integrated.test_note_brief` for
`Note.grant_if_new` — each spend appends a Line + spawns a Brief on the
user's single TAX_LEDGER Post."""

from django.test import TestCase

from apps.billboard.models import Brief, Line, Post, TAX_LEDGER_POST_TITLE
from apps.billboard.tax import (
    TAX_DEBIT_TEMPLATES,
    log_tax_debit,
)
from apps.lyric.models import User, get_or_create_taxman


class LogTaxDebitTest(TestCase):
    def setUp(self):
        self.user = User.objects.create(email="tax@test.io")

    def test_free_draw_locked_creates_post_line_brief(self):
        post, line, brief = log_tax_debit(self.user, "free_draw_locked")
        # Post created with the canonical title + correct kind
        self.assertEqual(post.owner, self.user)
        self.assertEqual(post.kind, Post.KIND_TAX_LEDGER)
        self.assertEqual(post.title, TAX_LEDGER_POST_TITLE)
        # Line authored by @taxman + admin_solicited
        self.assertEqual(line.post, post)
        self.assertEqual(line.author, get_or_create_taxman())
        self.assertTrue(line.admin_solicited)
        # Brief points at the Post + Line w. correct kind
        self.assertEqual(brief.owner, self.user)
        self.assertEqual(brief.post, post)
        self.assertEqual(brief.line, line)
        self.assertEqual(brief.kind, Brief.KIND_TAX_LEDGER)
        self.assertEqual(brief.title, TAX_LEDGER_POST_TITLE)

    def test_paid_draw_locked_uses_paid_template_text(self):
        _, line, _ = log_tax_debit(self.user, "paid_draw_locked")
        self.assertIn("PAID DRAW", line.text)
        # `GATE VIEW` is wrapped in a `.btn-pri-name` span for inline styling
        # parity w. the actual button label (user-spec 2026-05-26), so the
        # raw text has HTML between "depositing a Token in " + "GATE VIEW".
        self.assertIn("depositing a Token in", line.text)
        self.assertIn("GATE VIEW", line.text)

    def test_free_draw_locked_uses_free_template_text(self):
        _, line, _ = log_tax_debit(self.user, "free_draw_locked")
        self.assertIn("FREE DRAW", line.text)
        self.assertIn("24h from the production of this log", line.text)

    def test_two_spends_share_one_post_with_two_lines(self):
        """Like Note unlocks: one Post per user, growing thread of Lines."""
        log_tax_debit(self.user, "free_draw_locked")
        log_tax_debit(self.user, "paid_draw_locked")
        posts = Post.objects.filter(owner=self.user, kind=Post.KIND_TAX_LEDGER)
        self.assertEqual(posts.count(), 1)
        self.assertEqual(posts.first().lines.count(), 2)

    def test_two_free_draws_produce_distinct_lines(self):
        """Each spend produces a UNIQUE Line — text is timestamp-prefixed so
        a second identical-slug spend doesn't collide with `unique_together
        = (post, text)`."""
        log_tax_debit(self.user, "free_draw_locked")
        log_tax_debit(self.user, "free_draw_locked")
        post = Post.objects.get(owner=self.user, kind=Post.KIND_TAX_LEDGER)
        line_texts = list(post.lines.values_list("text", flat=True))
        self.assertEqual(len(line_texts), 2)
        self.assertNotEqual(line_texts[0], line_texts[1])

    def test_unknown_slug_raises(self):
        with self.assertRaises(KeyError):
            log_tax_debit(self.user, "no_such_slug")

    def test_template_keys_cover_both_known_slugs(self):
        self.assertIn("free_draw_locked", TAX_DEBIT_TEMPLATES)
        self.assertIn("paid_draw_locked", TAX_DEBIT_TEMPLATES)


class UnsolicitedLineGuardTest(TestCase):
    """post_save guard nukes any Line saved on a TAX_LEDGER Post w.o.
    admin_solicited=True — mirrors the NOTE_UNLOCK defense-in-depth."""

    def setUp(self):
        self.user = User.objects.create(email="guard@test.io")
        self.taxman = get_or_create_taxman()
        self.post = Post.objects.create(
            owner=self.user,
            kind=Post.KIND_TAX_LEDGER,
            title=TAX_LEDGER_POST_TITLE,
        )

    def test_unsolicited_line_on_tax_ledger_gets_deleted(self):
        Line.objects.create(
            post=self.post, text="impostor", author=self.taxman,
            admin_solicited=False,
        )
        self.assertEqual(self.post.lines.count(), 0)

    def test_solicited_line_on_tax_ledger_survives(self):
        Line.objects.create(
            post=self.post, text="legit", author=self.taxman,
            admin_solicited=True,
        )
        self.assertEqual(self.post.lines.count(), 1)


class TaxmanReservedUsernameTest(TestCase):
    """`taxman` joins `adman` as a reserved system-author handle."""

    def test_taxman_is_reserved(self):
        from apps.lyric.models import is_reserved_username
        self.assertTrue(is_reserved_username("taxman"))
        self.assertTrue(is_reserved_username("TAXMAN"))  # case-insensitive

    def test_get_or_create_taxman_is_idempotent(self):
        a = get_or_create_taxman()
        b = get_or_create_taxman()
        self.assertEqual(a.pk, b.pk)
        self.assertEqual(a.email, "taxman@earthmanrpg.local")
