"""SessionManager — high-level API for conversation session management."""

from __future__ import annotations

import logging
from typing import Any

from agentkit.session.models import Message, MessageRole, Session, SessionStatus
from agentkit.session.store import InMemorySessionStore, SessionStore

logger = logging.getLogger(__name__)


class SessionManager:
    """Manages conversation sessions and their messages.

    Provides a high-level API for creating, querying, and updating
    sessions, as well as appending and retrieving messages.
    """

    def __init__(self, store: SessionStore | None = None):
        self._store = store or InMemorySessionStore()

    @property
    def store(self) -> SessionStore:
        return self._store

    async def create_session(
        self,
        agent_name: str,
        metadata: dict[str, Any] | None = None,
    ) -> Session:
        """Create a new conversation session bound to an Agent.

        Args:
            agent_name: Name of the Agent this session is bound to.
            metadata: Optional metadata to attach to the session.

        Returns:
            The newly created Session.
        """
        session = Session(
            session_id=Session.new_session_id(),
            agent_name=agent_name,
            metadata=metadata or {},
        )
        await self._store.save_session(session)
        logger.info(f"Session created: {session.session_id} for agent '{agent_name}'")
        return session

    async def get_session(self, session_id: str) -> Session | None:
        """Get a session by ID."""
        return await self._store.get_session(session_id)

    async def pause_session(self, session_id: str) -> Session | None:
        """Pause an active session."""
        return await self._store.update_session_status(session_id, SessionStatus.PAUSED)

    async def resume_session(self, session_id: str) -> Session | None:
        """Resume a paused session."""
        return await self._store.update_session_status(session_id, SessionStatus.ACTIVE)

    async def close_session(self, session_id: str) -> Session | None:
        """Close a session. Closed sessions cannot accept new messages."""
        return await self._store.update_session_status(session_id, SessionStatus.CLOSED)

    async def delete_session(self, session_id: str) -> bool:
        """Delete a session and all its messages."""
        return await self._store.delete_session(session_id)

    async def list_sessions(
        self,
        agent_name: str | None = None,
        limit: int = 100,
    ) -> list[Session]:
        """List sessions, optionally filtered by agent name."""
        return await self._store.list_sessions(agent_name=agent_name, limit=limit)

    async def append_message(
        self,
        session_id: str,
        role: MessageRole,
        content: str,
        tool_call_id: str | None = None,
        agent_name: str | None = None,
        metadata: dict[str, Any] | None = None,
    ) -> Message:
        """Append a message to a session.

        Args:
            session_id: Target session ID.
            role: Message role (user/assistant/tool/system).
            content: Message content.
            tool_call_id: Optional tool call ID for tool messages.
            agent_name: Optional agent name for multi-Agent sessions.
            metadata: Optional message metadata.

        Returns:
            The newly created Message.

        Raises:
            ValueError: If the session does not exist or is closed.
        """
        session = await self._store.get_session(session_id)
        if session is None:
            raise ValueError(f"Session '{session_id}' not found")
        if session.status == SessionStatus.CLOSED:
            raise ValueError(f"Session '{session_id}' is closed and cannot accept new messages")

        message = Message(
            message_id=Session.new_message_id(),
            session_id=session_id,
            role=role,
            content=content,
            tool_call_id=tool_call_id,
            agent_name=agent_name,
            metadata=metadata or {},
        )
        await self._store.append_message(message)

        # Update session's updated_at timestamp
        session.updated_at = __import__("datetime").datetime.now(__import__("datetime").timezone.utc)
        await self._store.save_session(session)

        return message

    async def get_messages(
        self,
        session_id: str,
        limit: int | None = None,
        offset: int = 0,
    ) -> list[Message]:
        """Get messages for a session with optional pagination.

        Args:
            session_id: Target session ID.
            limit: Maximum number of messages to return. None for all.
            offset: Number of messages to skip from the beginning.

        Returns:
            List of messages ordered chronologically.
        """
        return await self._store.get_messages(session_id, limit=limit, offset=offset)

    async def get_chat_messages(self, session_id: str) -> list[dict[str, str]]:
        """Get messages formatted for LLM chat API consumption.

        Returns messages as OpenAI-compatible dicts suitable for
        passing directly to the ReAct engine or LLM Gateway.
        """
        messages = await self._store.get_messages(session_id)
        return [m.to_chat_message() for m in messages]

    async def count_messages(self, session_id: str) -> int:
        """Count messages in a session."""
        return await self._store.count_messages(session_id)

    async def health_check(self) -> bool:
        """Check if the underlying store is healthy."""
        return await self._store.health_check()
