"""
Exercise 1: a tiny FastAPI-style router (medium)

FastAPI turns type-hinted functions into endpoints. Build a minimal version with only the standard library:

  - App.get(path) is a decorator registering a handler for GET requests on a path pattern such as
    "/items/{item_id}" or "/users/{user_id}/orders".
  - App.handle(path) finds the matching route, extracts path parameters, CONVERTS them using the handler's
    type hints (int, float, str), calls the handler with keyword arguments and returns (200, result).
  - No matching route → (404, {"detail": "Not Found"}).
  - A parameter that can't be converted (e.g. "abc" for int) → (422, {"detail": "<name>: expected int"}).
  - If the handler raises HTTPError(status, detail) → (status, {"detail": detail}).
"""

import re
import typing


class HTTPError(Exception):
    def __init__(self, status, detail):
        self.status = status
        self.detail = detail


class App:
    def __init__(self):
        self.routes = []

    def get(self, path):
        def decorator(fn):
            return fn  # TODO: register (pattern, fn)
        return decorator

    def handle(self, path):
        return 404, {"detail": "Not Found"}  # TODO


# --- self-check: do not modify below this line ---
app = App()
ITEMS = {1: "bowl", 2: "leash"}


@app.get("/items/{item_id}")
def get_item(item_id: int):
    if item_id not in ITEMS:
        raise HTTPError(404, "Item not found")
    return {"id": item_id, "name": ITEMS[item_id]}


@app.get("/users/{user_id}/orders/{order_id}")
def get_order(user_id: str, order_id: int):
    return {"user": user_id, "order": order_id}


@app.get("/health")
def health():
    return {"ok": True}

checks = []
checks.append(("typed path param", app.handle("/items/2"), (200, {"id": 2, "name": "leash"})))
checks.append(("handler HTTP error", app.handle("/items/9"), (404, {"detail": "Item not found"})))
checks.append(("validation error", app.handle("/items/abc"), (422, {"detail": "item_id: expected int"})))
checks.append(("multiple params", app.handle("/users/ana/orders/7"), (200, {"user": "ana", "order": 7})))
checks.append(("no params", app.handle("/health"), (200, {"ok": True})))
checks.append(("unknown route", app.handle("/nope"), (404, {"detail": "Not Found"})))

passed = 0
for label, actual, expected in checks:
    ok = actual == expected
    passed += ok
    print(f"{'PASS' if ok else 'FAIL'}: {label} (got {actual!r}, expected {expected!r})")

print("PASS" if passed == len(checks) else "FAIL")
