"""Tests for the pure helpers in new_demo.py:  python3 -m unittest scripts/test_new_demo.py"""
import pathlib
import sys
import unittest

sys.path.insert(0, str(pathlib.Path(__file__).resolve().parent))
import new_demo  # noqa: E402

NAV = """CATEGORIES = [
    ('graphics', '🎨 图形渲染', '分形', [
        ('mandelbrot', '曼德博集合'), ('terrain', '噪声地形'),
    ]),
    ('games', '🎮 游戏与 AI', '可以玩', [
        ('gomoku', '五子棋 AI'),
    ]),
]
"""

HOME = """        <section class="cat" id="cat-graphics" aria-labelledby="cat-graphics-title">
            <h2 class="cat-title" id="cat-graphics-title">🎨 图形渲染<small>分形</small></h2>
            <div class="card-grid">
            <a href="mandelbrot/" class="card">
            </a>
            </div>
        </section>

        <p class="help">x</p>
"""


class AddToCategories(unittest.TestCase):
    def test_appends_to_the_end_of_the_right_category(self):
        out = new_demo.add_to_categories(NAV, 'graphics', 'wfc', '波函数坍缩')
        graphics = out[:out.index("('games'")]
        self.assertTrue(graphics.rstrip().endswith("('wfc', '波函数坍缩'),\n    ]),"))
        self.assertNotIn('wfc', out[out.index("('games'"):])

    def test_rejects_unknown_category_and_duplicates(self):
        with self.assertRaises(ValueError):
            new_demo.add_to_categories(NAV, 'nope', 'x', 'x')
        with self.assertRaises(ValueError):
            new_demo.add_to_categories(NAV, 'graphics', 'terrain', '噪声地形')

    def test_result_is_still_valid_python(self):
        ns = {}
        exec(new_demo.add_to_categories(NAV, 'games', 'chip8', 'CHIP-8'), ns)
        self.assertEqual(ns['CATEGORIES'][1][3][-1], ('chip8', 'CHIP-8'))


class AddCard(unittest.TestCase):
    def test_adds_card_inside_existing_section(self):
        out = new_demo.add_card(HOME, 'graphics', '', '', 'wfc', '🧩', 'WFC', '说明', '标签')
        section = out[:out.index('</section>')]
        self.assertIn('href="wfc/"', section)
        self.assertLess(section.index('href="mandelbrot/"'), section.index('href="wfc/"'))

    def test_creates_missing_section_after_the_last_one(self):
        out = new_demo.add_card(HOME, 'games', '🎮 游戏与 AI', '可以玩', 'chip8', '🕹️', 'CHIP-8', 'd', 't')
        self.assertIn('id="cat-games"', out)
        self.assertLess(out.index('id="cat-graphics"'), out.index('id="cat-games"'))
        self.assertLess(out.index('id="cat-games"'), out.index('<p class="help">'))

    def test_escapes_text_and_rejects_duplicates(self):
        out = new_demo.add_card(HOME, 'graphics', '', '', 'x', 'i', 'a<b', 'c&d', 't')
        self.assertIn('a&lt;b', out)
        self.assertIn('c&amp;d', out)
        with self.assertRaises(ValueError):
            new_demo.add_card(HOME, 'graphics', '', '', 'mandelbrot', 'i', 't', 'd', 'g')


class PageHtml(unittest.TestCase):
    def test_links_own_stylesheet_only_when_asked(self):
        self.assertIn('href="style.css"', new_demo.page_html('T', 'H', 'S', '', 'h', True))
        self.assertNotIn('href="style.css"', new_demo.page_html('T', 'H', 'S', '', 'h', False))

    def test_has_the_placeholders_the_generators_fill(self):
        page = new_demo.page_html('T', 'H', 'S', '', 'h', False)
        self.assertEqual(page.count('<nav class="top-nav"></nav>'), 1)
        self.assertEqual(page.count('<details class="explain"></details>'), 1)


if __name__ == '__main__':
    unittest.main()
