from __future__ import annotations

import asyncio
from collections.abc import Awaitable, Callable

import httpx
from fastapi import FastAPI

type Scenario[Result] = Callable[[httpx.AsyncClient], Awaitable[Result]]


def run_scenario[Result](application: FastAPI, scenario: Scenario[Result]) -> Result:
    async def run() -> Result:
        transport = httpx.ASGITransport(app=application, raise_app_exceptions=False)
        async with application.router.lifespan_context(application):
            async with httpx.AsyncClient(
                transport=transport, base_url="http://testserver"
            ) as client:
                return await scenario(client)

    return asyncio.run(run())


def request(application: FastAPI, path: str) -> httpx.Response:
    async def get(client: httpx.AsyncClient) -> httpx.Response:
        return await client.get(path)

    return run_scenario(application, get)
