"""
Discover workers tool.

Provides discover_workers for finding existing Claude Code and Codex sessions.
"""

import logging
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 ..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,
    get_project_dir,
    parse_codex_session,
    parse_session,
)
from ..utils import error_response, HINTS

logger = logging.getLogger("maniple")


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

    @mcp.tool()
    async def discover_workers(
        ctx: Context[ServerSession, "AppContext"],
        max_age: int | None = 3600,
    ) -> dict:
        """
        Discover existing Claude Code and Codex sessions running in the active terminal backend.

        For each terminal session, searches JSONL files in ~/.claude/projects/ and
        ~/.codex/sessions/ for matching terminal session markers. Sessions spawned
        by maniple (formerly claude-team) write their terminal IDs into the JSONL
        (e.g., <!maniple-iterm:UUID!>, <!maniple-tmux:%1!>, or legacy <!claude-team-...!>), enabling
        reliable detection and recovery after MCP server restarts.
        For tmux, only panes in maniple/claude-team-managed tmux sessions are scanned.

        Only JSONL files modified within max_age seconds are checked. If a session
        was started more than max_age seconds ago and hasn't had recent activity,
        it won't be discovered. Increase max_age to find older sessions.

        Args:
            max_age: Only check JSONL files modified within this many seconds.
                Default 3600 (1 hour). Use 86400 (24 hours) for older sessions.

        Returns:
            Dict with:
                - sessions: List of discovered sessions, each containing:
                    - backend_id: Terminal backend identifier
                    - iterm_session_id: iTerm2's internal session ID (iTerm backend)
                    - tmux_pane_id: tmux pane id (tmux backend)
                    - project_path: Detected project path
                    - claude_session_id: The JSONL session UUID (Claude only)
                    - codex_session_id: The JSONL session UUID (Codex only)
                    - internal_session_id: Our short session ID (e.g., "b48e2d5b")
                    - last_assistant_preview: Preview of last assistant message
                    - already_managed: True if already in our registry
                    - agent_type: "claude" or "codex"
                - count: Total number of sessions found
                - unmanaged_count: Number not yet in registry (available to adopt)
        """
        # 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

        if backend_id not in ("iterm", "tmux"):
            return error_response(
                "discover_workers is only supported with iTerm2 or tmux backend",
                hint=HINTS["terminal_backend_required"],
            )

        discovered = []

        managed_ids = {
            s.terminal_session.native_id
            for s in registry.list_all()
            if hasattr(s, 'terminal_session') and s.terminal_session.backend_id == backend_id
        }

        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 terminal_session in terminal_sessions:
            native_id = terminal_session.native_id
            try:
                if backend_id == "iterm":
                    # Look for this iTerm session ID in recent JSONL files
                    match = find_jsonl_by_iterm_id(
                        native_id,
                        max_age_seconds=max_age,
                    )

                    if match:
                        project_path = match.project_path
                        claude_session_id = match.jsonl_path.stem
                        internal_session_id = match.internal_session_id

                        # Get last assistant message preview from JSONL
                        last_assistant_preview = None
                        try:
                            jsonl_path = (
                                get_project_dir(project_path)
                                / f"{claude_session_id}.jsonl"
                            )
                            if jsonl_path.exists():
                                state = parse_session(jsonl_path)
                                if state.last_assistant_message:
                                    content = state.last_assistant_message.content
                                    last_assistant_preview = (
                                        content[:200] + "..."
                                        if len(content) > 200
                                        else content
                                    )
                        except Exception as e:
                            logger.debug(f"Could not get conversation preview: {e}")

                        discovered.append({
                            "backend_id": backend_id,
                            "iterm_session_id": native_id,
                            "project_path": project_path,
                            "claude_session_id": claude_session_id,
                            "internal_session_id": internal_session_id,
                            "last_assistant_preview": last_assistant_preview,
                            "already_managed": native_id in managed_ids,
                            "agent_type": "claude",
                        })
                        continue

                    # Fall back to Codex marker scan if no Claude match
                    codex_match = find_codex_session_by_iterm_id(
                        native_id,
                        max_age_seconds=max_age,
                    )

                    if not codex_match:
                        continue

                    project_path = codex_match.project_path
                    internal_session_id = codex_match.internal_session_id

                    # Get last assistant message preview from Codex JSONL
                    last_assistant_preview = None
                    try:
                        jsonl_path = codex_match.jsonl_path
                        if jsonl_path.exists():
                            state = parse_codex_session(jsonl_path)
                            if state.last_assistant_message:
                                content = state.last_assistant_message.content
                                last_assistant_preview = (
                                    content[:200] + "..."
                                    if len(content) > 200
                                    else content
                                )
                    except Exception as e:
                        logger.debug(f"Could not get conversation preview: {e}")

                    discovered.append({
                        "backend_id": backend_id,
                        "iterm_session_id": native_id,
                        "project_path": project_path,
                        "codex_session_id": codex_match.jsonl_path.stem,
                        "internal_session_id": internal_session_id,
                        "last_assistant_preview": last_assistant_preview,
                        "already_managed": native_id in managed_ids,
                        "agent_type": "codex",
                    })
                    continue

                # Tmux backend
                match = find_jsonl_by_tmux_id(
                    native_id,
                    max_age_seconds=max_age,
                )

                if not match:
                    # Fall back to Codex marker scan if no Claude match
                    codex_match = find_codex_session_by_tmux_id(
                        native_id,
                        max_age_seconds=max_age,
                    )

                    if not codex_match:
                        continue

                    project_path = codex_match.project_path
                    internal_session_id = codex_match.internal_session_id

                    # Get last assistant message preview from Codex JSONL
                    last_assistant_preview = None
                    try:
                        jsonl_path = codex_match.jsonl_path
                        if jsonl_path.exists():
                            state = parse_codex_session(jsonl_path)
                            if state.last_assistant_message:
                                content = state.last_assistant_message.content
                                last_assistant_preview = (
                                    content[:200] + "..."
                                    if len(content) > 200
                                    else content
                                )
                    except Exception as e:
                        logger.debug(f"Could not get conversation preview: {e}")

                    discovered.append({
                        "backend_id": backend_id,
                        "tmux_pane_id": native_id,
                        "project_path": project_path,
                        "codex_session_id": codex_match.jsonl_path.stem,
                        "internal_session_id": internal_session_id,
                        "last_assistant_preview": last_assistant_preview,
                        "already_managed": native_id in managed_ids,
                        "agent_type": "codex",
                    })
                    continue

                project_path = match.project_path
                claude_session_id = match.jsonl_path.stem
                internal_session_id = match.internal_session_id

                # Get last assistant message preview from JSONL
                last_assistant_preview = None
                try:
                    jsonl_path = get_project_dir(project_path) / f"{claude_session_id}.jsonl"
                    if jsonl_path.exists():
                        state = parse_session(jsonl_path)
                        if state.last_assistant_message:
                            content = state.last_assistant_message.content
                            last_assistant_preview = (
                                content[:200] + "..."
                                if len(content) > 200
                                else content
                            )
                except Exception as e:
                    logger.debug(f"Could not get conversation preview: {e}")

                discovered.append({
                    "backend_id": backend_id,
                    "tmux_pane_id": native_id,
                    "project_path": project_path,
                    "claude_session_id": claude_session_id,
                    "internal_session_id": internal_session_id,
                    "last_assistant_preview": last_assistant_preview,
                    "already_managed": native_id in managed_ids,
                    "agent_type": "claude",
                })

            except Exception as e:
                logger.warning(f"Error scanning session {native_id}: {e}")
                continue

        unmanaged = [s for s in discovered if not s["already_managed"]]

        return {
            "sessions": discovered,
            "count": len(discovered),
            "unmanaged_count": len(unmanaged),
        }
