import requests
import logging
from ..utils import parse_json_string, PREFIX_FOR_ERROR_OBSERVATION

logger = logging.getLogger(__name__)

def execute_tool_action(action_data: str, tools: list, raise_on_error: bool = True):
    """
    Parse and execute an LLM-generated JSON tool action.

    Args:
        action_data (str): The raw JSON string generated by the model.
        tools (list): A list of available tool instances (BaseTool subclasses).

    Returns:
        Any: The tool's output (the observation).
    """
    # --- 1. Parse JSON safely ---
    logger.debug(f"Raw action data: {action_data}")
    parsed_action, feedback = parse_json_string(action_data)
    logger.debug(f"Parsed action data: {parsed_action}")
    if parsed_action is None:
        assert feedback is not None
        return f"{PREFIX_FOR_ERROR_OBSERVATION}{feedback}"

    # --- 2. Validate required fields ---
    if "action" not in parsed_action or "action_input" not in parsed_action:
        # raise ValueError(f"Invalid tool call format: {parsed_action}")
        return f"{PREFIX_FOR_ERROR_OBSERVATION}Invalid tool call format: missing 'action' or/and 'action_input'."

    tool_name = parsed_action["action"]
    action_input = parsed_action["action_input"]

    # --- 3. Find tool by name ---
    tool = next((t for t in tools if t.name == tool_name), None)
    if tool is None:
        raise ValueError(f"No tool found with name '{tool_name}'")

    # --- 4. Execute tool ---
    try:
        # Handle empty string or non-dict action_input
        if isinstance(action_input, str) and action_input.strip() == "":
            action_input = {}
            
        if hasattr(tool, "_run"):
            result = tool._run(**action_input)
        elif hasattr(tool, "__call__"):
            result = tool(**action_input)
        else:
            raise AttributeError(f"Tool {tool_name} has no callable method.")
    except Exception as e:
        
        # raise RuntimeError(f"Error executing tool '{tool_name}': {e}")
        return f"{PREFIX_FOR_ERROR_OBSERVATION}'{tool_name}': {e}"

    if raise_on_error:
        if isinstance(result, str) and "ConnectTimeoutError" in result:
            raise Exception(f"Network issue or server-side error: {result}")
            exit()
        if isinstance(result, str) and " HTTPConnectionPool" in result:
            raise Exception(f"Network issue or server-side error: {result}")
            exit()

    # --- 5. Return observation ---
    return result

def inspect_toolkit(tools):
    for tool in tools:
        inspect_tool(tool)
        
def inspect_tool(tool):
    print("Type: ", type(tool))
    print("Name:", tool.name) # multiply
    print("Description:", tool.description) # Multiply two numbers.
    print("Args:", tool.args)
    print("\n")
    
def test_connection():
    # find_nearby = NearbyPlacesTool(client=client)
    # find_nearby.invoke({"placeId": "0", "type": "accounting" })
    # run the following command to find the Bearer token:
    # curl -X POST http://10.224.245.233:5000/api/login -H "Content-Type: application/json" -d '{"username": "test", "password": "123"}'
    url = "http://10.224.245.233:5000/api"+"/map/nearby"
    headers = {
        "Authorization": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InRlc3QiLCJpc3MiOiJtYXBxdWVzdC1hcHAub25yZW5kZXIuY29tIiwiaWF0IjoxNzU5OTk4NzUyfQ.ss23UkIzD73vogcFoRoUG1GrBAfFTOB0_H2CAS6Q-Z0"
    }
            
    params = {
        "location": 0,
        "radius": None,
        "type": "accounting",
        "keyword": None,
        "rankby": "distance"
    }
    response = requests.get(url, headers=headers, params=params)
    print(response)