# -*- coding: utf-8 -*-
"""FastAPI 应用入口（接口层组装）。

启动方式（项目根目录）：
    uv run uvicorn app.main:app --host 127.0.0.1 --port 8090
或使用脚本：``uv run python -m app``
"""
from __future__ import annotations

from contextlib import asynccontextmanager

from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware

from app import config
from app.infrastructure.repositories import Database
from app.api.routers import agents as agents_router
from app.api.routers import auth as auth_router
from app.api.routers import bootstrap as bootstrap_router
from app.api.routers import rbac_admin as rbac_admin_router
from app.api.routers import rbac_government as rbac_government_router
from app.api.routers import rbac_opc as rbac_opc_router
from app.api.routers import rbac_investor as rbac_investor_router
from app.api.routers import rbac_operator as rbac_operator_router
from app.api.routers import rbac_org as rbac_org_router
from app.api.routers import rbac_ecosystem as rbac_ecosystem_router
from app.api.routers import rbac_developer as rbac_developer_router
from app.api.routers import rbac_portals as rbac_portals_router
from app.api.routers import templates as templates_router
from app.api.routers import relay as relay_router

APP_NAME = "云超服Agents 演示后端"


@asynccontextmanager
async def lifespan(app: FastAPI):
    """启动时初始化数据库（建表 + 幂等种子）。

    若 ``app.state.db`` 已由外部注入（如测试夹具），则直接复用，
    不重新创建，避免覆盖调用方准备的数据库实例。
    """
    db = getattr(app.state, "db", None)
    if db is None:
        db = Database()
        await db.initialize()
        app.state.db = db
    yield
    if db is not None and db._owns_session:
        await db.close()
        # 释放引擎连接池，避免连接残留导致下次启动 initialize() 被锁挂起/连接泄漏
        engine = getattr(db, "_engine", None)
        if engine is not None:
            try:
                await engine.dispose()
            except Exception:  # noqa: BLE001
                pass


app = FastAPI(
    title=APP_NAME,
    description=(
        "云超服核心服务端：身份/平台 API + 培训子应用（/api/*），统一对外 opc.pinesound.cn。"
        "异步四层架构（接口/业务/领域/基础设施）。"
    ),
    version="0.1.0",
    lifespan=lifespan,
)

# 演示服务允许任意来源（实际生产由主后端网关收敛）。
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_methods=["*"],
    allow_headers=["*"],
)

app.include_router(auth_router.router)
app.include_router(agents_router.router)
app.include_router(templates_router.router)
app.include_router(bootstrap_router.router)
app.include_router(rbac_admin_router.router)
app.include_router(rbac_government_router.router)
app.include_router(rbac_opc_router.router)
app.include_router(rbac_investor_router.router)
app.include_router(rbac_operator_router.router)
app.include_router(rbac_org_router.router)
app.include_router(rbac_portals_router.router)
app.include_router(rbac_ecosystem_router.router)
app.include_router(rbac_developer_router.router)
app.include_router(relay_router.router)


@app.get("/health", tags=["meta"], summary="健康检查")
async def health():
    return {
        "status": "ok",
        "service": "pineagents-demo-server",
        "auth_enabled": config.AUTH_ENABLED,
    }


@app.get("/", tags=["meta"], include_in_schema=False)
async def root():
    return {
        "service": APP_NAME,
        "docs": "/docs",
        "health": "/health",
    }
