import logging
from contextlib import asynccontextmanager

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

from . import cloudinary_service, crud, schemas, security
from .config import get_settings
from .database import SessionLocal
from .routers import admins, auth, contact, media, registrations, sponsorship

settings = get_settings()
logger = logging.getLogger("cycleyatra")

# Schema is managed by Alembic migrations — run `alembic upgrade head` before serving.


def _bootstrap_superadmin() -> None:
    """Seed the env-configured superadmin, re-syncing its password on startup.

    If the admin doesn't exist it is created. If it already exists but the
    `ADMIN_BOOTSTRAP_PASSWORD` no longer matches the stored hash (e.g. the env
    value was changed after the first run), its password is re-synced so the
    configured credentials always work. Requires the admin_users table (run
    `alembic upgrade head` first). Failures are logged, not raised, so a missing
    migration doesn't block startup.
    """
    if not (settings.admin_bootstrap_email and settings.admin_bootstrap_password):
        return
    db = SessionLocal()
    try:
        admin = crud.get_admin_by_email(db, settings.admin_bootstrap_email)
        if admin is None:
            crud.create_admin(
                db,
                schemas.AdminUserCreate(
                    email=settings.admin_bootstrap_email,
                    name=settings.admin_bootstrap_name,
                    password=settings.admin_bootstrap_password,
                    role=security.ROLE_SUPERADMIN,
                ),
            )
            logger.info("Seeded bootstrap superadmin %s", settings.admin_bootstrap_email)
        elif not security.verify_password(
            settings.admin_bootstrap_password, admin.hashed_password
        ):
            crud.update_admin(
                db,
                admin,
                schemas.AdminUserUpdate(password=settings.admin_bootstrap_password),
            )
            logger.info(
                "Re-synced bootstrap superadmin password for %s",
                settings.admin_bootstrap_email,
            )
    except Exception:  # noqa: BLE001 - never block startup on seeding
        logger.exception(
            "Could not seed bootstrap superadmin "
            "(has `alembic upgrade head` been run?)"
        )
    finally:
        db.close()


@asynccontextmanager
async def lifespan(app: FastAPI):
    _bootstrap_superadmin()
    if cloudinary_service.configure():
        logger.info("Cloudinary configured for cloud '%s'", settings.cloudinary_cloud_name)
    else:
        logger.warning(
            "Cloudinary not configured — gallery uploads will return 503 until "
            "CLOUDINARY_* env vars are set."
        )
    yield


app = FastAPI(
    title="CycleYatra Backend",
    description="API for the Rameswaram to Ayodhya Cycling Yatra 2026.",
    version="0.1.0",
    lifespan=lifespan,
)

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

app.include_router(auth.router)
app.include_router(admins.router)
app.include_router(registrations.router)
app.include_router(contact.router)
app.include_router(sponsorship.router)
app.include_router(media.router)


@app.get("/api/health", tags=["health"])
def health() -> dict[str, str]:
    return {"status": "ok"}
