from contextlib import asynccontextmanager

from fastapi import FastAPI, HTTPException, Request
from fastapi.responses import FileResponse, JSONResponse
from fastapi.staticfiles import StaticFiles
from sqlalchemy import text

from . import VERSION, config
from .db import Base, SessionLocal, engine
from .routes import admin, insights, inventory, settings, shop
from .seed import seed_base, seed_demo


def setup_database():
    Base.metadata.create_all(engine)
    with SessionLocal() as db:
        seed_base(db)
        if config.DEMO:
            seed_demo(db)


@asynccontextmanager
async def lifespan(app):
    setup_database()
    yield


app = FastAPI(title="Abrokyire Aba Ghana", version=VERSION, lifespan=lifespan, docs_url=None, redoc_url=None, openapi_url=None)
app.include_router(shop.router)
app.include_router(admin.router)
app.include_router(insights.router)
app.include_router(inventory.router)
app.include_router(settings.router)


@app.middleware("http")
async def security_headers(request: Request, call_next):
    resp = await call_next(request)
    resp.headers.setdefault("X-Content-Type-Options", "nosniff")
    resp.headers.setdefault("X-Frame-Options", "DENY")
    resp.headers.setdefault("Referrer-Policy", "same-origin")
    resp.headers.setdefault(
        "Content-Security-Policy",
        "default-src 'self'; img-src 'self' data:; style-src 'self' 'unsafe-inline'; script-src 'self'; frame-ancestors 'none'")
    if request.url.path.startswith("/api/"):
        resp.headers["Cache-Control"] = "no-store"
    return resp


@app.get("/api/health")
def health():
    with SessionLocal() as db:
        db.execute(text("select 1"))
    return {"ok": True, "version": VERSION, "demo": config.DEMO}


@app.exception_handler(HTTPException)
async def http_error(request: Request, exc: HTTPException):
    return JSONResponse({"detail": exc.detail}, status_code=exc.status_code, headers=getattr(exc, "headers", None))


config.UPLOAD_DIR.mkdir(parents=True, exist_ok=True)
app.mount("/uploads", StaticFiles(directory=config.UPLOAD_DIR), name="uploads")


@app.get("/{path:path}", include_in_schema=False)
def web(path: str):
    """Serve the built React app; unknown paths get index.html so page links work on refresh."""
    if path.startswith("api/"):
        raise HTTPException(404, "No such page.")
    root = config.WEB_DIR.resolve()
    if not root.exists():
        return JSONResponse({"detail": "The web app is not built yet. Run: npm run build (in web/)."}, status_code=503)
    target = (root / path).resolve()
    if path and target.is_file() and root in target.parents:
        # Built asset names carry a content hash, so they can be cached for good; anything else must be re-checked.
        cache = "public, max-age=31536000, immutable" if target.parent.name == "assets" else "no-cache"
        return FileResponse(target, headers={"Cache-Control": cache})
    return FileResponse(root / "index.html", headers={"Cache-Control": "no-cache"})
