from collections.abc import AsyncGenerator
from contextlib import asynccontextmanager
from fastapi import FastAPI, Request, HTTPException
from fastapi.responses import JSONResponse
from fastapi.middleware.cors import CORSMiddleware
from fastapi.middleware.gzip import GZipMiddleware

from backend.core.config import get_app_settings
from backend.core.root_logger import get_logger
from backend.routes import router
from backend import __version__
import uvicorn

settings = get_app_settings()
logger = get_logger()

description = f"""
fuware is a web application for managing your house items and tracking them.
"""

@asynccontextmanager
async def lifespan_fn(_: FastAPI) -> AsyncGenerator[None, None]:
  logger.info("start: database initialization")
  import backend.db.init_db as init_db

  init_db.main()
  logger.info("end: database initialization")

  logger.info("-----SYSTEM STARTUP-----")
  # logger.info("------APP SETTINGS------")
  # logger.info(
  #       settings.model_dump_json(
  #           indent=4,
  #           exclude={
  #               "SECRET",
  #               "DB_URL",  # replace by DB_URL_PUBLIC for logs
  #               "DB_PROVIDER",
  #           },
  #       )
  #   )
  yield
  logger.info("-----SYSTEM SHUTDOWN-----")

app = FastAPI(
  title="Fuware",
  description=description,
  version=__version__,
  docs_url=settings.DOCS_URL,
  redoc_url=settings.REDOC_URL,
  lifespan=lifespan_fn,
)

app.add_middleware(GZipMiddleware, minimum_size=1000)

if not settings.PRODUCTION:
  allowed_origins = ["http://localhost:3000"]

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

@app.exception_handler(HTTPException)
async def unicorn_exception_handler(request: Request, exc: HTTPException):
  return JSONResponse(
    status_code=exc.status_code,
    content={"status": exc.status_code, "data": exc.detail},
  )

def api_routers():
  app.include_router(router)

api_routers()

def main():
  uvicorn.run("app:app", host="0.0.0.0", port=settings.API_PORT, reload=True, workers=1, forwarded_allow_ips="*")

if __name__ == "__main__":
  main()
