"""
Read worker logs tool.

Provides read_worker_logs for getting conversation history from a Claude Code session.
"""

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 ..utils import error_response, HINTS, get_session_or_error, CONVERSATION_PAGE_SIZE


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

    @mcp.tool()
    async def read_worker_logs(
        ctx: Context[ServerSession, "AppContext"],
        session_id: str,
        pages: int | None = 1,
        offset: int | None = 0,
    ) -> dict:
        """
        Get conversation history from a Claude Code session with reverse pagination.

        Returns messages from the session's JSONL file, paginated from the end
        (most recent first by default). Each message includes text content,
        tool use names/inputs, and thinking blocks.

        Pagination works from the end of the conversation:
        - pages=1, offset=0: Returns the most recent page (default)
        - pages=3, offset=0: Returns the last 3 pages in chronological order
        - pages=2, offset=1: Returns 2 pages, skipping the most recent page

        Page size is 5 messages (each user or assistant message counts as 1).

        Args:
            session_id: ID of the target session.
                Accepts internal IDs, terminal IDs, or worker names.
            pages: Number of pages to return (default 1)
            offset: Number of pages to skip from the end (default 0 = most recent)

        Returns:
            Dict with:
                - messages: List of message dicts in chronological order
                - page_info: Pagination metadata (total_messages, total_pages, etc.)
                - session_id: The session ID
        """
        # Handle None values from MCP clients that send explicit null for omitted params
        pages = pages if pages is not None else 1
        offset = offset if offset is not None else 0

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

        # Validate inputs
        if pages < 1:
            return error_response(
                "pages must be at least 1",
                hint="Use pages=1 to get the most recent page",
            )
        if offset < 0:
            return error_response(
                "offset must be non-negative",
                hint="Use offset=0 for most recent, offset=1 to skip most recent page, etc.",
            )

        # Look up session (accepts internal ID, terminal ID, or name)
        session = get_session_or_error(registry, session_id)
        if isinstance(session, dict):
            return session  # Error response

        jsonl_path = session.get_jsonl_path()
        if not jsonl_path or not jsonl_path.exists():
            return error_response(
                "No JSONL session file found - Claude may not have started yet",
                hint=HINTS["no_jsonl_file"],
                session_id=session_id,
                status=session.status.value,
            )

        # Parse the session state
        state = session.get_conversation_state()
        if not state:
            return error_response(
                "Could not parse session state",
                hint="The JSONL file may be corrupted. Try closing and spawning a new session",
                session_id=session_id,
                status=session.status.value,
            )

        # Get all messages (user and assistant with content)
        all_messages = state.conversation
        total_messages = len(all_messages)
        total_pages = (total_messages + CONVERSATION_PAGE_SIZE - 1) // CONVERSATION_PAGE_SIZE

        if total_messages == 0:
            return {
                "session_id": session_id,
                "messages": [],
                "page_info": {
                    "total_messages": 0,
                    "total_pages": 0,
                    "page_size": CONVERSATION_PAGE_SIZE,
                    "pages_returned": 0,
                    "offset": offset,
                },
            }

        # Calculate which messages to return using reverse pagination
        # offset=0 means start from the end, offset=1 means skip 1 page from end, etc.
        messages_to_skip_from_end = offset * CONVERSATION_PAGE_SIZE
        messages_to_take = pages * CONVERSATION_PAGE_SIZE

        # Calculate start and end indices
        # We're working backwards from the end
        end_index = total_messages - messages_to_skip_from_end
        start_index = max(0, end_index - messages_to_take)

        # Handle edge cases
        if end_index <= 0:
            return {
                "session_id": session_id,
                "messages": [],
                "page_info": {
                    "total_messages": total_messages,
                    "total_pages": total_pages,
                    "page_size": CONVERSATION_PAGE_SIZE,
                    "pages_returned": 0,
                    "offset": offset,
                    "note": f"Offset {offset} is beyond available messages",
                },
            }

        # Slice messages (already in chronological order)
        selected_messages = all_messages[start_index:end_index]

        # Convert to dicts
        message_dicts = [msg.to_dict() for msg in selected_messages]

        # Calculate actual pages returned
        pages_returned = (len(selected_messages) + CONVERSATION_PAGE_SIZE - 1) // CONVERSATION_PAGE_SIZE

        return {
            "session_id": session_id,
            "messages": message_dicts,
            "page_info": {
                "total_messages": total_messages,
                "total_pages": total_pages,
                "page_size": CONVERSATION_PAGE_SIZE,
                "pages_returned": pages_returned,
                "messages_returned": len(selected_messages),
                "offset": offset,
                "start_index": start_index,
                "end_index": end_index,
            },
        }
