from typing import get_type_hints
import aiohttp
from functools import wraps
from typing import Callable, Any, Awaitable


class BaseClient:
    def __init__(self, session: aiohttp.ClientSession=None, host: str = None):
        self.session = session
        self.host = host

    def open(self):
        self.session = aiohttp.ClientSession()

    async def __aenter__(self) -> "BaseClient":
        self.open()
        return self

    async def __aexit__(self, exc_type, exc_val, exc_tb):
        await self.session.close()

    @staticmethod
    def http_post(endpoint: str):
        """
        HTTP POST请求装饰器，处理通用的请求逻辑
        """

        def decorator(func: Callable[..., Awaitable[Any]]) -> Callable[..., Awaitable[Any]]:
            @wraps(func)
            async def wrapper(client_instance: BaseClient, model: Any, request_id: str):
                # 从原函数的返回类型注解中获取VO类型
                return_type = get_type_hints(func).get("return")
                if return_type is None:
                    raise ValueError(
                        f"Function {func.__name__} must have a return type annotation"
                    )

                url = f"{client_instance.host}{endpoint}"
                headers = {"request_id": request_id}
                json_data = model.model_dump()

                async with client_instance.session.post(
                    url, headers=headers, json=json_data
                ) as response:
                    response.raise_for_status()
                    response_json = await response.json()
                    return return_type(**response_json)

            return wrapper

        return decorator
