"""
Direct read-only connection to tenant Aurora PostgreSQL databases.

Used in hybrid mode for low-latency reads (agent memory, conversation
history) while mutations go through the platform REST API.

Connects to {tenant_id}_db.aivibe.cloud:5432 using asyncpg.
"""

from __future__ import annotations

from typing import Any

from aicippy.utils.logging import get_logger

logger = get_logger(__name__)


class TenantDBReader:
    """Direct read-only connection to a tenant's Aurora PostgreSQL database.

    Used for low-latency reads (agent memory, conversation history)
    while mutations go through the API. Connection pooling via asyncpg.

    Args:
        tenant_id: Tenant identifier (used to derive the DB host).
        db_credentials: Dict with keys: username, password, database.
        db_host_suffix: Domain suffix for the DB host (default: _db.aivibe.cloud).
        port: PostgreSQL port (default: 5432).
        ssl: Whether to use SSL (default: True).
        min_pool_size: Minimum connection pool size (default: 1).
        max_pool_size: Maximum connection pool size (default: 5).
    """

    __slots__ = (
        "_credentials",
        "_host",
        "_max_pool_size",
        "_min_pool_size",
        "_pool",
        "_port",
        "_ssl",
        "_tenant_id",
    )

    def __init__(
        self,
        tenant_id: str,
        db_credentials: dict[str, str],
        db_host_suffix: str = "_db.aivibe.cloud",
        port: int = 5432,
        ssl: bool = True,
        min_pool_size: int = 1,
        max_pool_size: int = 5,
    ) -> None:
        self._tenant_id = tenant_id
        self._host = f"{tenant_id}{db_host_suffix}"
        self._port = port
        self._ssl = ssl
        self._credentials = db_credentials
        self._min_pool_size = min_pool_size
        self._max_pool_size = max_pool_size
        self._pool: Any = None  # asyncpg.Pool, lazy initialized

    async def _ensure_pool(self) -> Any:
        """Create the connection pool if not already created."""
        if self._pool is not None:
            return self._pool

        try:
            import asyncpg  # type: ignore[import-untyped]

            ssl_context: Any = "require" if self._ssl else False

            self._pool = await asyncpg.create_pool(
                host=self._host,
                port=self._port,
                user=self._credentials.get("username", ""),
                password=self._credentials.get("password", ""),
                database=self._credentials.get("database", "aicippy"),
                ssl=ssl_context,
                min_size=self._min_pool_size,
                max_size=self._max_pool_size,
                command_timeout=10,
            )

            logger.info(
                "tenant_db_pool_created",
                tenant_id=self._tenant_id,
                host=self._host,
            )
            return self._pool

        except ImportError:
            logger.warning("asyncpg_not_installed")
            raise
        except Exception as e:
            logger.warning(
                "tenant_db_pool_creation_failed",
                tenant_id=self._tenant_id,
                error=str(e),
            )
            raise

    async def get_conversation_history(
        self,
        user_id: str,
        limit: int = 50,
    ) -> list[dict[str, Any]]:
        """Read conversation history directly from the tenant database.

        Args:
            user_id: User identifier.
            limit: Maximum number of conversations to return.

        Returns:
            List of conversation records.
        """
        pool = await self._ensure_pool()
        rows = await pool.fetch(
            """
            SELECT session_id, messages, created_at, updated_at, message_count
            FROM aicippy_com_conversations
            WHERE user_id = $1
            ORDER BY updated_at DESC
            LIMIT $2
            """,
            user_id,
            limit,
        )
        return [dict(row) for row in rows]

    async def get_tenant_memories(
        self,
        user_id: str,
    ) -> dict[str, Any]:
        """Read tenant memory entries directly from the tenant database.

        Args:
            user_id: User identifier.

        Returns:
            Dict of key -> value pairs.
        """
        pool = await self._ensure_pool()
        rows = await pool.fetch(
            """
            SELECT key, value
            FROM aicippy_com_tenant_memory
            WHERE user_id = $1
            """,
            user_id,
        )
        return {row["key"]: row["value"] for row in rows}

    async def close(self) -> None:
        """Close the connection pool."""
        if self._pool is not None:
            await self._pool.close()
            self._pool = None
            logger.info(
                "tenant_db_pool_closed",
                tenant_id=self._tenant_id,
            )

    async def __aenter__(self) -> TenantDBReader:
        await self._ensure_pool()
        return self

    async def __aexit__(self, *args: Any) -> None:
        await self.close()
