"""
Comprehensive Unit Test Suite for FreeExile Milestone 4 Telegraph Decal Renderer:
- Module existence and strict line caps (< 250 lines, <= 350 soft cap)
- Data structures and 4 telegraph shapes (cone, circle, ring, line)
- PoE2 windup delay ranges (0.6s–1.2s)
- Poise break / stagger immediate attack cancellation (staggerTimer > 0)
- Canvas 2D isometric ground rendering & translucent warning decals
- Integration verification for index.html, entity_renderer.js, monster_system.js
"""

import unittest
import re
from pathlib import Path

PROJECT_ROOT = Path(__file__).resolve().parent.parent.parent
WEBAPP_DIR = PROJECT_ROOT / "client" / "webapp"
TELEGRAPH_JS = WEBAPP_DIR / "js" / "engine" / "telegraph_renderer.js"
INDEX_HTML = WEBAPP_DIR / "index.html"
ENTITY_RENDERER_JS = WEBAPP_DIR / "js" / "engine" / "entity_renderer.js"
MONSTER_SYSTEM_JS = WEBAPP_DIR / "js" / "engine" / "monster_system.js"


class TestTelegraphRenderer(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        cls.target_path = TELEGRAPH_JS
        cls.code = cls.target_path.read_text(encoding="utf-8")
        cls.lines = cls.code.splitlines()

    def test_telegraph_module_exists(self):
        """Verifies telegraph_renderer.js target exists."""
        self.assertTrue(self.target_path.exists(), f"Target {self.target_path} not found")

    def test_strict_line_caps(self):
        """Verifies telegraph_renderer.js is strictly < 250 lines and <= 350 soft cap."""
        line_count = len(self.lines)
        self.assertLess(line_count, 250, f"telegraph_renderer.js exceeds 250 lines: {line_count}")
        self.assertLessEqual(line_count, 350, f"telegraph_renderer.js exceeds soft cap: {line_count}")

    def test_api_surface_and_exports(self):
        """Verifies core API methods exist on TelegraphRenderer."""
        required_methods = [
            "addTelegraph", "cancelTelegraph", "cancelTelegraphById",
            "clearAllTelegraphs", "getActiveTelegraphs", "updateTelegraphs",
            "renderTelegraphs", "updateAndRender", "startMonsterAttack"
        ]
        for m in required_methods:
            self.assertIn(m, self.code, f"Missing method {m} in telegraph_renderer.js")
        self.assertIn("window.TelegraphRenderer = TelegraphRenderer", self.code)
        self.assertIn("export { TelegraphRenderer", self.code)

    def test_all_four_shapes_supported(self):
        """Verifies cone, circle, ring, and line telegraph shapes are supported."""
        for shape in ["cone", "circle", "ring", "line"]:
            self.assertIn(f"'{shape}'", self.code, f"Telegraph shape '{shape}' not supported")

    def test_poe2_windup_delays(self):
        """Verifies 0.6s–1.2s windup delay ranges matching PoE2 combat specifications."""
        self.assertIn("duration:", self.code)
        self.assertIn("progress:", self.code)
        self.assertIn("1.0", self.code)
        self.assertIn("0.8", self.code)

    def test_poise_break_stagger_cancellation(self):
        """Verifies staggerTimer > 0 immediately cancels active attack telegraphs."""
        self.assertIn("staggerTimer", self.code)
        self.assertIn("staggerTimer > 0", self.code)
        self.assertIn("activeTelegraphs.splice", self.code)

    def test_canvas_2d_isometric_rendering(self):
        """Verifies Canvas 2D isometric ground rendering with worldToIso and translucent crimson palette."""
        self.assertIn("worldToIso", self.code)
        self.assertIn("rgba(239, 68, 68", self.code)
        self.assertIn("pulse", self.code)

    def test_html_script_integration_and_caps(self):
        """Verifies index.html line cap (<= 200 soft cap, <= 400 hard cap)."""
        html_lines = INDEX_HTML.read_text(encoding="utf-8").splitlines()
        self.assertLessEqual(len(html_lines), 200, f"index.html exceeds soft cap: {len(html_lines)}")
        self.assertLessEqual(len(html_lines), 400, f"index.html exceeds hard cap: {len(html_lines)}")

    def test_entity_renderer_line_cap(self):
        """Verifies entity_renderer.js line cap (<= 500 hard cap)."""
        lines = ENTITY_RENDERER_JS.read_text(encoding="utf-8").splitlines()
        self.assertLessEqual(len(lines), 500, f"entity_renderer.js exceeds hard cap: {len(lines)}")

    def test_monster_system_line_cap(self):
        """Verifies monster_system.js line cap (<= 500 hard cap)."""
        lines = MONSTER_SYSTEM_JS.read_text(encoding="utf-8").splitlines()
        self.assertLessEqual(len(lines), 500, f"monster_system.js exceeds hard cap: {len(lines)}")


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