"""Octen API 异步客户端"""

from typing import Optional
from .core.async_http_client import AsyncHTTPClient
from .resources.search import SearchResource
from .resources.embedding import EmbeddingResource
from .utils.constants import DEFAULT_BASE_URL, DEFAULT_TIMEOUT, DEFAULT_MAX_RETRIES


class AsyncSearchResource(SearchResource):
    """异步 Search API 资源

    继承自同步 SearchResource，但使用异步 HTTP 客户端
    """

    async def search(self, *args, **kwargs):
        """异步执行 Web 搜索

        参数与同步版本相同，但需要 await 调用
        """
        # 复用父类的参数验证逻辑
        from octen.models.search import SearchRequest, SearchResponse
        from octen.utils.constants import ENDPOINT_SEARCH

        request = SearchRequest(
            query=kwargs.get("query"),
            count=kwargs.get("count"),
            search_type=kwargs.get("search_type"),
            include_domains=kwargs.get("include_domains"),
            exclude_domains=kwargs.get("exclude_domains"),
            include_text=kwargs.get("include_text"),
            exclude_text=kwargs.get("exclude_text"),
            time_basis=kwargs.get("time_basis"),
            start_time=kwargs.get("start_time"),
            end_time=kwargs.get("end_time"),
            highlight=kwargs.get("highlight"),
            format=kwargs.get("format"),
            safesearch=kwargs.get("safesearch"),
            full_content=kwargs.get("full_content"),
        )

        response_data = await self._client.request(
            method="POST",
            endpoint=ENDPOINT_SEARCH,
            json=request.model_dump(exclude_none=True),
            timeout=kwargs.get("timeout"),
        )

        return SearchResponse(**response_data)

    async def simple_search(self, query: str, count: int = 5, timeout: Optional[float] = None):
        """异步简化搜索接口"""
        return await self.search(query=query, count=count, timeout=timeout)


class AsyncEmbeddingResource(EmbeddingResource):
    """异步 Embedding API 资源

    继承自同步 EmbeddingResource，但使用异步 HTTP 客户端
    """

    async def create(self, *args, **kwargs):
        """异步创建文本嵌入

        参数与同步版本相同，但需要 await 调用
        """
        from octen.models.embedding import EmbeddingRequest, EmbeddingResponse
        from octen.utils.constants import ENDPOINT_EMBEDDING

        request = EmbeddingRequest(
            input=kwargs.get("input"),
            model=kwargs.get("model"),
            dimension=kwargs.get("dimension"),
            input_type=kwargs.get("input_type"),
            truncation=kwargs.get("truncation"),
        )

        response_data = await self._client.request(
            method="POST",
            endpoint=ENDPOINT_EMBEDDING,
            json=request.model_dump(exclude_none=True),
            timeout=kwargs.get("timeout"),
        )

        return EmbeddingResponse(**response_data)

    async def embed_query(self, text: str, model: Optional[str] = None,
                         dimension: Optional[int] = None, timeout: Optional[float] = None):
        """异步嵌入查询文本"""
        response = await self.create(
            input=text,
            model=model,
            dimension=dimension,
            input_type="query",
            timeout=timeout,
        )
        return response.get_first_embedding() or []

    async def embed_documents(self, texts, model: Optional[str] = None,
                             dimension: Optional[int] = None, timeout: Optional[float] = None):
        """异步嵌入文档文本列表"""
        response = await self.create(
            input=texts,
            model=model,
            dimension=dimension,
            input_type="document",
            timeout=timeout,
        )
        return response.get_embeddings()


class AsyncOcten:
    """Octen API 异步客户端

    提供对 Octen API 的异步访问，支持搜索和嵌入功能。

    Attributes:
        search: 异步 Search API 资源
        embedding: 异步 Embedding API 资源

    Example:
        基础用法::

            import asyncio
            from octen import AsyncOcten

            async def main():
                # 使用异步上下文管理器（推荐）
                async with AsyncOcten(api_key="your-api-key") as client:
                    # 异步搜索
                    response = await client.search.search("Python", count=5)
                    for result in response.results:
                        print(result['title'])

                    # 异步嵌入
                    embedding = await client.embedding.create("Hello")
                    vector = embedding.get_first_embedding()

            asyncio.run(main())

        并发请求::

            async def main():
                async with AsyncOcten(api_key="your-api-key") as client:
                    # 同时执行多个请求
                    search_task = client.search.search("AI")
                    embedding_task = client.embedding.create("Hello")

                    results, embeddings = await asyncio.gather(
                        search_task,
                        embedding_task
                    )

            asyncio.run(main())
    """

    def __init__(
        self,
        api_key: str,
        base_url: str = DEFAULT_BASE_URL,
        timeout: float = DEFAULT_TIMEOUT,
        max_retries: int = DEFAULT_MAX_RETRIES,
        http2: bool = True,
    ):
        """初始化异步 Octen 客户端

        Args:
            api_key: Octen API 密钥（必填）
            base_url: API 基础 URL（默认: https://api.octen.ai）
            timeout: 默认请求超时时间，单位秒（默认: 30.0）
            max_retries: 最大重试次数（默认: 3）
            http2: 是否启用 HTTP/2（默认: True）

        Raises:
            ValueError: 如果 api_key 为空
        """
        if not api_key:
            raise ValueError("api_key 不能为空")

        # 创建异步 HTTP 客户端
        self._http_client = AsyncHTTPClient(
            base_url=base_url,
            api_key=api_key,
            timeout=timeout,
            max_retries=max_retries,
            http2=http2,
        )

        # 初始化异步资源
        self.search = AsyncSearchResource(self._http_client)
        self.embedding = AsyncEmbeddingResource(self._http_client)

    async def close(self):
        """关闭客户端，释放连接池资源

        在不使用异步上下文管理器时，应该手动调用此方法。
        """
        await self._http_client.close()

    async def __aenter__(self):
        """支持异步上下文管理器协议"""
        return self

    async def __aexit__(self, exc_type, exc_val, exc_tb):
        """退出异步上下文管理器时自动关闭客户端"""
        await self.close()
        return False

    def __repr__(self) -> str:
        """返回客户端的字符串表示"""
        return f"AsyncOcten(base_url={self._http_client.base_url!r})"
