import json
from collections.abc import Callable
from typing import Any


def find_function(datasource: list[Callable], name: str) -> Callable | None:
    """Find a function in the datasource by name.

    Args:
        datasource: List of functions to search
        name: Name of the function to find

    Returns:
        The function if found, None otherwise
    """
    for func in datasource:
        if func.__name__ == name:
            return func
    return None


def try_execute_tool(func: Callable, args: Any) -> tuple[Any, str | None]:
    """Execute a tool function with error handling.

    Args:
        func: The function to execute
        args: Arguments to pass (dict or single value)

    Returns:
        Tuple of (result, error_message). If successful, error_message is None.
    """
    try:
        result = func(**args) if isinstance(args, dict) else func(args)
        return json.dumps(result) if isinstance(result, dict) else str(result), None
    except Exception as e:
        return None, repr(e)


def ensure_json_serializable(value: Any) -> Any:
    """Ensure a value is JSON-serializable.

    Args:
        value: Value to check/convert

    Returns:
        JSON-serializable version of the value
    """
    if value is None:
        return None

    try:
        import json

        json.dumps(value)
        return value
    except (TypeError, ValueError):
        return str(value)
