from django.test import TestCase
from django.db import IntegrityError

from apps.tooltips.models import TooltipContent


class TooltipContentModelTest(TestCase):

    # ── Required fields ───────────────────────────────────────────────────────

    def test_can_create_with_slug_and_title_only(self):
        tt = TooltipContent.objects.create(slug='sun', title='Sun')
        self.assertEqual(TooltipContent.objects.count(), 1)
        self.assertEqual(tt.slug, 'sun')
        self.assertEqual(tt.title, 'Sun')

    def test_slug_is_unique(self):
        TooltipContent.objects.create(slug='sun', title='Sun')
        with self.assertRaises(IntegrityError):
            TooltipContent.objects.create(slug='sun', title='Another Sun')

    def test_str_returns_title(self):
        tt = TooltipContent(slug='moon', title='Moon')
        self.assertEqual(str(tt), 'Moon')

    # ── Optional text fields ──────────────────────────────────────────────────

    def test_optional_text_fields_default_blank(self):
        tt = TooltipContent.objects.create(slug='mars', title='Mars')
        for field in ('type_label', 'symbol', 'degree_str',
                      'description', 'shoptalk', 'expiry', 'effect'):
            self.assertEqual(getattr(tt, field), '', msg=f'{field} should default blank')

    def test_can_set_all_text_fields(self):
        tt = TooltipContent.objects.create(
            slug='jupiter',
            title='Jupiter',
            type_label='Planet',
            symbol='♃',
            degree_str='14° 22′ Scorpio',
            description='Planet of expansion and fortune.',
            shoptalk='Ruler of Sagittarius.',
            expiry='',
            effect='Amplifies whichever house it occupies.',
        )
        self.assertEqual(tt.type_label, 'Planet')
        self.assertEqual(tt.symbol, '♃')
        self.assertEqual(tt.degree_str, '14° 22′ Scorpio')

    # ── extras JSONField ──────────────────────────────────────────────────────

    def test_extras_defaults_to_empty_dict(self):
        tt = TooltipContent.objects.create(slug='venus', title='Venus')
        self.assertEqual(tt.extras, {})

    def test_extras_stores_dignities(self):
        tt = TooltipContent.objects.create(
            slug='saturn',
            title='Saturn',
            extras={
                'dignities': {
                    'Domicile': 'Capricorn / Aquarius',
                    'Exalted': 'Libra',
                    'Exile': 'Cancer / Leo',
                    'Fallen': 'Aries',
                },
            },
        )
        tt.refresh_from_db()
        self.assertEqual(tt.extras['dignities']['Exalted'], 'Libra')

    def test_extras_stores_aspects(self):
        tt = TooltipContent.objects.create(
            slug='mercury',
            title='Mercury',
            extras={
                'aspects': [
                    {'symbol': '△', 'type': 'Trine', 'body': 'Venus', 'orb': '2° 14′'},
                    {'symbol': '□', 'type': 'Square', 'body': 'Mars', 'orb': '0° 42′'},
                ],
            },
        )
        tt.refresh_from_db()
        self.assertEqual(len(tt.extras['aspects']), 2)
        self.assertEqual(tt.extras['aspects'][0]['type'], 'Trine')

    def test_extras_stores_keywords(self):
        tt = TooltipContent.objects.create(
            slug='the-schizo',
            title='The Schizo, Leavened',
            extras={
                'keywords_up': ['willpower', 'skill', 'resourcefulness'],
                'keywords_rev': ['hubris', 'overreach'],
            },
        )
        tt.refresh_from_db()
        self.assertIn('willpower', tt.extras['keywords_up'])

    def test_extras_stores_cautions(self):
        tt = TooltipContent.objects.create(
            slug='the-schizo-cautions',
            title='The Schizo, Leavened',
            extras={
                'cautions': [
                    {
                        'title': 'Caution!',
                        'type_label': 'Rival Interaction',
                        'shoptalk': '[Shoptalk forthcoming]',
                        'effect': 'This card will reverse into I. The Pervert...',
                    },
                ],
            },
        )
        tt.refresh_from_db()
        self.assertEqual(tt.extras['cautions'][0]['type_label'], 'Rival Interaction')

    def test_extras_stores_nav(self):
        """PRV/NXT nav dict for paired or sequenced tooltips."""
        tt = TooltipContent.objects.create(
            slug='house-01',
            title='House of Self',
            extras={
                'nav': {'prv': 'house-12', 'nxt': 'house-02'},
            },
        )
        tt.refresh_from_db()
        self.assertEqual(tt.extras['nav']['nxt'], 'house-02')
