import unittest

from score_ablation import uncertainty
from write_report import copy_contrast


class FamilyUncertaintyTests(unittest.TestCase):
    def test_related_donors_remain_one_sign_flip_unit(self):
        pairs = [{"donor": "a", "difference": 1}, {"donor": "b", "difference": 1}]
        result = uncertainty(pairs, {"a": ("a", "b"), "b": ("a", "b")})
        self.assertEqual(result["family_clusters"], 1)
        self.assertEqual(result["sign_flip_p"], 1)
        self.assertEqual(result["difference_pp"], 100)

    def test_opposing_effects_do_not_create_net_gain(self):
        pairs = [{"donor": "a", "difference": 1}, {"donor": "b", "difference": -1}]
        result = uncertainty(pairs, {"a": ("a",), "b": ("b",)})
        self.assertEqual(result["difference_pp"], 0)
        self.assertEqual(result["sign_flip_p"], 1)

    def test_missing_results_are_not_zero_effect(self):
        result = uncertainty([], {})
        self.assertIsNone(result["difference_pp"])
        self.assertIsNone(result["sign_flip_p"])

    def test_missing_relationship_metadata_uses_explicit_singleton(self):
        result = uncertainty([{"donor": "new", "difference": 1},
                              {"donor": "new", "difference": 0}], {})
        self.assertEqual(result["family_clusters"], 1)
        self.assertEqual(result["singleton_fallback_donors"], ["new"])
        self.assertEqual(result["difference_pp"], 50)
        self.assertEqual(result["sign_flip_p"], 1)

    def test_copy_recovery_uses_copy_denominator_and_shared_family(self):
        def row(donor, arm, n, recovered):
            return {"donor": donor, "gene": "A", "arm": arm,
                    "unmatched": {"eligible_copies": n, "exact_copies_recovered": recovered}}
        rows = [row("a", "x", 2, 2), row("a", "y", 2, 0),
                row("b", "x", 1, 0), row("b", "y", 1, 1),
                row("missing", "x", 2, 2)]
        result = copy_contrast(rows, "x", "y", {"a": ("a", "b"), "b": ("a", "b")})
        self.assertEqual(result["eligible_copies"], 3)
        self.assertEqual((result["recovered_a"], result["recovered_b"]), (2, 1))
        self.assertAlmostEqual(result["difference_pp"], 100 / 3)
        self.assertEqual(result["family_clusters"], 1)
        self.assertEqual(result["sign_flip_p"], 1)


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