from typing import Generator, Dict, List, Self

from alayaflow.utils.singleton import SingletonMeta
from alayaflow.workflow import WorkflowManager
from alayaflow.execution import ExecutorManager, ExecutorType
from alayaflow.common.config import settings


class APISingleton(metaclass=SingletonMeta):
    def __init__(self) -> None:
        self.workflow_manager = WorkflowManager()
        self.executor_manager = ExecutorManager(
            workflow_manager=self.workflow_manager
        )
        self._inited = False                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    

    def is_inited(self) -> bool:
        return self._inited

    def _check_init(self) -> None:
        if not self._inited:
            raise ValueError("Flow APISingleton 未初始化，请先调用 init 方法")

    def init(self, config: dict = {}) -> Self:
        """初始化 Flow APISingleton"""
        # Overwrite all for now
        settings.alayahub_url = config.get("alayahub_url", settings.alayahub_url)
        settings.langfuse_enabled = config.get("langfuse_enabled", settings.langfuse_enabled)
        settings.langfuse_public_key = config.get("langfuse_public_key", settings.langfuse_public_key)
        settings.langfuse_secret_key = config.get("langfuse_secret_key", settings.langfuse_secret_key)
        settings.langfuse_url = config.get("langfuse_url", settings.langfuse_url)
        self._inited = True
        return self

    def list_loaded_workflow_ids(self) -> List[str]:
        """列举已加载的工作流"""
        self._check_init()
        return self.workflow_manager.list_loaded_workflow_ids()

    def list_available_workflows(self) -> Dict[str, List[str]]:
        """列举工作流，分别返回本地已安装和远程未安装的工作流"""
        self._check_init()
        return self.workflow_manager.list_available_workflows()

    def get_workflow_info(self, workflow_id: str) -> dict:
        """获取工作流信息"""
        self._check_init()
        return self.workflow_manager.get_workflow_info(workflow_id)

    def install_workflow(self, workflow_id: str) -> bool:
        """安装工作流"""
        self._check_init()
        return self.workflow_manager.install_workflow(workflow_id)

    def uninstall_workflow(self, workflow_id: str) -> bool:
        """卸载工作流"""
        self._check_init()
        return self.workflow_manager.uninstall_workflow(workflow_id)

    def load_workflow(self, workflow_id: str, version: str, init_args: dict = {}):
        """加载工作流"""
        self._check_init()
        return self.workflow_manager.load_workflow(workflow_id, version, init_args)

    def exec_workflow(
        self,
        workflow_id: str,
        version: str,
        input_data: dict,
        user_config: dict,
        executor_type: str | ExecutorType = ExecutorType.NAIVE
    ) -> Generator[dict, None, None]:
        """执行工作流"""
        self._check_init()
        yield from self.executor_manager.exec_workflow(
            workflow_id=workflow_id,
            version=version,
            input_data=input_data,
            user_config=user_config,
            executor_type=executor_type
        )
