import unittest
from bot.lib import diff


class TestDiff(unittest.TestCase):
    def test_removed_set(self):
        d = diff.compute_diff({"A", "B", "C"}, {"A", "C"})
        self.assertEqual(d.removed, {"B"})
        self.assertEqual(d.added, set())

    def test_added_set(self):
        d = diff.compute_diff({"A"}, {"A", "B"})
        self.assertEqual(d.added, {"B"})
        self.assertEqual(d.removed, set())

    def test_renamed_heuristic_within_distance(self):
        d = diff.compute_diff({"GetSpellInfo"}, {"GetSpellInfoX"})
        self.assertIn(("GetSpellInfo", "GetSpellInfoX"), d.renamed)

    def test_renamed_heuristic_too_far(self):
        d = diff.compute_diff({"GetSpellInfo"}, {"UnitName"})
        self.assertEqual(d.renamed, [])

    def test_renamed_max_distance_default_three(self):
        # Distance of exactly 3 should match.
        d = diff.compute_diff({"abcdef"}, {"abcXYZ"})
        self.assertIn(("abcdef", "abcXYZ"), d.renamed)
        # Distance of 4 should not.
        d2 = diff.compute_diff({"abcdef"}, {"WXYZef"})
        self.assertEqual(d2.renamed, [])

    def test_renamed_pairing_is_bijective(self):
        # An added item must not appear in more than one rename pair.
        d = diff.compute_diff({"GetSpellInfo", "GetSpellDesc"}, {"GetSpellInfoX"})
        added_in_pairs = [new for _, new in d.renamed]
        self.assertEqual(len(added_in_pairs), len(set(added_in_pairs)))
        self.assertLessEqual(len(d.renamed), 1)


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