import unittest
from booking import simulate


class BookingTests(unittest.TestCase):
    def test_single_desk_fixture(self):
        self.assertEqual(simulate(range(6)), {"arrivals": 6, "served": 3,
                         "abandoned": 3, "mean_wait": 4.0, "last_finish": 15.0})

    def test_second_desk_fixture(self):
        self.assertEqual(simulate(range(6), staff=2), {"arrivals": 6, "served": 6,
                         "abandoned": 0, "mean_wait": 3.0, "last_finish": 16.0})

    def test_empty(self):
        self.assertIsNone(simulate([])["mean_wait"])
        self.assertEqual(simulate([])["served"], 0)

    def test_patience_boundary_is_inclusive(self):
        self.assertEqual(simulate([0, 0], service_minutes=8, patience=8)["served"], 2)
        self.assertEqual(simulate([0, 0], service_minutes=9, patience=8)["served"], 1)

    def test_abandonment_does_not_reserve_staff(self):
        self.assertEqual(simulate([0, 0, 5], patience=0)["served"], 2)

    def test_accounting_and_demand(self):
        for size in range(31):
            result = simulate(range(size))
            self.assertEqual(result["served"] + result["abandoned"], size)
        self.assertEqual(simulate(range(12))["served"], 4)

    def test_rejects_invalid_inputs(self):
        for kwargs in [{"staff": 0}, {"staff": True}, {"staff": 1.5},
                       {"service_minutes": 0}, {"patience": -1},
                       {"patience": float("nan")}, {"service_minutes": float("inf")}]:
            with self.subTest(kwargs=kwargs), self.assertRaises(ValueError):
                simulate([0], **kwargs)
        for arrivals in [[1, 0], [-1], [True], [float("nan")]]:
            with self.subTest(arrivals=arrivals), self.assertRaises(ValueError):
                simulate(arrivals)


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