import asyncio
from typing import Dict, Optional
from agent.memory import MemoryManager


class SessionManager:
    """Manages agent sessions and their associated memory.

    Coordinates between the gateway's UserSession (for conversation state)
    and the agent's MemoryManager (for persistent memory with Zep).
    """

    def __init__(self, memory_manager: MemoryManager):
        """Initialize session manager.

        Args:
            memory_manager: MemoryManager instance for persistent storage
        """
        self.memory = memory_manager
        self._locks: Dict[str, asyncio.Lock] = {}

    async def get_session_lock(self, session_id: str) -> asyncio.Lock:
        """Get or create a lock for a session.

        Prevents concurrent execution for the same session.

        Args:
            session_id: Session identifier

        Returns:
            asyncio.Lock for this session
        """
        if session_id not in self._locks:
            self._locks[session_id] = asyncio.Lock()
        return self._locks[session_id]

    async def save_message(
        self,
        session_id: str,
        role: str,
        content: str,
        metadata: Optional[Dict] = None
    ) -> None:
        """Save a message to persistent memory.

        Args:
            session_id: Session identifier
            role: Message role ("user" or "assistant")
            content: Message content
            metadata: Optional metadata
        """
        await self.memory.add_memory(session_id, role, content, metadata)

    async def get_relevant_context(
        self,
        session_id: str,
        query: str,
        limit: int = 5
    ) -> str:
        """Get relevant historical context for a query.

        Uses semantic search over past conversations.

        Args:
            session_id: Session identifier
            query: Search query
            limit: Maximum results

        Returns:
            Formatted string of relevant past messages
        """
        results = await self.memory.search_memory(session_id, query, limit)

        if not results:
            return ""

        context_parts = ["## Relevant Past Context\n"]
        for i, result in enumerate(results, 1):
            role = result["role"].capitalize()
            content = result["content"]
            score = result.get("score", 0.0)
            context_parts.append(f"{i}. [{role}, relevance: {score:.2f}] {content}\n")

        return "\n".join(context_parts)

    async def cleanup_session(self, session_id: str) -> None:
        """Cleanup session resources.

        Args:
            session_id: Session to cleanup
        """
        if session_id in self._locks:
            del self._locks[session_id]
