"""AgentBill Async Client — v10.4.1

Async counterpart of the AgentBill client for use with async frameworks.
Provides the same resource API surface but all HTTP calls are async.

Usage:
    from agentbill import AsyncAgentBill

    async with AsyncAgentBill.init({"api_key": "agb_...", "customer_id": "cust_123"}) as client:
        customers = await client.customers.alist(limit=10)
        resp = await client.request("GET", "/v1/custom-endpoint")
"""

from typing import Any, Dict

from .types import AgentBillConfig
from .async_http_client import AsyncAgentBillHTTPClient


class _AsyncResourceProxy:
    """Wraps sync resource methods to use the async HTTP client.

    Each CRUD call delegates to the async HTTP client, returning parsed data.
    """

    def __init__(self, http: AsyncAgentBillHTTPClient, base_path: str):
        self._http = http
        self._path = base_path

    async def list(self, **params) -> Dict[str, Any]:
        str_params = {k: str(v) for k, v in params.items() if v is not None}
        resp = await self._http.get(self._path, params=str_params)
        return resp.data

    async def create(self, **payload) -> Dict[str, Any]:
        clean = {k: v for k, v in payload.items() if v is not None}
        resp = await self._http.post(self._path, json=clean)
        return resp.data

    async def get(self, resource_id: str) -> Dict[str, Any]:
        resp = await self._http.get(self._path, params={"id": resource_id})
        return resp.data

    async def update(self, resource_id: str, **payload) -> Dict[str, Any]:
        clean = {k: v for k, v in payload.items() if v is not None}
        clean["id"] = resource_id
        resp = await self._http.patch(self._path, json=clean)
        return resp.data

    async def delete(self, resource_id: str) -> None:
        await self._http.request("DELETE", self._path, json={"id": resource_id})


class AsyncAgentBill:
    """Async AgentBill SDK client.

    Mirrors the sync ``AgentBill`` class but uses ``AsyncAgentBillHTTPClient``
    under the hood. Resources expose async CRUD methods.
    """

    def __init__(self, config: AgentBillConfig):
        self.config = config
        base_url = config.get("base_url", "https://api.agentbill.io")
        api_key = config["api_key"]
        self.http = AsyncAgentBillHTTPClient(base_url=base_url, api_key=api_key)

        # Async resource proxies
        self.customers = _AsyncResourceProxy(self.http, "/functions/v1/api-customers")
        self.agents = _AsyncResourceProxy(self.http, "/functions/v1/api-agents")
        self.contacts = _AsyncResourceProxy(self.http, "/functions/v1/api-contacts")
        self.orders = _AsyncResourceProxy(self.http, "/functions/v1/api-orders")
        self.signal_types = _AsyncResourceProxy(self.http, "/functions/v1/api-signal-types")
        self.signals = _AsyncResourceProxy(self.http, "/functions/v1/list-signals")

    @classmethod
    def init(cls, config: AgentBillConfig) -> "AsyncAgentBill":
        """Initialize async AgentBill client."""
        return cls(config)

    # ── Raw HTTP escape hatch ─────────────────────────────────

    async def request(self, method: str, path: str, **kwargs) -> Any:
        """Make an arbitrary async HTTP request through the unified client."""
        return await self.http.request(method, path, **kwargs)

    # ── lifecycle ─────────────────────────────────────────────

    async def close(self) -> None:
        await self.http.close()

    async def __aenter__(self):
        return self

    async def __aexit__(self, *args):
        await self.close()


__all__ = ["AsyncAgentBill"]
