from django.test import TestCase
from django.utils import timezone

from apps.lyric.admin import TokenAdminForm
from apps.lyric.models import Token, User


class UserAdminTest(TestCase):
    def setUp(self):
        self.superuser = User.objects.create_superuser(
            email="admin@example.com", password="secret"
        )
        self.client.force_login(self.superuser)

    def test_user_changelist_loads(self):
        response = self.client.get("/admin/lyric/user/")
        self.assertEqual(response.status_code, 200)

    def test_user_changelist_displays_email(self):
        response = self.client.get("/admin/lyric/user/")
        self.assertContains(response, "admin@example.com")

    def test_user_changelist_search_by_email(self):
        User.objects.create_superuser(email="other@example.com", password="x")
        response = self.client.get("/admin/lyric/user/?q=admin")
        self.assertContains(response, "admin@example.com")
        self.assertNotContains(response, "other@example.com")


class TokenAdminFormTest(TestCase):
    def setUp(self):
        self.user = User.objects.create(email="gamer@example.com")

    def _form(self, token_type, expires_at=None):
        return TokenAdminForm(data={
            "user": self.user.pk,
            "token_type": token_type,
            "expires_at": expires_at or "",
        })

    def test_free_token_without_expires_at_is_invalid(self):
        form = self._form(Token.FREE)
        self.assertFalse(form.is_valid())
        self.assertIn("Free Tokens must have an expiration date", str(form.errors))

    def test_free_token_with_expires_at_is_valid(self):
        form = self._form(Token.FREE, expires_at=timezone.now())
        self.assertTrue(form.is_valid())

    def test_other_token_types_do_not_require_expires_at(self):
        for token_type in (Token.COIN, Token.TITHE):
            with self.subTest(token_type=token_type):
                form = self._form(token_type)
                self.assertTrue(form.is_valid())

    def test_pass_token_for_non_staff_user_is_invalid(self):
        # PASS is the admin-only trinket — the admin form must surface this
        # as a validation error instead of silently writing a row that the
        # game-side surfaces (game kit, gate picker) will then ignore.
        form = self._form(Token.PASS)
        self.assertFalse(form.is_valid())

    def test_pass_token_for_staff_user_is_valid(self):
        staff = User.objects.create(email="staffadmin@example.com", is_staff=True)
        Token.objects.filter(user=staff, token_type=Token.PASS).delete()
        form = TokenAdminForm(data={
            "user": staff.pk,
            "token_type": Token.PASS,
            "expires_at": "",
        })
        self.assertTrue(form.is_valid())
