"""Cursor management mixin for MCGhidra.

Provides tools for managing pagination cursors.
"""

from typing import Any, Dict, Optional

from fastmcp import Context
from fastmcp.contrib.mcp_mixin import mcp_tool

from ..core.pagination import get_cursor_manager
from .base import MCGhidraMixinBase


class CursorsMixin(MCGhidraMixinBase):
    """Mixin for cursor management.

    Provides tools for navigating paginated results.
    """

    @mcp_tool()
    def cursor_next(
        self, cursor_id: str, ctx: Optional[Context] = None
    ) -> Dict[str, Any]:
        """Get the next page of results for a cursor.

        Args:
            cursor_id: The cursor identifier from a previous paginated response
            ctx: FastMCP context (auto-injected)

        Returns:
            Next page of results with updated pagination info
        """
        session_id = self._get_session_id(ctx)
        cursor_manager = get_cursor_manager()

        # Get and advance cursor
        state = cursor_manager.get_cursor(cursor_id, session_id)
        if not state:
            return {
                "success": False,
                "error": {
                    "code": "CURSOR_NOT_FOUND",
                    "message": f"Cursor '{cursor_id}' not found or expired. "
                    "Cursors expire after 5 minutes of inactivity.",
                },
            }

        # Advance to next page
        state = cursor_manager.advance_cursor(cursor_id, session_id)
        if not state:
            return {
                "success": False,
                "error": {
                    "code": "CURSOR_ADVANCE_FAILED",
                    "message": "Failed to advance cursor",
                },
            }

        current_page = cursor_manager.get_page(state)
        response_cursor = cursor_id if state.has_more else None

        response = {
            "success": True,
            "result": current_page,
            "pagination": {
                "cursor_id": response_cursor,
                "session_id": session_id,
                "total_count": state.total_count,
                "filtered_count": state.filtered_count,
                "page_size": state.page_size,
                "current_page": state.current_page,
                "total_pages": state.total_pages,
                "has_more": state.has_more,
                "grep_pattern": state.grep_pattern,
                "items_returned": len(current_page),
            },
        }

        if state.has_more:
            remaining = state.filtered_count - (state.current_page * state.page_size)
            response["_message"] = (
                f"Showing {len(current_page)} of {state.filtered_count} items "
                f"(page {state.current_page}/{state.total_pages}). "
                f"To get the next {min(state.page_size, remaining)} items, call: "
                f"cursor_next(cursor_id='{cursor_id}')"
            )
        else:
            response["_message"] = (
                f"Complete: {len(current_page)} items returned (final page)"
            )

        return response

    @mcp_tool()
    def cursor_list(
        self, ctx: Optional[Context] = None, all_sessions: bool = False
    ) -> Dict[str, Any]:
        """List active cursors for the current session.

        Args:
            ctx: FastMCP context (auto-injected)
            all_sessions: Include cursors from all sessions (admin only)

        Returns:
            List of active cursors with their status
        """
        session_id = self._get_session_id(ctx)
        cursor_manager = get_cursor_manager()

        if all_sessions:
            cursors = cursor_manager.list_cursors()
        else:
            cursors = cursor_manager.list_cursors(session_id)

        return {
            "success": True,
            "cursors": cursors,
            "session_id": session_id,
            "count": len(cursors),
        }

    @mcp_tool()
    def cursor_delete(
        self, cursor_id: str, ctx: Optional[Context] = None
    ) -> Dict[str, Any]:
        """Delete a specific cursor.

        Args:
            cursor_id: The cursor identifier to delete
            ctx: FastMCP context (auto-injected)

        Returns:
            Confirmation of deletion
        """
        session_id = self._get_session_id(ctx)
        cursor_manager = get_cursor_manager()

        deleted = cursor_manager.delete_cursor(cursor_id, session_id)

        if deleted:
            return {
                "success": True,
                "message": f"Cursor '{cursor_id}' deleted",
            }
        else:
            return {
                "success": False,
                "error": {
                    "code": "CURSOR_NOT_FOUND",
                    "message": f"Cursor '{cursor_id}' not found or belongs to another session",
                },
            }

    @mcp_tool()
    def cursor_delete_all(self, ctx: Optional[Context] = None) -> Dict[str, Any]:
        """Delete all cursors for the current session.

        Args:
            ctx: FastMCP context (auto-injected)

        Returns:
            Number of cursors deleted
        """
        session_id = self._get_session_id(ctx)
        cursor_manager = get_cursor_manager()

        count = cursor_manager.delete_session_cursors(session_id)

        return {
            "success": True,
            "message": f"Deleted {count} cursor(s) for session",
            "deleted_count": count,
        }
