from pprint import pformat
from typing import Any

from arbol import aprint

from litemind.agent.tools.base_tool import BaseTool
from litemind.agent.tools.callbacks.base_tool_callbacks import BaseToolCallbacks


class PrintApiCallbacks(BaseToolCallbacks):
    """Tool callback that prints execution details to the console via Arbol.

    Useful for debugging and monitoring tool usage. Each lifecycle event
    (start, activity, end, error) can be independently enabled or disabled.
    """

    def __init__(
        self,
        print_on_tool_start: bool = False,
        print_on_tool_activity: bool = False,
        print_on_tool_end: bool = False,
        print_on_tool_error: bool = True,
        **kwargs,
    ):
        """
        Initialize the callback with per-event printing controls.

        Parameters
        ----------
        print_on_tool_start : bool
            Whether to print when a tool starts execution.
        print_on_tool_activity : bool
            Whether to print when a tool reports intermediate activity.
        print_on_tool_end : bool
            Whether to print when a tool finishes execution.
        print_on_tool_error : bool
            Whether to print when a tool encounters an error.
        **kwargs
            Rejected; raises ValueError if any unknown arguments are passed.

        Raises
        ------
        ValueError
            If unknown keyword arguments are provided.
        """
        super().__init__()

        # Set the printing options based on the provided parameters:
        self.print_on_tool_start = print_on_tool_start
        self.print_on_tool_activity = print_on_tool_activity
        self.print_on_tool_end = print_on_tool_end
        self.print_on_tool_error = print_on_tool_error

        if kwargs:
            raise ValueError(f"Unknown arguments: {pformat(kwargs)}")

    def on_tool_start(self, tool: BaseTool, *args, **kwargs) -> None:
        aprint(f"Tool Start: {tool.name} with args: {args} and kwargs: {kwargs}")

    def on_tool_activity(self, tool: "BaseTool", activity_type: str, **kwargs) -> Any:
        aprint(f"Tool Activity: {tool.name} is {activity_type} with info: {kwargs}")

    def on_tool_end(self, tool: BaseTool, result: Any) -> None:
        aprint(f"Tool End: {tool.name} with result: {result}")

    def on_tool_error(self, tool: BaseTool, exception: Exception) -> None:
        aprint(f"Tool Error: {tool.name} with exception: {exception}")
