import logging
from contextlib import asynccontextmanager

from fastapi import Depends, FastAPI
from fastapi.middleware.cors import CORSMiddleware
from sqlalchemy import text

from app.config.config import settings
from app.database import engine
from app.middleware.auth import get_current_user
from app.routers import auth as auth_router
from app.routers import configuration

# ─── Logging ──────────────────────────────────────────────────────────────────
logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s | %(levelname)-8s | %(name)s | %(message)s",
    datefmt="%Y-%m-%d %H:%M:%S",
)
logger = logging.getLogger(__name__)


# ─── Lifespan (startup / shutdown) ────────────────────────────────────────────
@asynccontextmanager
async def lifespan(app: FastAPI):
    logger.info(f"🚀  Starting {settings.APP_NAME}  [env={settings.ENV}]")
    # Verify DB connection on startup
    try:
        async with engine.connect() as conn:
            await conn.execute(text("SELECT 1"))
        logger.info("✅  Database connection: OK")
    except Exception as exc:
        logger.error(f"❌  Database connection FAILED: {exc}")
    yield
    # Shutdown — close all pool connections cleanly
    await engine.dispose()
    logger.info("🛑  Application shutdown complete")


# ─── App factory ──────────────────────────────────────────────────────────────
# In production: Swagger UI and ReDoc are disabled to avoid exposing API surface.
app = FastAPI(
    title=settings.APP_NAME,
    version="1.0.0",
    description=(
        "Configurable Multi-Tenant Loan Management System (LMS) — "
        "configuration portal for lender product rules."
    ),
    lifespan=lifespan,
    # Disable interactive docs in production
    docs_url=None if settings.is_production else "/docs",
    redoc_url=None if settings.is_production else "/redoc",
    openapi_url=None if settings.is_production else "/openapi.json",
)

# ─── CORS ─────────────────────────────────────────────────────────────────────
app.add_middleware(
    CORSMiddleware,
    allow_origins=settings.cors_origins_list,
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

# ─── Public routes ────────────────────────────────────────────────────────────
# /auth/microsoft/login, /auth/microsoft/callback, /auth/token, /auth/me
app.include_router(auth_router.router)

# ─── Config routes (auth temporarily removed — will re-add after OAuth is live) ─
app.include_router(configuration.router)


# ─── Root ─────────────────────────────────────────────────────────────────────
@app.get("/", tags=["Health"])
def read_root():
    return {
        "status": "ONLINE",
        "app": settings.APP_NAME,
        "environment": settings.ENV,
        "docs": "/docs" if not settings.is_production else "disabled",
    }


# ─── Health Check ─────────────────────────────────────────────────────────────
@app.get("/health", tags=["Health"])
async def health_check():
    """
    Readiness probe — checks MySQL connectivity and Redis cache status.
    Returns HTTP 200 with `status=ok` when fully healthy,
    or `status=degraded` when cache is unreachable (app still functional).
    """
    from app.services.cache_service import cache_service

    db_status = "ok"
    db_error: str | None = None
    try:
        async with engine.connect() as conn:
            await conn.execute(text("SELECT 1"))
    except Exception as exc:
        db_status = "error"
        db_error = str(exc)
        logger.error(f"Health check — DB error: {exc}")

    cache_status = "ok" if cache_service.is_connected else "degraded"

    overall = "ok" if db_status == "ok" else "degraded"

    payload: dict = {
        "status": overall,
        "environment": settings.ENV,
        "database": db_status,
        "cache": cache_status,
    }
    if db_error:
        payload["database_error"] = db_error

    return payload


if __name__ == "__main__":
    import uvicorn

    uvicorn.run("main:app", host="0.0.0.0", port=8000, reload=True)
