"""
Polymarket API client.

Thin wrapper around Polymarket's public REST APIs.
All functions are async and return raw dicts / lists.

API reference: https://docs.polymarket.com/api-reference
"""

import httpx
from typing import Any

GAMMA_API = "https://gamma-api.polymarket.com"
CLOB_API = "https://clob.polymarket.com"

TIMEOUT = httpx.Timeout(15.0)


async def _get(url: str, params: dict[str, Any] | None = None) -> Any:
    """Fire a GET request and return parsed JSON."""
    async with httpx.AsyncClient(timeout=TIMEOUT) as client:
        resp = await client.get(url, params=params)
        resp.raise_for_status()
        return resp.json()


# ── Search (Gamma /public-search) ───────────────────────────────

async def search_markets_api(query: str, limit: int = 20) -> list[dict]:
    """Full-text search across Polymarket markets.

    Uses the /public-search endpoint — the same search that powers the
    Polymarket website. Returns active, open markets sorted by volume.
    """
    data = await _get(f"{GAMMA_API}/public-search", params={
        "q": query,
        "limit_per_type": 50,
        "events_status": "active",
    })
    events = data.get("events") or []

    markets: list[dict] = []
    seen: set[str] = set()
    for event in events:
        for m in event.get("markets", []):
            mid = str(m.get("id") or m.get("conditionId") or "")
            if mid and mid not in seen:
                seen.add(mid)
                if m.get("closed"):
                    continue
                markets.append(m)

    def _vol(m: dict) -> float:
        try:
            return float(m.get("volume24hr") or 0)
        except (TypeError, ValueError):
            return 0.0

    markets.sort(key=_vol, reverse=True)
    return markets[:limit]


# ── Markets (Gamma /markets) ────────────────────────────────────

async def get_markets(
    limit: int = 100,
    order: str = "volume24hr",
    ascending: bool = False,
    closed: bool = False,
    end_date_min: str | None = None,
    end_date_max: str | None = None,
    volume_num_min: float | None = None,
    tag_id: int | None = None,
) -> list[dict]:
    """Fetch markets with flexible filtering.

    Params match the official Gamma API docs:
    https://docs.polymarket.com/api-reference/markets/list-markets
    """
    params: dict[str, Any] = {
        "limit": min(limit, 100),
        "order": order,
        "ascending": str(ascending).lower(),
        "closed": str(closed).lower(),
    }
    if end_date_min:
        params["end_date_min"] = end_date_min
    if end_date_max:
        params["end_date_max"] = end_date_max
    if volume_num_min is not None:
        params["volume_num_min"] = volume_num_min
    if tag_id is not None:
        params["tag_id"] = tag_id
    return await _get(f"{GAMMA_API}/markets", params=params)


async def get_market_by_id(market_id: str) -> dict:
    """Fetch a single market by its ID."""
    return await _get(f"{GAMMA_API}/markets/{market_id}")


async def get_market_by_slug(slug: str) -> dict:
    """Fetch a single market by its slug."""
    return await _get(f"{GAMMA_API}/markets/slug/{slug}")


# ── Events (Gamma /events) ──────────────────────────────────────

async def get_events(
    limit: int = 50,
    order: str = "volume24hr",
    ascending: bool = False,
    active: bool = True,
    closed: bool = False,
    tag_slug: str | None = None,
    end_date_min: str | None = None,
    end_date_max: str | None = None,
) -> list[dict]:
    """Fetch events with filtering.

    Each event contains nested markets.
    Docs: https://docs.polymarket.com/api-reference/events/list-events
    """
    params: dict[str, Any] = {
        "limit": min(limit, 100),
        "order": order,
        "ascending": str(ascending).lower(),
        "active": str(active).lower(),
        "closed": str(closed).lower(),
    }
    if tag_slug:
        params["tag_slug"] = tag_slug
    if end_date_min:
        params["end_date_min"] = end_date_min
    if end_date_max:
        params["end_date_max"] = end_date_max
    return await _get(f"{GAMMA_API}/events", params=params)


# ── Orderbook (CLOB /book) ──────────────────────────────────────

async def get_orderbook(token_id: str) -> dict:
    """Fetch the CLOB orderbook for a token.

    Returns bids, asks, spread, last_trade_price.
    Docs: https://docs.polymarket.com/api-reference/market-data/get-order-book
    """
    return await _get(f"{CLOB_API}/book", params={"token_id": token_id})


# ── Price History (CLOB /prices-history) ─────────────────────────

async def get_price_history(
    token_id: str,
    interval: str = "1w",
    fidelity: int = 60,
) -> dict:
    """Fetch historical price data for a market token.

    Args:
        token_id: The token (asset) ID.
        interval: Time window — "1h", "6h", "1d", "1w", "1m", "all", "max".
        fidelity: Data granularity in minutes (default 60 = hourly points).

    Docs: https://docs.polymarket.com/api-reference/markets/get-prices-history
    """
    return await _get(f"{CLOB_API}/prices-history", params={
        "market": token_id,
        "interval": interval,
        "fidelity": fidelity,
    })
