import importlib.util
import os
import inspect

moduleMap = {}

def loadModule(moduleName):
    modulesLocation = os.path.dirname(os.path.realpath(__file__))
    modulePath = os.path.join(modulesLocation, moduleName, "main.py")

    if not os.path.exists(modulePath):
        raise Exception(f"Module {moduleName} not found")

    spec = importlib.util.spec_from_file_location(
        f"omnis_module_{moduleName}",
        modulePath
    )
    module = importlib.util.module_from_spec(spec)
    spec.loader.exec_module(module)
    return module


async def call(module, method, params, response):
    if module not in moduleMap:
        moduleMap[module] = loadModule(module)

    mod = moduleMap[module]

    if not hasattr(mod, method):
        raise AttributeError(
            f"Method '{method}' not found in module '{module}'"
        )

    func = getattr(mod, method)
    sig = inspect.signature(func)

    if len(sig.parameters) != 2:
        raise TypeError(
            f"Method '{method}' in module '{module}' must accept 2 parameters"
        )

    result = func(params, response)

    if inspect.iscoroutine(result):
        result = await result

    return result
