import logging
from fastapi import FastAPI, Request
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import JSONResponse
from fastapi.staticfiles import StaticFiles
from contextlib import asynccontextmanager
from apscheduler.schedulers.asyncio import AsyncIOScheduler
from slowapi import _rate_limit_exceeded_handler
from slowapi.errors import RateLimitExceeded

from app.api import auth, staff, departments, sessions, roles, uploads, patients
from app.constants import error_codes
from app.db.engine import engine
from app.models import Base
from app.core.config import settings
from app.core.limiter import limiter
from app.services.data_wipe import purge_expired

logger = logging.getLogger(__name__)

_scheduler = AsyncIOScheduler()

logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s %(levelname)s %(name)s: %(message)s",
)
logger = logging.getLogger(__name__)


@asynccontextmanager
async def lifespan(app: FastAPI):
    async with engine.begin() as conn:
        await conn.run_sync(Base.metadata.create_all)

    _scheduler.add_job(purge_expired, "interval", hours=1, id="purge_expired")
    _scheduler.start()
    logger.info("CT Surgery API starting — scheduler running")

    yield

    _scheduler.shutdown(wait=False)
    logger.info("CT Surgery API shutting down")


app = FastAPI(
    title="CT Surgery API",
    version="1.0.0",
    lifespan=lifespan,
)

app.state.limiter = limiter
app.add_exception_handler(RateLimitExceeded, _rate_limit_exceeded_handler)


# ── Middleware ─────────────────────────────────────────────────────────────────

app.add_middleware(
    CORSMiddleware,
    allow_origins=settings.ALLOWED_ORIGINS,
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)


@app.middleware("http")
async def log_requests(request: Request, call_next):
    logger.info("--> [%s] %s", request.method, request.url.path)
    response = await call_next(request)
    logger.info("<-- [%s] %s %s", request.method, request.url.path, response.status_code)
    return response


# ── Error Handlers ─────────────────────────────────────────────────────────────

@app.exception_handler(Exception)
async def global_error_handler(request: Request, exc: Exception):
    logger.exception("Unhandled error on [%s] %s", request.method, request.url.path)
    return JSONResponse(
        status_code=500,
        content={"detail": {"error": error_codes.INTERNAL_ERROR, "message": str(exc)}},
    )


# ── Routers ────────────────────────────────────────────────────────────────────

app.include_router(auth.router, prefix="/auth", tags=["Auth"])
app.include_router(staff.router, prefix="/staff", tags=["Staff"])
app.include_router(departments.router, prefix="/departments", tags=["Departments"])
app.include_router(patients.router, prefix="/patients", tags=["Patients"])
app.include_router(sessions.router, prefix="/sessions", tags=["Sessions"])
app.include_router(roles.router, prefix="/roles", tags=["Roles"])
app.include_router(uploads.router, prefix="/uploads", tags=["Uploads"])
app.mount("/media", StaticFiles(directory="uploads"), name="media")


# ── Health Check ───────────────────────────────────────────────────────────────

@app.get("/health", tags=["Health"])
async def health():
    return {"status": "ok"}
