import tempfile
import unittest
from pathlib import Path
from bot.lib import grep


class TestGrep(unittest.TestCase):
    def setUp(self):
        self.root = Path(tempfile.mkdtemp())
        (self.root / "Modules").mkdir()
        (self.root / "Libs").mkdir()
        (self.root / "CritMatic.lua").write_text(
            "local x = GetSpellInfo(123)\nlocal y = UnitName('player')\n",
            encoding="utf-8",
        )
        (self.root / "Modules" / "CritLog.lua").write_text(
            "GetSpellDescription(7)\n", encoding="utf-8"
        )
        (self.root / "Libs" / "Ace3.lua").write_text(
            "GetSpellInfo(999)\n", encoding="utf-8"
        )

    def test_finds_call_sites_in_main_and_modules(self):
        sites = grep.find_call_sites({"GetSpellInfo", "GetSpellDescription"}, self.root)
        files = {s.path for s in sites}
        self.assertIn("CritMatic.lua", files)
        self.assertIn("Modules/CritLog.lua", files)

    def test_excludes_libs(self):
        sites = grep.find_call_sites({"GetSpellInfo"}, self.root)
        for s in sites:
            self.assertFalse(s.path.startswith("Libs/"))

    def test_word_boundary(self):
        # "UnitNameOf" should NOT match "UnitName".
        (self.root / "X.lua").write_text("UnitNameOf(7)\n", encoding="utf-8")
        sites = grep.find_call_sites({"UnitName"}, self.root)
        self.assertEqual({s.path for s in sites}, {"CritMatic.lua"})

    def test_records_line_and_snippet(self):
        sites = grep.find_call_sites({"GetSpellInfo"}, self.root)
        s = next(s for s in sites if s.path == "CritMatic.lua")
        self.assertEqual(s.line, 1)
        self.assertIn("GetSpellInfo(123)", s.snippet)
        self.assertEqual(s.symbol, "GetSpellInfo")


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