import time
from inire.geometry.primitives import Port
from inire.geometry.collision import CollisionEngine
from inire.router.danger_map import DangerMap
from inire.router.cost import CostEvaluator
from inire.router.astar import AStarRouter
from inire.router.pathfinder import PathFinder

def benchmark_scaling() -> None:
    print("Starting Scalability Benchmark...")

    # 1. Memory Verification (20x20mm)
    # Resolution 1um -> 20000 x 20000 grid
    bounds = (0, 0, 20000, 20000)
    print(f"Initializing DangerMap for {bounds} area...")
    dm = DangerMap(bounds=bounds, resolution=1.0)
    # nbytes for float32: 20000 * 20000 * 4 bytes = 1.6 GB
    mem_gb = dm.grid.nbytes / (1024**3)
    print(f"DangerMap memory usage: {mem_gb:.2f} GB")
    assert mem_gb < 2.0

    # 2. Node Expansion Rate (50 nets)
    engine = CollisionEngine(clearance=2.0)
    # Use a smaller area for routing benchmark to keep it fast
    routing_bounds = (0, 0, 1000, 1000)
    danger_map = DangerMap(bounds=routing_bounds)
    danger_map.precompute([])
    evaluator = CostEvaluator(engine, danger_map)
    router = AStarRouter(evaluator)
    pf = PathFinder(router, evaluator)

    num_nets = 50
    netlist = {}
    for i in range(num_nets):
        # Parallel nets spaced by 10um
        netlist[f"net{i}"] = (Port(0, i * 10, 0), Port(100, i * 10, 0))

    print(f"Routing {num_nets} nets...")
    start_time = time.monotonic()
    results = pf.route_all(netlist, dict.fromkeys(netlist, 2.0))
    end_time = time.monotonic()

    total_time = end_time - start_time
    print(f"Total routing time: {total_time:.2f} s")
    print(f"Time per net: {total_time/num_nets:.4f} s")

    if total_time > 0:
        nodes_per_sec = router.total_nodes_expanded / total_time
        print(f"Node expansion rate: {nodes_per_sec:.2f} nodes/s")

    # Success rate
    successes = sum(1 for r in results.values() if r.is_valid)
    print(f"Success rate: {successes/num_nets * 100:.1f}%")

if __name__ == "__main__":
    benchmark_scaling()
