from contextlib import asynccontextmanager
from fastapi import FastAPI
from fastapi.exceptions import RequestValidationError
from fastapi.middleware.cors import CORSMiddleware
from starlette.exceptions import HTTPException as StarletteHTTPException
from app.database import init_db, async_session
import app.models  # noqa: F401 - 注册所有模型
from app.routers import (
    auth_router,
    conversation_router,
    document_router,
    task_router,
    forum_router,
    graph_router,
    agent_router,
    todo_router,
    settings_router,
    folder_router,
    skill_router,
    log_router,
    system_router,
    brain_router,
)
from app.routers.scheduler import router as scheduler_router
from app.services.scheduler_service import start_scheduler, stop_scheduler, get_scheduler_status
from app.services.admin_bootstrap_service import ensure_admin_user
from app.config import settings
from app.logging_utils import (
    setup_logging,
    request_logging_middleware,
    log_http_exception,
    log_validation_exception,
    log_unhandled_exception,
    persist_system_log,
)
import os


INSECURE_SECRET_KEYS = {
    'change-me-in-production',
    'change-me-to-a-random-secret-key',
    'jarvis-secret-key-change-in-production',
}


def validate_startup_security() -> None:
    if not settings.DEBUG and settings.SECRET_KEY in INSECURE_SECRET_KEYS:
        raise RuntimeError('SECRET_KEY must be changed before running with DEBUG disabled')


async def run_startup() -> None:
    validate_startup_security()
    await init_db()
    async with async_session() as session:
        await ensure_admin_user(session, settings)
    await persist_system_log(
        message="application_started",
        source="app",
        operation="app.startup",
        details={"version": settings.APP_VERSION},
    )
    start_scheduler()


@asynccontextmanager
async def lifespan(app: FastAPI):
    # 启动
    setup_logging(settings.DEBUG)
    os.makedirs(settings.DATA_DIR, exist_ok=True)
    os.makedirs(settings.UPLOAD_DIR, exist_ok=True)
    os.makedirs(settings.CHROMA_PERSIST_DIR, exist_ok=True)
    await run_startup()
    yield
    # 关闭
    stop_scheduler()


app = FastAPI(
    title=settings.APP_NAME,
    version=settings.APP_VERSION,
    lifespan=lifespan,
)

# CORS
app.add_middleware(
    CORSMiddleware,
    allow_origins=settings.CORS_ORIGINS,
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)
app.middleware("http")(request_logging_middleware)
app.add_exception_handler(StarletteHTTPException, log_http_exception)
app.add_exception_handler(RequestValidationError, log_validation_exception)
app.add_exception_handler(Exception, log_unhandled_exception)

# 注册路由
app.include_router(auth_router)
app.include_router(conversation_router)
app.include_router(document_router)
app.include_router(task_router)
app.include_router(forum_router)
app.include_router(graph_router)
app.include_router(agent_router)
app.include_router(todo_router)
app.include_router(settings_router)
app.include_router(folder_router)
app.include_router(skill_router)
app.include_router(log_router)
app.include_router(system_router)
app.include_router(brain_router)
app.include_router(scheduler_router)


@app.get("/api/health")
async def health():
    return {
        "status": "ok",
        "version": settings.APP_VERSION,
        "llm_provider": settings.LLM_PROVIDER,
        "scheduler": get_scheduler_status(),
    }
