from fastapi import FastAPI, Request
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import JSONResponse
from slowapi import Limiter, _rate_limit_exceeded_handler
from slowapi.util import get_remote_address
from slowapi.errors import RateLimitExceeded

from app.core.config import settings
from app.routers import analytics, anomali, assistant, audit, auth, dashboard, end_to_end, expenses, files, general_affairs, laporan, laporan_shift, pemindahan, penebusan, penerimaan, penyetoran, products, rekonsiliasi, roles, spbu, stock_adjustment, system, users

app = FastAPI(
    title="SPBU Manager API",
    version="1.0.0",
    docs_url="/api/docs" if not settings.is_production else None,
    redoc_url="/api/redoc" if not settings.is_production else None,
    redirect_slashes=False,
)

limiter = Limiter(key_func=get_remote_address)
app.state.limiter = limiter
app.add_exception_handler(RateLimitExceeded, _rate_limit_exceeded_handler)

app.add_middleware(
    CORSMiddleware,
    allow_origins=[o.strip() for o in settings.CORS_ORIGINS.split(",") if o.strip()],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

app.include_router(auth.router, prefix="/api/v1/auth", tags=["auth"])
app.include_router(spbu.router, prefix="/api/v1/spbus", tags=["spbu"])
app.include_router(products.router, prefix="/api/v1/products", tags=["products"])
app.include_router(users.router, prefix="/api/v1/users", tags=["users"])
app.include_router(roles.router, prefix="/api/v1/roles", tags=["roles"])
app.include_router(system.router, prefix="/api/v1/system", tags=["system"])
app.include_router(laporan_shift.router, prefix="/api/v1", tags=["penjualan"])
app.include_router(stock_adjustment.router, prefix="/api/v1", tags=["stock"])
app.include_router(penebusan.router, prefix="/api/v1", tags=["penebusan"])
app.include_router(penerimaan.router, prefix="/api/v1", tags=["penerimaan"])
app.include_router(expenses.router, prefix="/api/v1", tags=["expenses"])
app.include_router(penyetoran.router, prefix="/api/v1", tags=["penyetoran"])
app.include_router(end_to_end.router, prefix="/api/v1", tags=["rekonsiliasi"])
app.include_router(rekonsiliasi.router, prefix="/api/v1", tags=["rekonsiliasi"])
app.include_router(dashboard.router, prefix="/api/v1", tags=["dashboard"])
app.include_router(laporan.router, prefix="/api/v1", tags=["laporan"])
app.include_router(analytics.router, prefix="/api/v1", tags=["analytics"])
app.include_router(anomali.router, prefix="/api/v1", tags=["anomali"])
app.include_router(pemindahan.router, prefix="/api/v1", tags=["pemindahan"])
app.include_router(audit.router, prefix="/api/v1", tags=["audit"])
app.include_router(assistant.router, prefix="/api/v1", tags=["assistant"])
app.include_router(general_affairs.router, prefix="/api/v1", tags=["general-affairs"])
app.include_router(files.router, prefix="/api/v1", tags=["files"])


@app.exception_handler(Exception)
async def global_exception_handler(request: Request, exc: Exception) -> JSONResponse:
    msg = str(exc) if settings.ENVIRONMENT == "development" else "Internal server error"
    # CORSMiddleware doesn't inject headers when exceptions propagate out of the ASGI app.
    # Manually reflect the Origin header so the browser doesn't swallow the error as CORS.
    headers: dict[str, str] = {}
    origin = request.headers.get("origin")
    if origin:
        allowed = [o.strip() for o in settings.CORS_ORIGINS.split(",") if o.strip()]
        if "*" in allowed or origin in allowed:
            headers["Access-Control-Allow-Origin"] = origin
            headers["Access-Control-Allow-Credentials"] = "true"
    return JSONResponse(
        status_code=500,
        content={"error": {"code": "INTERNAL_ERROR", "message": msg}},
        headers=headers,
    )


@app.get("/api/health")
async def health() -> dict:
    return {"status": "ok"}
