"""
Unit test recommendations for FreeExile Modern ARPG Skill Bar & Cooldown Sweeps.
File: tests/unit/test_skill_bar_and_cooldown_sweeps.py
Target verification:
1. SkillBarController interface contract: registerSlot, triggerCooldown, onReady.
2. 360° clockwise radial cooldown sweep overlay with conic-gradient.
3. 0.25s luminous ready flash pulse keyframes and class toggle.
4. Slot keybinding badges, charges badge, and tactile press states.
5. Canonical martial skills atlas sprite rendering from martial_skills_atlas.png.
6. Backward compatibility with existing combat action buttons (#skill-fire, #skill-thunder, #skill-frost, #skill-dodge).
"""

import unittest
from pathlib import Path

PROJECT_ROOT = Path(__file__).resolve().parent.parent.parent.parent
EXPLORER_DIR = Path(__file__).resolve().parent
PROPOSED_JS = EXPLORER_DIR / "proposed_skill_bar_controller.js"
PROPOSED_CSS = EXPLORER_DIR / "proposed_hud_skills.css"
PROPOSED_HTML = EXPLORER_DIR / "proposed_index_patch.html"


class TestSkillBarAndCooldownSweeps(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        cls.assertTrue(PROPOSED_JS.exists(), "proposed_skill_bar_controller.js must exist")
        cls.assertTrue(PROPOSED_CSS.exists(), "proposed_hud_skills.css must exist")
        cls.assertTrue(PROPOSED_HTML.exists(), "proposed_index_patch.html must exist")

        with open(PROPOSED_JS, "r", encoding="utf-8") as f:
            cls.js_content = f.read()
        with open(PROPOSED_CSS, "r", encoding="utf-8") as f:
            cls.css_content = f.read()
        with open(PROPOSED_HTML, "r", encoding="utf-8") as f:
            cls.html_content = f.read()

    def test_controller_interface_contract(self):
        """SkillBarController must implement registerSlot, triggerCooldown, and onReady."""
        self.assertIn("class SkillBarController", self.js_content)
        self.assertIn("registerSlot(", self.js_content)
        self.assertIn("triggerCooldown(", self.js_content)
        self.assertIn("onReady(", self.js_content)
        self.assertIn("activateSlot(", self.js_content)
        self.assertIn("isSlotOnCooldown(", self.js_content)
        self.assertIn("getRemainingCooldown(", self.js_content)

    def test_canonical_atlas_map_metadata(self):
        """SKILL_ATLAS_MAP must map all 10 canonical active skills with UV grid indices."""
        expected_skills = [
            "cuu_tieu_loi_kiem", "thanh_phong_van_kiem_vu",
            "u_minh_huyet_doc_cham", "thien_ma_boc_doc_kinh",
            "bang_phach_han_quang_tran", "bang_tien_xuyen_tam",
            "liet_hoa_toan_phong_tram", "liet_diem_boc_khi_tram",
            "kim_cang_truy_dia_chan", "kim_cang_bat_hoai_the"
        ]
        for skill in expected_skills:
            self.assertIn(skill, self.js_content, f"Skill '{skill}' must exist in SKILL_ATLAS_MAP")

    def test_conic_gradient_radial_sweep_in_css(self):
        """hud_skills.css must specify conic-gradient with --cooldown-sweep variable."""
        self.assertIn(".cooldown-overlay", self.css_content)
        self.assertIn("conic-gradient", self.css_content)
        self.assertIn("--cooldown-sweep", self.css_content)
        self.assertIn(".cooldown-counter", self.css_content)

    def test_luminous_ready_flash_pulse(self):
        """hud_skills.css must implement 0.25s ready flash pulse animation."""
        self.assertIn("@keyframes skill-ready-pulse", self.css_content)
        self.assertIn(".is-ready-pulse", self.css_content)
        self.assertIn("0.25s", self.css_content)
        self.assertIn("rgba(251, 191, 36", self.css_content)  # Golden bloom amber

    def test_tactile_press_and_blocked_states(self):
        """CSS must define tactile pressed state and blocked error shake."""
        self.assertIn(".is-pressed", self.css_content)
        self.assertIn(".is-cooldown-blocked", self.css_content)
        self.assertIn("@keyframes skill-blocked-shake", self.css_content)

    def test_seven_action_slots_present_in_html(self):
        """Proposed HTML patch must define all 7 required ARPG slots."""
        slots = [
            "skill-potion",   # Flask (4)
            "skill-fire",     # Skill 1 (Q)
            "skill-slot-w",   # Skill 2 (W)
            "skill-thunder",  # Skill 3 (E)
            "skill-frost",    # Skill 4 (R)
            "skill-primary",  # Primary Attack (LMB)
            "skill-dodge"     # Dodge Roll (Space)
        ]
        for slot in slots:
            self.assertIn(f'id="{slot}"', self.html_content, f"Slot '{slot}' must exist in HTML patch")

    def test_backward_compatibility_ids(self):
        """Must preserve existing combat button IDs required by mobile webapp tests."""
        compat_ids = ["skill-fire", "skill-thunder", "skill-frost", "skill-dodge"]
        for cid in compat_ids:
            self.assertIn(f'id="{cid}"', self.html_content)

    def test_hygiene_line_limits(self):
        """JS and CSS files must remain strictly within the 350-line soft cap."""
        js_lines = len(self.js_content.splitlines())
        css_lines = len(self.css_content.splitlines())
        self.assertLessEqual(js_lines, 350, f"JS file exceeds soft cap: {js_lines} > 350")
        self.assertLessEqual(css_lines, 350, f"CSS file exceeds soft cap: {css_lines} > 350")


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