"""SessionManager — 会话管理 + IM Client 多窗口接入

架构：
- 一个 IMClient 实例（contact_id="tool_agent"）
- 一个 ServiceAgent 实例（共享，只读 + 提交任务书）
- 多个 chat_id 窗口，每个窗口维护独立的 Claude SDK session
- 外部 Agent 通过 contact_id + chat_id 咨询
- 收到 IM 消息时，按 chat_id 路由到对应 session
"""

from __future__ import annotations

import asyncio
import logging
import sys
from pathlib import Path
from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from tool_agent.router.agent import Router

logger = logging.getLogger(__name__)

# im-client 路径
_IM_CLIENT_DIR = str(
    Path(__file__).resolve().parent.parent.parent / "im-client"
)
if _IM_CLIENT_DIR not in sys.path:
    sys.path.insert(0, _IM_CLIENT_DIR)


class SessionManager:
    """一个 ServiceAgent 实例 + 多个 chat_id 窗口"""

    def __init__(self, router: Router) -> None:
        self.router = router
        self._sdk_sessions: dict[str, str] = {}  # chat_id → Claude SDK session_id
        self._agent = None  # lazy init, 单实例
        self._im_client = None
        self._im_task = None

    def _get_agent(self):
        if self._agent is None:
            from tool_agent.service.agent import ServiceAgent
            self._agent = ServiceAgent(self.router)
        return self._agent

    # ---- 对话入口（HTTP 和 IM 共用）----

    async def chat(self, message: str, chat_id: str) -> tuple[str, str]:
        """处理一条消息。同一个 ServiceAgent，按 chat_id 隔离 session。"""
        agent = self._get_agent()
        sdk_sid = self._sdk_sessions.get(chat_id)
        response, new_sid = await agent.chat(message, session_id=sdk_sid)
        self._sdk_sessions[chat_id] = new_sid
        return response, chat_id

    def list_sessions(self) -> list[str]:
        return list(self._sdk_sessions.keys())

    def get_status(self) -> dict:
        """返回所有窗口和会话的状态"""
        windows = []
        for chat_id, sdk_sid in self._sdk_sessions.items():
            windows.append({
                "chat_id": chat_id,
                "sdk_session_id": sdk_sid,
                "has_im_window": (
                    self._im_client is not None
                    and chat_id in self._im_client._windows
                ),
            })
        return {
            "total_windows": len(self._sdk_sessions),
            "im_connected": self._im_client is not None and self._im_task is not None,
            "windows": windows,
        }

    # ---- IM Client 接入 ----

    async def start_im(
        self,
        contact_id: str = "tool_agent",
        server_url: str = "ws://localhost:8000",
    ):
        """启动 IM Client，连接 IM Server。"""
        from client import IMClient
        from notifier import AgentNotifier

        self._im_client = IMClient(
            contact_id=contact_id,
            server_url=server_url,
        )
        self._im_task = asyncio.create_task(self._im_client.run())
        logger.info(f"IM Client 已启动，身份: {contact_id}")

    def open_chat_window(self, chat_id: str):
        """为某个 chat_id 打开 IM 窗口，注册消息回调。"""
        if self._im_client is None:
            logger.warning("IM Client 未启动，无法打开窗口")
            return

        from notifier import AgentNotifier

        manager = self

        class _WindowNotifier(AgentNotifier):
            """收到该窗口的消息时，自动调用 ServiceAgent 处理并回复。"""
            async def notify(self, count: int, from_contacts: list[str]):
                await manager._handle_window_messages(chat_id, from_contacts)

        self._im_client.open_window(chat_id, notifier=_WindowNotifier())
        logger.info(f"已打开 IM 窗口: chat_id={chat_id}")

    async def _handle_window_messages(self, chat_id: str, from_contacts: list[str]):
        """处理某个窗口的新消息。"""
        if self._im_client is None:
            return

        pending = self._im_client.read_pending(chat_id)
        for msg in pending:
            sender = msg.get("sender", "unknown")
            content = msg.get("content", "")
            if not content.strip():
                continue

            logger.info(f"IM [{chat_id}] 收到: {sender} -> {content[:60]}")

            try:
                response, _ = await self.chat(content, chat_id=chat_id)
                # 回复到对方的 sender_chat_id（如果有的话）
                sender_chat_id = msg.get("sender_chat_id")
                self._im_client.send_message(
                    chat_id=chat_id,
                    receiver=sender,
                    content=response,
                    receiver_chat_id=sender_chat_id,
                )
                logger.info(f"IM [{chat_id}] 回复: -> {sender} {response[:60]}")
            except Exception as e:
                logger.error(f"IM [{chat_id}] 处理失败: {e}")

    async def stop_im(self):
        if self._im_task:
            self._im_task.cancel()
            try:
                await self._im_task
            except asyncio.CancelledError:
                pass
            self._im_task = None
        logger.info("IM Client 已停止")
