"""HTTP client for Memory Gateway's `/memory-system` API."""

from __future__ import annotations

from typing import Any

import httpx

from .store import MemoryGatewayUserStore


class MemoryGatewayClient:
    """Small async client for the Memory Gateway business API."""

    def __init__(
        self,
        *,
        base_url: str,
        store: MemoryGatewayUserStore,
        api_key: str = "",
        timeout_seconds: float = 15.0,
        transport: httpx.AsyncBaseTransport | None = None,
    ) -> None:
        self.base_url = base_url.rstrip("/")
        self.api_key = api_key
        self.timeout_seconds = timeout_seconds
        self.store = store
        self.transport = transport

    async def ensure_user(self, user_id: str) -> str:
        cached = self.store.get_user_key(user_id)
        if cached:
            return cached

        data = await self._post("/memory-system/users", {"user_id": user_id})
        user_key = self._extract_user_key(data)
        if not user_key:
            raise RuntimeError("Memory Gateway user creation response missing user_key")
        self.store.save_user_key(user_id, user_key)
        return user_key

    async def get_profile(
        self,
        *,
        user_id: str,
        user_key: str,
        query: str = "用户画像",
        limit: int = 5,
    ) -> dict[str, Any]:
        return await self._get(
            f"/memory-system/users/{user_id}/profile",
            {"user_key": user_key, "query": query, "limit": limit},
        )

    async def get_session_context(
        self,
        *,
        user_id: str,
        user_key: str,
        session_id: str,
        query: str,
        limit: int = 5,
    ) -> dict[str, Any]:
        return await self._post(
            f"/memory-system/sessions/{session_id}/context",
            {"user_id": user_id, "user_key": user_key, "query": query, "limit": limit},
        )

    async def search(
        self,
        *,
        user_id: str,
        user_key: str,
        session_id: str,
        query: str,
        limit: int = 5,
    ) -> dict[str, Any]:
        return await self._post(
            "/memory-system/search",
            {
                "user_id": user_id,
                "user_key": user_key,
                "session_id": session_id,
                "query": query,
                "use_llm": False,
                "limit": limit,
            },
        )

    async def ingest_messages(
        self,
        *,
        user_id: str,
        user_key: str,
        session_id: str,
        user_message: str | None,
        assistant_message: str | None,
    ) -> dict[str, Any]:
        return await self._post(
            "/memory-system/messages",
            {
                "user_id": user_id,
                "user_key": user_key,
                "session_id": session_id,
                "user_message": user_message,
                "assistant_message": assistant_message,
            },
        )

    async def commit_session(
        self,
        *,
        user_id: str,
        user_key: str,
        session_id: str,
    ) -> dict[str, Any]:
        return await self._post(
            f"/memory-system/sessions/{session_id}/commit",
            {"user_id": user_id, "user_key": user_key},
        )

    async def _get(self, path: str, params: dict[str, Any]) -> dict[str, Any]:
        async with self._client() as client:
            response = await client.get(path, params=params)
            response.raise_for_status()
            return response.json()

    async def _post(self, path: str, payload: dict[str, Any]) -> dict[str, Any]:
        async with self._client() as client:
            response = await client.post(path, json=payload)
            response.raise_for_status()
            return response.json()

    def _client(self) -> httpx.AsyncClient:
        headers = {"Content-Type": "application/json"}
        if self.api_key:
            headers["X-API-Key"] = self.api_key
        return httpx.AsyncClient(
            base_url=self.base_url,
            headers=headers,
            timeout=self.timeout_seconds,
            transport=self.transport,
        )

    @staticmethod
    def _extract_user_key(data: dict[str, Any]) -> str | None:
        account = data.get("account")
        result = account.get("result") if isinstance(account, dict) else None
        user_key = result.get("user_key") if isinstance(result, dict) else None
        return str(user_key) if user_key else None
