import asyncio

from contextlib import asynccontextmanager

from fastapi import FastAPI, HTTPException

from algo.algo_runner import AlgoRunner
from algo.scene_runner import SceneRunner

from common.biz_exception import BizExceptionHandlers
from common.global_logger import logger
from db.database import get_db
from services.device_model_relation_service import DeviceModelRelationService
from services.device_scene_relation_service import DeviceSceneRelationService
from services.device_service import DeviceService
from services.global_config import GlobalConfig
from services.model_service import ModelService
from services.scene_service import SceneService
from services.schedule_job import start_scheduler
from tcp.tcp_manager import TcpManager
from tcp.tcp_server import start_server

_app = None  # 创建一个私有变量来存储 app 实例


def create_app() -> FastAPI:
    global _app
    if _app is None:
        _app = FastAPI(docs_url=None)

        @asynccontextmanager
        async def lifespan(app: FastAPI):
            main_loop = asyncio.get_running_loop()

            # async with get_db() as db:
            async for db in get_db():
                global_config = GlobalConfig()
                await global_config.init_config()

                device_service = DeviceService(db)
                model_service = ModelService(db)
                model_relation_service = DeviceModelRelationService(db)
                scene_service = SceneService(db)
                scene_relation_service = DeviceSceneRelationService(db)

                app.state.device_service = device_service
                app.state.model_service = model_service
                app.state.model_relation_service = model_relation_service
                app.state.scene_service = scene_service
                app.state.scene_relation_service = scene_relation_service

                tcp_manager = TcpManager(device_service=device_service)
                app.state.tcp_manager = tcp_manager
                await tcp_manager.start()

                algo_runner = AlgoRunner(
                    device_service=device_service,
                    model_service=model_service,
                    relation_service=model_relation_service,
                )
                app.state.algo_runner = algo_runner
                await algo_runner.start()

                scene_runner = SceneRunner(
                    device_service=device_service,
                    scene_service=scene_service,
                    relation_service=scene_relation_service,
                    tcp_manager=tcp_manager,
                    main_loop=main_loop
                )
                app.state.scene_runner = scene_runner
                await scene_runner.start()

                main_loop.create_task(start_server())

                main_loop.create_task(start_scheduler())

            yield  # 允许请求处理

            logger.info("Shutting down application...")

        _app.router.lifespan_context = lifespan
        _app.add_exception_handler(HTTPException, BizExceptionHandlers.biz_exception_handler)

    return _app


def get_app() -> FastAPI:
    return _app or create_app()
