"""Bookmarks mixin for MCGhidra.

Provides tools for managing Ghidra bookmarks (annotations at addresses).
"""

from typing import Any, Dict, List, Optional

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

from ..config import get_config
from .base import MCGhidraMixinBase


class BookmarksMixin(MCGhidraMixinBase):
    """Mixin for bookmark operations.

    Provides tools for:
    - Listing bookmarks with type/category filtering
    - Creating bookmarks at addresses
    - Deleting bookmarks
    """

    @mcp_tool()
    def bookmarks_list(
        self,
        type: Optional[str] = None,
        category: Optional[str] = None,
        port: Optional[int] = None,
        page_size: int = 50,
        grep: Optional[str] = None,
        grep_ignorecase: bool = True,
        return_all: bool = False,
        fields: Optional[List[str]] = None,
        ctx: Optional[Context] = None,
    ) -> Dict[str, Any]:
        """List bookmarks with optional type/category filtering.

        Args:
            type: Filter by bookmark type (e.g. "Note", "Warning", "Error", "Info")
            category: Filter by bookmark category
            port: Ghidra instance port (optional)
            page_size: Bookmarks per page (default: 50, max: 500)
            grep: Regex pattern to filter bookmark comments
            grep_ignorecase: Case-insensitive grep (default: True)
            return_all: Return all bookmarks without pagination
            fields: Field names to keep (e.g. ['address', 'type', 'comment']). Reduces response size.
            ctx: FastMCP context (auto-injected)

        Returns:
            Paginated list of bookmarks
        """
        try:
            port = self.get_instance_port(port)
        except ValueError as e:
            return {"success": False, "error": {"code": "NO_INSTANCE", "message": str(e)}}

        config = get_config()
        cap = config.resource_caps.get("bookmarks", 1000)
        params: Dict[str, Any] = {"limit": cap}
        if type:
            params["type"] = type
        if category:
            params["category"] = category

        response = self.safe_get(port, "bookmarks", params)
        simplified = self.simplify_response(response)

        if not simplified.get("success", True):
            return simplified

        bookmarks = simplified.get("result", [])
        if not isinstance(bookmarks, list):
            bookmarks = []

        query_params = {
            "tool": "bookmarks_list",
            "port": port,
            "type": type,
            "category": category,
            "grep": grep,
        }
        session_id = self._get_session_id(ctx)

        return self.filtered_paginate(
            data=bookmarks,
            query_params=query_params,
            tool_name="bookmarks_list",
            session_id=session_id,
            page_size=min(page_size, config.max_page_size),
            grep=grep,
            grep_ignorecase=grep_ignorecase,
            return_all=return_all,
            fields=fields,
        )

    @mcp_tool()
    def bookmarks_create(
        self,
        address: str,
        type: str = "Note",
        category: str = "",
        comment: str = "",
        port: Optional[int] = None,
    ) -> Dict[str, Any]:
        """Create a bookmark at the specified address.

        Args:
            address: Memory address in hex format
            type: Bookmark type (default: "Note"). Common types: Note, Warning, Error, Info
            category: Bookmark category (optional grouping string)
            comment: Bookmark comment text
            port: Ghidra instance port (optional)

        Returns:
            Created bookmark information
        """
        if not address:
            return {
                "success": False,
                "error": {
                    "code": "MISSING_PARAMETER",
                    "message": "address parameter is required",
                },
            }

        try:
            port = self.get_instance_port(port)
        except ValueError as e:
            return {"success": False, "error": {"code": "NO_INSTANCE", "message": str(e)}}

        payload = {
            "address": address,
            "type": type,
            "category": category,
            "comment": comment,
        }
        response = self.safe_post(port, "bookmarks", payload)
        return self.simplify_response(response)

    @mcp_tool()
    def bookmarks_delete(
        self,
        address: str,
        port: Optional[int] = None,
    ) -> Dict[str, Any]:
        """Delete all bookmarks at the specified address.

        Args:
            address: Memory address in hex format
            port: Ghidra instance port (optional)

        Returns:
            Operation result
        """
        if not address:
            return {
                "success": False,
                "error": {
                    "code": "MISSING_PARAMETER",
                    "message": "address parameter is required",
                },
            }

        try:
            port = self.get_instance_port(port)
        except ValueError as e:
            return {"success": False, "error": {"code": "NO_INSTANCE", "message": str(e)}}

        response = self.safe_delete(port, f"bookmarks/{address}")
        return self.simplify_response(response)
