import types
from typing import Callable
from openai_wrapper import OpenAI
import json
import inspect
from ez_openai.decorator import _openai_type_for_python_type

client = OpenAI()

def get_horoscope(sign):
    return f"{sign}: Next Tuesday you will befriend a baby otter."

# 1. Define a list of callable tools for the model
def test(func: Callable | types.FunctionType):
    descriptions: dict[str, str] = {}
    arguments = {}
    required_arguments = []
    sig = inspect.signature(func)
    for params in sig.parameters:
        descriptions[params] = params

    for param in sig.parameters.values():
        if param.annotation == inspect.Parameter.empty:
            raise ValueError(
                f"Parameter is untyped: {func.__name__}({param.name})")

        if param.name not in descriptions:  # type: ignore
            raise ValueError(
                f"Parameter has no description: {func.__name__}({param.name})"
            )

        arguments[param.name] = _openai_type_for_python_type(param)
        if param.name in descriptions:
            arguments[param.name]["description"] = descriptions[param.name]
        if param.default == inspect.Parameter.empty:
            required_arguments.append(param.name)

    fn_dict = {
        "type": "function",
        "function": {
            "name": func.__name__,
            "description": (func.__doc__ or "").strip(),
            "parameters": {
                "type": "object",
                "required": required_arguments,
                "properties": arguments,
            },
        },
    }
    tools = [
        {
            "type": "function",
            "name": func.__name__,
            "description": func.__doc__.strip() if func.__doc__ else "".strip(),
            "parameters": {
                "type": "object",
                "properties": {
                    "sign": {
                        "type": "string",
                        "description": "An astrological sign like Taurus or Aquarius",
                    },
                },
                "required": ["sign"],
            },
        },
    ]


    # Create a running input list we will add to over time
    input_list = [
        {"role": "user", "content": "What is my horoscope? I am an Aquarius."}
    ]

    # 2. Prompt the model with tools defined
    response = client.responses.create(
        model="gpt-5",
        tools=fn_dict, # type: ignore
        input=input_list, # type: ignore
    )
    
    input_list += response.output
    
    for item in response.output:
        if item.type == "function_call":
            bob = func(json.loads(item.arguments))
            
            input_list.append({
                "type": "function_call_output",
                "call_id": item.call_id,
                func.__name__: json.dumps({func.__name__: bob})
            })
            
            return

# if __name__ == "__main__":
#     # Save function call outputs for subsequent requests
#     input_list += response.output

#     for item in response.output:
#         if item.type == "function_call":
#             if item.name == "get_horoscope":
#                 # 3. Execute the function logic for get_horoscope
#                 horoscope = get_horoscope(json.loads(item.arguments))
                
#                 # 4. Provide function call results to the model
#                 input_list.append({
#                     "type": "function_call_output",
#                     "call_id": item.call_id,
#                     "output": json.dumps({
#                     "horoscope": horoscope
#                     })
#                 })

#     print("Final input:")
#     print(input_list)

#     response = client.responses.create(
#         model="gpt-5",
#         instructions="Respond only with a horoscope generated by a tool.",
#         tools=tools, # type: ignore
#         input=input_list, # pyright: ignore[reportArgumentType]
#     )

#     # 5. The model should be able to give a response!
#     print("Final output:")
#     print(response.model_dump_json(indent=2))
#     print("\n" + response.output_text)