from typing import Dict, List

import asyncio
import time
import httpx

from rlmesh.client.console import RLMeshConsole

ENDPOINTS_URL = "https://gcping.com/api/endpoints"


async def _fetch_region_url_map(client: httpx.AsyncClient) -> Dict[str, str]:
    r = await client.get(ENDPOINTS_URL, timeout=5)
    r.raise_for_status()
    data = r.json()
    if isinstance(data, dict):
        return {k: v["URL"] for k, v in data.items()}
    elif isinstance(data, list):
        return {item["Region"]: item["URL"] for item in data}
    else:
        raise TypeError(f"Unexpected endpoints payload type: {type(data).__name__}")


async def _ping_once(
    client: httpx.AsyncClient, url: str, timeout: float = 3.0
) -> float:
    t0 = time.perf_counter()
    try:
        resp = await client.get(url, timeout=timeout)
        resp.raise_for_status()
        return (time.perf_counter() - t0) * 1000.0
    except httpx.RequestError:
        return float("inf")


async def ping_gcp_regions_async(
    regions: List[str], timeout: float = 3.0
) -> Dict[str, float]:
    async with httpx.AsyncClient(http2=True) as client:
        mapping = await _fetch_region_url_map(client)
        tasks = {
            r: asyncio.create_task(_ping_once(client, mapping.get(r, ""), timeout))
            for r in regions
            if r in mapping
        }
        return {r: await t for r, t in tasks.items()}


async def compare_gcp_regions_async(regions: List[str], timeout: float = 3.0) -> str:
    results = await ping_gcp_regions_async(regions, timeout=timeout)
    if not results:
        raise ValueError("No valid regions to compare (none matched endpoint map).")
    return min(results, key=results.get)  # pyright: ignore
