"""Synthetic evaluation accounting demo. No models, network or persistent writes.
Run: python3 agent-eval-slice-gate.py
"""
import unittest

EXPECTED = {**{f"routine-{i}": "routine" for i in range(900)},
            **{f"boundary-{i}": "boundary" for i in range(100)}}


def fixture(routine_passes, boundary_passes):
    return {case: i < passes
            for name, count, passes in (("routine", 900, routine_passes),
                                        ("boundary", 100, boundary_passes))
            for i in range(count)
            for case in [f"{name}-{i}"]}


def evaluate(results):
    if set(results) != set(EXPECTED):
        raise ValueError("Case inventory mismatch")
    if any(type(value) is not bool for value in results.values()):
        raise ValueError("Missing or invalid verdict")
    slices = {}
    for name in sorted(set(EXPECTED.values())):
        values = [results[case] for case, group in EXPECTED.items() if group == name]
        if not values:
            raise ValueError("Empty required slice")
        slices[name] = (sum(values), len(values))
    return slices, sum(results.values()) / len(EXPECTED)


def release_allowed(results):
    try:
        slices, overall = evaluate(results)
    except ValueError:
        return False
    # Author-defined demonstration policy, not a vendor recommendation.
    boundary_passed, boundary_total = slices["boundary"]
    return overall >= 0.90 and boundary_passed == boundary_total


class GateTests(unittest.TestCase):
    def test_baseline_allowed(self):
        self.assertTrue(release_allowed(fixture(810, 100)))

    def test_better_average_still_blocked(self):
        baseline = fixture(810, 100)
        candidate = fixture(855, 80)
        self.assertGreater(evaluate(candidate)[1], evaluate(baseline)[1])
        self.assertFalse(release_allowed(candidate))

    def test_one_boundary_failure_blocks(self):
        self.assertFalse(release_allowed(fixture(900, 99)))

    def test_routine_floor_blocks(self):
        self.assertFalse(release_allowed(fixture(799, 100)))

    def test_missing_case_blocks(self):
        result = fixture(900, 100)
        del result["boundary-0"]
        self.assertFalse(release_allowed(result))

    def test_unknown_verdict_blocks(self):
        result = fixture(900, 100)
        result["boundary-0"] = None
        self.assertFalse(release_allowed(result))

    def test_extra_case_blocks(self):
        result = fixture(900, 100)
        result["unexpected"] = True
        self.assertFalse(release_allowed(result))

    def test_integer_is_not_boolean_verdict(self):
        result = fixture(900, 100)
        result["boundary-0"] = 1
        self.assertFalse(release_allowed(result))

    def test_threshold_inclusive(self):
        self.assertTrue(release_allowed(fixture(800, 100)))


if __name__ == "__main__":
    for label, result in (("baseline", fixture(810, 100)),
                          ("candidate", fixture(855, 80))):
        slices, overall = evaluate(result)
        print(f"{label}: overall={overall:.1%}, slices={slices}, "
              f"release={'ALLOW' if release_allowed(result) else 'BLOCK'}", flush=True)
    unittest.main(verbosity=2)
