"""Data types mixin for MCGhidra.

Provides tools for managing enum and typedef data types.
"""

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 DataTypesMixin(MCGhidraMixinBase):
    """Mixin for enum and typedef data type operations.

    Provides tools for:
    - Listing and creating enum data types
    - Listing and creating typedef data types
    """

    # --- Enums ---

    @mcp_tool()
    def enums_list(
        self,
        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 enum data types with their members.

        Args:
            port: Ghidra instance port (optional)
            page_size: Enums per page (default: 50, max: 500)
            grep: Regex pattern to filter enum names
            grep_ignorecase: Case-insensitive grep (default: True)
            return_all: Return all enums without pagination
            fields: Field names to keep (e.g. ['name', 'size', 'members']). Reduces response size.
            ctx: FastMCP context (auto-injected)

        Returns:
            Paginated list of enum data types
        """
        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("enums", 500)
        response = self.safe_get(port, "datatypes/enums", {"limit": cap})
        simplified = self.simplify_response(response)

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

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

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

        return self.filtered_paginate(
            data=enums,
            query_params=query_params,
            tool_name="enums_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 enums_create(
        self,
        name: str,
        size: int = 4,
        port: Optional[int] = None,
    ) -> Dict[str, Any]:
        """Create a new enum data type.

        Args:
            name: Name for the new enum
            size: Size in bytes (default: 4)
            port: Ghidra instance port (optional)

        Returns:
            Created enum information
        """
        if not name:
            return {
                "success": False,
                "error": {
                    "code": "MISSING_PARAMETER",
                    "message": "name 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 = {"name": name, "size": size}
        response = self.safe_post(port, "datatypes/enums", payload)
        return self.simplify_response(response)

    # --- Typedefs ---

    @mcp_tool()
    def typedefs_list(
        self,
        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 typedef data types.

        Args:
            port: Ghidra instance port (optional)
            page_size: Typedefs per page (default: 50, max: 500)
            grep: Regex pattern to filter typedef names
            grep_ignorecase: Case-insensitive grep (default: True)
            return_all: Return all typedefs without pagination
            fields: Field names to keep (e.g. ['name', 'base_type']). Reduces response size.
            ctx: FastMCP context (auto-injected)

        Returns:
            Paginated list of typedef data types
        """
        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("typedefs", 500)
        response = self.safe_get(port, "datatypes/typedefs", {"limit": cap})
        simplified = self.simplify_response(response)

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

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

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

        return self.filtered_paginate(
            data=typedefs,
            query_params=query_params,
            tool_name="typedefs_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 typedefs_create(
        self,
        name: str,
        base_type: str,
        port: Optional[int] = None,
    ) -> Dict[str, Any]:
        """Create a new typedef data type.

        Args:
            name: Name for the new typedef
            base_type: Name of the base data type (e.g. "int", "uint32_t", "char*")
            port: Ghidra instance port (optional)

        Returns:
            Created typedef information
        """
        if not name:
            return {
                "success": False,
                "error": {
                    "code": "MISSING_PARAMETER",
                    "message": "name parameter is required",
                },
            }
        if not base_type:
            return {
                "success": False,
                "error": {
                    "code": "MISSING_PARAMETER",
                    "message": "base_type 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 = {"name": name, "base_type": base_type}
        response = self.safe_post(port, "datatypes/typedefs", payload)
        return self.simplify_response(response)
