import asyncio
from contextlib import asynccontextmanager

from fastapi import FastAPI

# urllib3-future 覆盖 urllib3 命名空间后删除了 format_header_param，导致 telebot 崩溃，需在加载模块前打补丁
try:
    import urllib3.fields as _urllib3_fields

    if not hasattr(_urllib3_fields, "format_header_param") and hasattr(
        _urllib3_fields, "format_header_param_rfc2231"
    ):
        _urllib3_fields.format_header_param = (
            _urllib3_fields.format_header_param_rfc2231
        )
except Exception:
    pass

from app.chain.system import SystemChain
from app.core.config import global_vars
from app.helper.server import MoviePilotServerHelper
from app.helper.system import SystemHelper
from app.startup.command_initializer import init_command, stop_command, restart_command
from app.startup.modules_initializer import init_modules, stop_modules
from app.startup.monitor_initializer import stop_monitor, init_monitor
from app.startup.plugins_initializer import init_plugins, stop_plugins, sync_plugins
from app.startup.routers_initializer import init_routers
from app.startup.scheduler_initializer import (
    stop_scheduler,
    init_scheduler,
    init_plugin_scheduler,
)
from app.startup.workflow_initializer import init_workflow, stop_workflow
from app.utils.http import aclose_shared_async_transports


async def init_extra():
    """
    同步插件及重启相关依赖服务
    """
    if await sync_plugins():
        # 重新注册插件定时服务
        init_plugin_scheduler()
        # 重新注册命令
        restart_command()
    # 设置系统已修改标志
    SystemHelper().set_system_modified()
    # 重启完成
    SystemChain().restart_finish()
    # 上报当前安装版本
    await MoviePilotServerHelper.async_report_usage()


@asynccontextmanager
async def lifespan(app: FastAPI):
    """
    定义应用的生命周期事件
    """
    print("Starting up...")
    # 存储当前循环
    global_vars.set_loop(asyncio.get_event_loop())
    # 初始化路由
    init_routers(app)
    # 初始化模块
    init_modules()
    # 恢复插件备份
    SystemChain().restore_plugins()
    # 初始化插件
    init_plugins()
    # 初始化定时器
    init_scheduler()
    # 初始化监控器
    init_monitor()
    # 初始化命令
    init_command()
    # 初始化工作流
    init_workflow()
    # 插件同步到本地
    sync_plugins_task = asyncio.create_task(init_extra())
    try:
        # 在此处 yield，表示应用已经启动，控制权交回 FastAPI 主事件循环
        yield
    finally:
        print("Shutting down...")
        # 取消同步插件任务
        try:
            sync_plugins_task.cancel()
            await sync_plugins_task
        except asyncio.CancelledError:
            pass
        except Exception as e:
            print(str(e))
        # 备份插件
        SystemChain().backup_plugins()
        # 停止工作流
        stop_workflow()
        # 停止命令
        stop_command()
        # 停止监控器
        stop_monitor()
        # 停止定时器
        stop_scheduler()
        # 停止插件
        stop_plugins()
        # 停止模块
        await stop_modules()
        # 关闭共享的异步 HTTP 连接池，释放底层连接资源
        await aclose_shared_async_transports()
