from typing import Any, Callable, List

import uvicorn

from algo_backend.config import ServiceConfig
from algo_backend.metrics import PrometheusContext


class DefaultAlgoServiceStarter:
    """
    主线程的设置
    uvicorn容器启动fastapi
    """

    def __init__(self, service_name: str):
        self.service_name = service_name
        self.__main_pid_event: List[Callable[[], Any]] = []
        self.init_events()

    def init_events(self):
        # 初始化prometheus多进程的设置
        self.append_event(PrometheusContext.init)
        return self

    def append_event(self, func: Callable[[], Any]):
        """尾部插入事件"""
        self.__main_pid_event.append(func)
        return self

    def insert_event(self, func: Callable[[], Any], index: int = 0):
        """任意位置插入事件"""
        self.__main_pid_event.insert(index, func)
        return self

    def use_loguru(self):
        """
        使用loguru日志设置，对主进程的日志生效
        注册loguru的定时清理器
        """
        from algo_backend.log.loguru import LoguruStarter

        loguru_stater = LoguruStarter(service_name=self.service_name)
        self.insert_event(loguru_stater.setup_log)
        self.append_event(loguru_stater.run_log_cleaner)
        return self

    def main_pid_setup(self) -> "DefaultAlgoServiceStarter":
        """
        主进程中的设置事件
        """
        for func in self.__main_pid_event:
            func()
        return self

    @classmethod
    def run(
        cls,
        app_str: str = "app.backend.application:app",
        host: str = "0.0.0.0",
        **kwargs,
    ):
        # 启动服务
        uvicorn.run(
            app_str,
            host=host,
            port=ServiceConfig.HTTP_PORT,
            timeout_keep_alive=ServiceConfig.TIMEOUT_KEEP_ALIVE,
            workers=ServiceConfig.PROCESS_NUM,
            **kwargs,
        )
