"""
Adopt worker tool.

Provides adopt_worker for importing existing terminal Claude Code and Codex sessions.
"""

import logging
import os
from typing import TYPE_CHECKING

from mcp.server.fastmcp import Context, FastMCP
from mcp.server.session import ServerSession

if TYPE_CHECKING:
    from ..server import AppContext

from ..registry import SessionStatus
from ..session_state import (
    find_codex_session_by_iterm_id,
    find_codex_session_by_tmux_id,
    find_jsonl_by_iterm_id,
    find_jsonl_by_tmux_id,
)
from ..utils import error_response, HINTS

logger = logging.getLogger("maniple")


def register_tools(mcp: FastMCP, ensure_connection) -> None:
    """Register adopt_worker tool on the MCP server."""

    @mcp.tool()
    async def adopt_worker(
        ctx: Context[ServerSession, "AppContext"],
        iterm_session_id: str | None = None,
        tmux_pane_id: str | None = None,
        session_name: str | None = None,
        max_age: int | None = 3600,
    ) -> dict:
        """
        Adopt an existing terminal Claude Code or Codex session into the MCP registry.

        Takes a terminal session ID (from discover_workers) and registers it
        for management. Only works for sessions originally spawned by maniple
        (or legacy claude-team) which have markers in their JSONL for reliable correlation.

        Args:
            iterm_session_id: The iTerm2 session ID (from discover_workers)
            tmux_pane_id: The tmux pane ID (from discover_workers)
            session_name: Optional friendly name for the worker
            max_age: Only check JSONL files modified within this many seconds (default 3600)

        Returns:
            Dict with adopted worker info, or error if session not found
        """
        # Handle None values from MCP clients that send explicit null for omitted params
        max_age = max_age if max_age is not None else 3600

        app_ctx = ctx.request_context.lifespan_context
        registry = app_ctx.registry

        # Ensure we have a fresh backend connection/state
        backend = await ensure_connection(app_ctx)
        backend_id = backend.backend_id

        target_id = iterm_session_id if backend_id == "iterm" else tmux_pane_id
        if backend_id == "tmux" and not target_id:
            target_id = iterm_session_id
        if backend_id == "iterm" and not target_id:
            target_id = tmux_pane_id

        if not target_id:
            return error_response(
                "terminal session id is required",
                hint="Pass iterm_session_id or tmux_pane_id from discover_workers",
            )

        # Check if already managed
        for managed in registry.list_all():
            if (
                hasattr(managed, 'terminal_session')
                and managed.terminal_session.backend_id == backend_id
                and managed.terminal_session.native_id == target_id
            ):
                return error_response(
                    f"Session already managed as '{managed.session_id}'",
                    hint="Use message_workers to communicate with the existing session",
                    existing_session=managed.to_dict(),
                )

        # Find the terminal session by ID
        target_session = None
        try:
            terminal_sessions = await backend.list_sessions()
        except Exception as e:
            logger.warning(f"Error listing sessions for backend {backend_id}: {e}")
            terminal_sessions = []

        for session in terminal_sessions:
            if session.native_id == target_id:
                target_session = session
                break

        if not target_session:
            return error_response(
                f"Terminal session not found: {target_id}",
                hint="Run discover_workers to scan for active Claude or Codex sessions",
            )

        # Use marker-based discovery to recover original session identity.
        # This only works for sessions we originally spawned (which have our markers).
        agent_type = "claude"
        match = None
        if backend_id == "iterm":
            match = find_jsonl_by_iterm_id(target_id, max_age_seconds=max_age)
            if not match:
                codex_match = find_codex_session_by_iterm_id(
                    target_id,
                    max_age_seconds=max_age,
                )
                if not codex_match:
                    return error_response(
                        "Session not found or not spawned by maniple",
                        hint="adopt_worker only works for sessions originally spawned by maniple (or legacy claude-team). "
                        "External sessions cannot be reliably correlated to their JSONL files.",
                        iterm_session_id=target_id,
                    )
                match = codex_match
                agent_type = "codex"
        elif backend_id == "tmux":
            match = find_jsonl_by_tmux_id(target_id, max_age_seconds=max_age)
            if not match:
                codex_match = find_codex_session_by_tmux_id(
                    target_id,
                    max_age_seconds=max_age,
                )
                if not codex_match:
                    return error_response(
                        "Session not found or not spawned by maniple",
                        hint="adopt_worker only works for sessions originally spawned by maniple (or legacy claude-team). "
                        "External sessions cannot be reliably correlated to their JSONL files.",
                        tmux_pane_id=target_id,
                    )
                match = codex_match
                agent_type = "codex"
        else:
            return error_response(
                "adopt_worker is only supported with iTerm2 or tmux backend",
                hint=HINTS["terminal_backend_required"],
            )

        logger.info(
            "Recovered session via terminal marker: "
            f"project={match.project_path}, internal_id={match.internal_session_id}, "
            f"agent_type={agent_type}"
        )

        # Validate project path still exists
        if not os.path.isdir(match.project_path):
            return error_response(
                f"Project path no longer exists: {match.project_path}",
                hint=HINTS["project_path_missing"],
            )

        # Register with recovered identity (no new marker needed)
        managed = registry.add(
            terminal_session=target_session,
            project_path=match.project_path,
            name=session_name,
            session_id=match.internal_session_id,  # Recover original ID
        )
        managed.agent_type = agent_type
        if agent_type == "claude":
            managed.claude_session_id = match.jsonl_path.stem

        # Mark ready immediately (no discovery needed, we already have it)
        registry.update_status(managed.session_id, SessionStatus.READY)

        return {
            "success": True,
            "message": f"Session recovered as '{managed.session_id}'",
            "session": managed.to_dict(),
        }
