import asyncio
import signal
import platform
import os
from typing import Type

from setproctitle import setproctitle

from ldnode import logger
from .config import Settings
from .context import Context
from .schemas import Service
from .task_manager import TaskManager


def setup_exit_handlers(runner: "Runner"):
    """ 设置异步信号处理器 """
    loop = asyncio.get_running_loop()

    def signal_handler(sig = None):
        logger.runner.info(f"Received signal {signal.Signals(sig).name}")
        asyncio.create_task(runner.shutdown())

    for sig in [signal.SIGINT, signal.SIGTERM]:
        try:
            loop.add_signal_handler(sig, lambda s=sig: signal_handler(s))
        except NotImplementedError:
            # Windows 可能不支持 add_signal_handler
            signal.signal(sig, lambda s, f: asyncio.create_task(runner.shutdown()))
            

class Runner:
    """ 运行器 """
    @classmethod
    async def build(cls, version: str, settings: Settings, *service_classes: list[Type[Service]]):
        """ 构建运行器 """
        os.environ['POLARS_MAX_THREADS'] = str(settings.POLARS_MAX_THREADS)
        settings.NODE_VERSION = version
        settings.PLATFORM_TAG = platform.platform()
        runner = cls(version, settings, *service_classes)
        setup_exit_handlers(runner)
        await runner.run()
    
    def __init__(self, version: str, settings: Settings, *service_classes: list[Type[Service]]):
        self.context = Context(settings)
        self.tasks = TaskManager()
        self.exit_flag = asyncio.Event()
        self.version = version
        self.settings = settings
        self.services: dict[str, Service] = self.create_services(service_classes)
        
    def create_services(self, service_classes: list[Type[Service]]):
        """ 创建服务 """
        services: dict[str, Service] = {}
        for service_cls in service_classes:
            # 创建服务
            service = service_cls(self.settings, self.context)
            service_name = service.__class__.__name__
            services[service_name] = service
            # 注册事件处理函数
            handle_methods = [
                getattr(service, method) for method in dir(service) 
                if hasattr(getattr(service, method), "__annotations__") and "on_ev" in getattr(service, method).__annotations__
            ]
            for method in handle_methods:
                event = method.__annotations__["on_ev"]
                self.context.register_event_handler(event, method)
        return services
        
    async def shutdown(self):
        """ 优雅关闭 """
        # 关闭上下文关闭
        await self.context.notify_shutdown()
        # 关闭服务
        for service in self.services.values():
            await service.shutdown()
        # 等待所有任务完成
        await self.tasks.wait_all()
        # 设置退出标志
        self.exit_flag.set()

    async def run(self):
        """ 运行 """
        setproctitle("lude-node:main")
        self.running = True
        # 启动服务
        for service in self.services.values():
            self.tasks.create_task(service.start())
        # 保持工作进程存活
        self.tasks.create_task(self.context.keep_alive())
        # 事件循环
        self.tasks.create_task(self.context.event_loop())
        # 等待退出
        await self.exit_flag.wait()
        # 打招呼
        logger.runner.info("Bye~")
