from typing import Generator, Dict, List, Self, Optional, AsyncGenerator

from alayaflow.utils.singleton import SingletonMeta
from alayaflow.workflow import WorkflowManager
from alayaflow.execution import ExecutorManager, ExecutorType
from alayaflow.common.config import settings
from alayaflow.component.model import ModelManager, ModelProfile
from alayaflow.workflow.runnable import BaseRunnableWorkflow
from alayaflow.utils.logger import AlayaFlowLogger


logger = AlayaFlowLogger()


class APISingleton(metaclass=SingletonMeta):
    def __init__(self) -> None:
        self.workflow_manager = WorkflowManager()
        self.executor_manager = ExecutorManager(
            workflow_manager=self.workflow_manager
        )
        self.model_manager = ModelManager()
        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 = None) -> Self:
        """初始化 Flow APISingleton"""
        if config is None:
            config = {}
        # 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_base_url = config.get("langfus_base_url", settings.langfuse_base_url)

        logger.info(f"AlayaFlow is initialized with config: {settings.model_dump()}")
        
        self._inited = True
        return self

    def register_models(self, model_profiles: List[dict | ModelProfile]) -> None:
        self._check_init()
        profiles = [ModelProfile(**profile) if isinstance(profile, dict) else profile for profile in model_profiles]
        for profile in profiles:
            self.model_manager.register_profile(profile)

    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: Optional[Dict] = None, workflow_dir: Optional[str] = None) -> None:
        """加载本地工作流"""
        self._check_init()
        return self.workflow_manager.load_workflow(workflow_id, version, init_args or {}, workflow_dir)

    def register_workflow(self, runnable: BaseRunnableWorkflow, requirements: List[str] = None) -> None:
        """加载Python项目中的工作流"""
        self._check_init()
        self.workflow_manager.register_workflow(runnable, requirements or [])

    def exec_workflow(
        self,
        workflow_id: str,
        version: str,
        inputs: dict,
        context: dict,
        executor_type: str | ExecutorType = ExecutorType.NAIVE,
        metadata: dict = None
    ) -> Generator[dict, None, None]:
        """执行工作流"""
        self._check_init()
        for event in self.executor_manager.exec_workflow(
            workflow_id=workflow_id,
            version=version,
            inputs=inputs,
            context=context,
            executor_type=executor_type,
            metadata=metadata
        ):
            yield event

    async def exec_workflow_async(
        self,
        workflow_id: str,
        version: str,
        inputs: dict,
        context: dict,
        executor_type: str | ExecutorType = ExecutorType.NAIVE,
        metadata: dict = None
    ) -> AsyncGenerator[dict, None]:
        """异步执行工作流"""
        self._check_init()
        async for event in self.executor_manager.exec_workflow_async(
            workflow_id=workflow_id,
            version=version,
            inputs=inputs,
            context=context,
            executor_type=executor_type,
            metadata=metadata
        ):
            yield event
