# service/core/lifespan.py
"""
应用生命周期管理（精简版）

职责：
- 协调各个服务的启动和关闭
- 不包含具体的连接逻辑
- 支持可选依赖的优雅降级
"""

from contextlib import asynccontextmanager
from pathlib import Path
from typing import TYPE_CHECKING

from fastapi import FastAPI
from loguru import logger

from infoman.config import settings

if TYPE_CHECKING:
    from infoman.service.infrastructure.mq.manager import NATSManager

# ========== 数据库（必需） ==========
if settings.USE_PRO_ORM:
    from infoman.service.infrastructure.db_relation.manager_pro import db_manager
    _DB_MANAGER_TYPE = "pro"
else:
    from infoman.service.infrastructure.db_relation.manager import db_manager
    _DB_MANAGER_TYPE = "basic"

# ========== Redis（可选） ==========
try:
    from infoman.service.infrastructure.db_cache.manager import RedisManager
    REDIS_AVAILABLE = True
except ImportError:
    logger.warning("⚠️ Redis 依赖未安装，缓存功能将不可用 (需要: redis, fastapi-cache2)")
    RedisManager = None
    REDIS_AVAILABLE = False

# ========== 向量数据库（可选） ==========
try:
    from infoman.service.infrastructure.db_vector.manager import VectorDBManager
    VECTOR_AVAILABLE = True
except ImportError:
    logger.warning("⚠️ 向量数据库依赖未安装，向量搜索功能将不可用 (需要: qdrant-client)")
    VectorDBManager = None
    VECTOR_AVAILABLE = False

# ========== 消息队列（可选） ==========
try:
    from infoman.service.infrastructure.mq import NATSManager
    MQ_AVAILABLE = True
except ImportError:
    logger.warning("⚠️ 消息队列依赖未安装，NATS 功能将不可用 (需要: nats-py)")
    NATSManager = None
    MQ_AVAILABLE = False

# ========== 定时任务（可选） ==========
try:
    from infoman.service.infrastructure.scheduler import SchedulerManager
    SCHEDULER_AVAILABLE = True
except ImportError:
    logger.warning("⚠️ 定时任务依赖未安装，调度器功能将不可用 (需要: apscheduler)")
    SchedulerManager = None
    SCHEDULER_AVAILABLE = False


async def _register_event_handlers(nats_manager: "NATSManager") -> None:
    """
    自动注册NATS事件处理器

    从项目根目录的 app/events 或 {APP_NAME}/events 目录加载事件处理器。
    支持优雅降级：如果目录不存在，仅记录警告，不中断启动流程。

    Args:
        nats_manager: NATS管理器实例
    """
    try:
        from infoman.service.infrastructure.mq.nats.nats_event_router import event_router
        from infoman.service.utils.module_loader import register_event_handlers
    except ImportError as e:
        logger.warning(f"⚠️ 无法导入事件路由器或模块加载器: {e}")
        return

    possible_paths = [
        ("app.events", "./app/events"),
        (settings.MQ_EVENT_PACKAGE, settings.MQ_EVENT_PATH),
    ]

    loaded_any = False
    for package, folder in possible_paths:
        project_root = Path.cwd()
        loaded_modules = register_event_handlers(
            package=package,
            folder=folder,
            base_path=project_root
        )

        if loaded_modules:
            loaded_any = True
            logger.info(f"📦 从 {folder} 加载了 {len(loaded_modules)} 个事件模块")
            break

    if not loaded_any:
        logger.info(
            "ℹ️ 未找到事件处理器目录，跳过自动注册。"
            "如需使用NATS事件，请创建 app/events 目录"
        )
        return

    # 注册所有发现的事件处理器到NATS
    try:
        nats_client = nats_manager.client
        if nats_client:
            await event_router.register(nats_client=nats_client)
            logger.success("✅ NATS事件处理器注册完成")
        else:
            logger.warning("⚠️ NATS客户端未初始化，跳过事件注册")
    except Exception as e:
        logger.error(f"❌ 注册NATS事件处理器失败: {e}")
        # 不抛出异常，允许应用继续启动


@asynccontextmanager
async def lifespan(app: FastAPI):
    """应用生命周期管理（支持可选依赖）"""

    # ========== 启动 ==========
    logger.info(f"🚀 应用启动中 [{settings.APP_NAME} v{settings.APP_VERSION}]")
    logger.info(f"   环境: {settings.ENV}")
    logger.info(f"   数据库管理器: {_DB_MANAGER_TYPE}")
    logger.info(
        f"   可选功能: Redis={REDIS_AVAILABLE}, Vector={VECTOR_AVAILABLE}, "
        f"MQ={MQ_AVAILABLE}, Scheduler={SCHEDULER_AVAILABLE}"
    )

    # 初始化管理器（仅限已安装的）
    managers = {}

    # 数据库（必需）
    managers['db'] = db_manager
    app.state.db_manager = db_manager

    # Redis（可选）
    if REDIS_AVAILABLE:
        redis_manager = RedisManager()
        managers['redis'] = redis_manager
        app.state.redis_manager = redis_manager

    # 向量数据库（可选）
    if VECTOR_AVAILABLE:
        vector_manager = VectorDBManager()
        managers['vector'] = vector_manager
        app.state.vector_manager = vector_manager

    # 消息队列（可选）
    if MQ_AVAILABLE:
        nats_manager = NATSManager()
        managers['mq'] = nats_manager
        app.state.nats_manager = nats_manager

    # 定时任务（可选）
    if SCHEDULER_AVAILABLE:
        scheduler_manager = SchedulerManager()
        managers['scheduler'] = scheduler_manager
        app.state.scheduler_manager = scheduler_manager

    try:
        # 1. 数据库
        await db_manager.startup(app)

        # 2. Redis（如果可用）
        if 'redis' in managers:
            await managers['redis'].startup(app)

        # 3. 向量数据库（如果可用）
        if 'vector' in managers:
            await managers['vector'].startup(app)

        # 4. 消息队列（如果可用）
        if 'mq' in managers:
            await managers['mq'].startup(app)

            # 4.1 自动注册事件处理器
            if managers['mq'].is_available:
                await _register_event_handlers(managers['mq'])

        # 5. 定时任务（如果可用）
        if 'scheduler' in managers:
            await managers['scheduler'].startup(app)

        logger.success("✅ 所有服务启动完成")

    except Exception as e:
        logger.error(f"❌ 服务启动失败: {e}")
        raise

    # ========== 运行 ==========
    yield

    # ========== 关闭 ==========
    logger.info("⏹️ 应用关闭中...")

    try:
        # 按相反顺序关闭（仅关闭已启动的）
        if 'scheduler' in managers:
            await managers['scheduler'].shutdown()

        if 'mq' in managers:
            await managers['mq'].shutdown()

        if 'vector' in managers:
            await managers['vector'].shutdown()

        if 'redis' in managers:
            await managers['redis'].shutdown()

        await db_manager.shutdown()

        logger.success("✅ 所有服务已关闭")

    except Exception as e:
        logger.error(f"❌ 服务关闭失败: {e}")
