"""Synthetic booking desk model. No patient data or clinical predictions."""
import heapq
import math
from statistics import mean


def finite_number(value, name, minimum=0):
    if isinstance(value, bool) or not isinstance(value, (int, float)):
        raise ValueError(f"{name} must be a finite number")
    if not math.isfinite(value) or value < minimum:
        raise ValueError(f"{name} must be finite and >= {minimum}")


def simulate(arrivals, service_minutes=5, staff=1, patience=8):
    finite_number(service_minutes, "service_minutes")
    finite_number(patience, "patience")
    if service_minutes == 0 or type(staff) is not int or staff < 1:
        raise ValueError("service time and staff must be positive")
    arrivals = list(arrivals)
    for arrival in arrivals:
        finite_number(arrival, "arrival")
    if arrivals != sorted(arrivals):
        raise ValueError("arrivals must be chronological")
    free_at = [0.0] * staff
    waits = []
    abandoned = 0
    for arrival in arrivals:
        start = max(arrival, free_at[0])
        wait = start - arrival
        if wait > patience:
            abandoned += 1
            continue
        heapq.heapreplace(free_at, start + service_minutes)
        waits.append(wait)
    return {"arrivals": len(arrivals), "served": len(waits),
            "abandoned": abandoned, "mean_wait": mean(waits) if waits else None,
            "last_finish": max(free_at)}


if __name__ == "__main__":
    for name, arrivals, staff in [("one desk", range(6), 1),
                                  ("two desks", range(6), 2),
                                  ("more demand", range(12), 1)]:
        print(name, simulate(arrivals, staff=staff))
