"""Standalone Runner - 自动发现并启动配置驱动的 Agent

扫描 agent_configs/ 目录下的 YAML 文件，自动注册和启动 Agent。
支持命令行启动：python -m agentkit.core.standalone
"""

import asyncio
import logging
import os
import sys
from pathlib import Path

import yaml

from agentkit.core.config_driven import AgentConfig, ConfigDrivenAgent
from agentkit.tools.function_tool import FunctionTool
from agentkit.tools.registry import ToolRegistry

logger = logging.getLogger(__name__)

DEFAULT_CONFIG_DIR = "agent_configs"


class StandaloneRunner:
    """自动发现并启动配置驱动的 Agent

    用法::

        runner = StandaloneRunner(config_dir="agent_configs")
        runner.add_tool(FunctionTool.from_func(my_tool_func))
        await runner.start_all(redis_url="redis://localhost:6379")
    """

    def __init__(
        self,
        config_dir: str = DEFAULT_CONFIG_DIR,
        tool_registry: ToolRegistry | None = None,
        llm_client=None,
        custom_handlers: dict | None = None,
    ):
        self._config_dir = config_dir
        self._tool_registry = tool_registry or ToolRegistry()
        self._llm_client = llm_client
        self._custom_handlers = custom_handlers or {}
        self._agents: dict[str, ConfigDrivenAgent] = {}

    @property
    def agents(self) -> dict[str, ConfigDrivenAgent]:
        return self._agents

    def add_tool(self, tool) -> "StandaloneRunner":
        """添加工具到注册中心"""
        self._tool_registry.register(tool)
        return self

    def add_custom_handler(self, name: str, handler) -> "StandaloneRunner":
        """注册自定义 handler"""
        self._custom_handlers[name] = handler
        return self

    def discover_configs(self) -> list[AgentConfig]:
        """扫描配置目录，发现所有 YAML 配置"""
        configs = []
        config_path = Path(self._config_dir)

        if not config_path.exists():
            logger.warning(f"Config directory '{self._config_dir}' not found")
            return configs

        for yaml_file in sorted(config_path.glob("*.yaml")):
            try:
                config = AgentConfig.from_yaml(str(yaml_file))
                configs.append(config)
                logger.info(f"Discovered agent config: {config.name} from {yaml_file.name}")
            except Exception as e:
                logger.error(f"Failed to load config '{yaml_file}': {e}")

        for yml_file in sorted(config_path.glob("*.yml")):
            try:
                config = AgentConfig.from_yaml(str(yml_file))
                configs.append(config)
                logger.info(f"Discovered agent config: {config.name} from {yml_file.name}")
            except Exception as e:
                logger.error(f"Failed to load config '{yml_file}': {e}")

        return configs

    def build_agents(self) -> dict[str, ConfigDrivenAgent]:
        """从发现的配置构建 Agent 实例"""
        configs = self.discover_configs()
        self._agents.clear()

        for config in configs:
            try:
                agent = ConfigDrivenAgent(
                    config=config,
                    tool_registry=self._tool_registry,
                    llm_client=self._llm_client,
                    custom_handlers=self._custom_handlers,
                )
                self._agents[config.name] = agent
                logger.info(f"Built agent: {config.name} (mode={config.task_mode})")
            except Exception as e:
                logger.error(f"Failed to build agent '{config.name}': {e}")

        return self._agents

    async def start_all(self, redis_url: str = "") -> None:
        """启动所有已构建的 Agent"""
        if not self._agents:
            self.build_agents()

        for name, agent in self._agents.items():
            try:
                await agent.start(redis_url=redis_url)
                logger.info(f"Agent '{name}' started")
            except Exception as e:
                logger.error(f"Failed to start agent '{name}': {e}")

    async def stop_all(self) -> None:
        """停止所有 Agent"""
        for name, agent in self._agents.items():
            try:
                await agent.stop()
                logger.info(f"Agent '{name}' stopped")
            except Exception as e:
                logger.error(f"Failed to stop agent '{name}': {e}")

    async def execute_task(self, agent_name: str, task) -> dict | None:
        """在指定 Agent 上执行任务（本地模式）"""
        if agent_name not in self._agents:
            logger.error(f"Agent '{agent_name}' not found")
            return None

        agent = self._agents[agent_name]
        result = await agent.execute(task)
        return result.to_dict()


async def main():
    """命令行入口"""
    logging.basicConfig(
        level=logging.INFO,
        format="%(asctime)s [%(name)s] %(levelname)s: %(message)s",
    )

    config_dir = sys.argv[1] if len(sys.argv) > 1 else DEFAULT_CONFIG_DIR
    redis_url = os.environ.get("REDIS_URL", "")

    runner = StandaloneRunner(config_dir=config_dir)
    agents = runner.build_agents()

    if not agents:
        logger.error("No agents discovered. Check your config directory.")
        sys.exit(1)

    logger.info(f"Discovered {len(agents)} agent(s): {list(agents.keys())}")

    try:
        await runner.start_all(redis_url=redis_url)
        logger.info("All agents started. Press Ctrl+C to stop.")

        # 保持运行
        while True:
            await asyncio.sleep(1)
    except KeyboardInterrupt:
        logger.info("Shutting down...")
    finally:
        await runner.stop_all()


if __name__ == "__main__":
    asyncio.run(main())
