import inspect
from instaui.internal.backend.common.response import response_data
from .watch_handler import get_watch_handler
from .event_handler import get_event_handler
from .async_executor import AsyncExecutor


class Api:
    def __init__(self) -> None:
        self._async_executor = AsyncExecutor()

    def watch_call(self, data: dict):
        hkey = data.pop("hKey")
        handler = get_watch_handler(hkey)
        if handler is None:
            return {"error": "watch handler not found"}

        exec_result = handler.fn(*handler.get_handler_args(_get_binds_from_data(data)))

        if inspect.iscoroutinefunction(handler.fn):
            result = self._async_executor.run(exec_result)
        else:
            result = exec_result
        return response_data(handler.outputs_binding_count, result)

    def event_call(self, data: dict):
        hkey = data.pop("hKey")
        handler = get_event_handler(hkey)
        if handler is None:
            raise ValueError("event handler not found")

        args = [bind for bind in data.get("bind", [])]

        exec_result = handler.fn(*handler.get_handler_args(args))

        if inspect.iscoroutinefunction(handler.fn):
            result = self._async_executor.run(exec_result)
        else:
            result = exec_result

        return response_data(handler.outputs_binding_count, result)


def _get_binds_from_data(data: dict):
    return data.get("input", [])
