from contextlib import asynccontextmanager import logging from pathlib import Path from fastapi import FastAPI, Request from fastapi.middleware.cors import CORSMiddleware from fastapi.responses import JSONResponse from fastapi.staticfiles import StaticFiles from app.core.config import get_settings from app.api import chat, drug, auth, admin from app.api import admin_knowledge from app.api.exam import chapter, practice, exam_qa, progress settings = get_settings() logging.basicConfig( level=settings.log_level, format="%(asctime)s [%(levelname)s] %(name)s: %(message)s", handlers=[ logging.FileHandler(settings.log_file), logging.StreamHandler(), ], ) logger = logging.getLogger(__name__) @asynccontextmanager async def lifespan(app: FastAPI): logger.info(f"Starting {settings.app_name} in {settings.app_env} mode") yield logger.info(f"Shutting down {settings.app_name}") app = FastAPI( title=settings.app_name, version="1.0.0", lifespan=lifespan, ) app.add_middleware( CORSMiddleware, allow_origins=["*"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) app.include_router(chat.router, prefix=settings.api_prefix) app.include_router(drug.router, prefix=settings.api_prefix) app.include_router(auth.router, prefix=settings.api_prefix) app.include_router(admin.router, prefix=settings.api_prefix) app.include_router(admin_knowledge.router, prefix=settings.api_prefix) app.include_router(chapter.router, prefix=settings.api_prefix) app.include_router(practice.router, prefix=settings.api_prefix) app.include_router(exam_qa.router, prefix=settings.api_prefix) app.include_router(progress.router, prefix=settings.api_prefix) # ้™ๆ€ๆ–‡ไปถ static_dir = Path(__file__).resolve().parent.parent.parent / "static" static_dir.mkdir(parents=True, exist_ok=True) app.mount("/static", StaticFiles(directory=str(static_dir), html=True), name="static") @app.get("/") async def root(): from fastapi.responses import FileResponse return FileResponse(static_dir / "index.html") @app.get("/health") async def health_check(): return {"status": "ok", "app": settings.app_name, "env": settings.app_env} @app.exception_handler(Exception) async def global_exception_handler(request: Request, exc: Exception): logger.error(f"Unhandled exception: {exc}", exc_info=True) return JSONResponse( status_code=500, content={"detail": "Internal server error"}, )