"""FastAPI app entry point.

Run locally with:
    uvicorn backend.main:app --reload --port 8000

Routers are mounted under settings.API_PREFIX (default '/api'). The
root `/` and `/api/health` endpoints live here at the app level since
they don't belong to any feature module.

Auth:
  - /api/auth/login is PUBLIC
  - /api/auth/me, /api/auth/change-password are protected inside auth.py
  - /api/health is PUBLIC
  - All other /api/* require a valid Bearer token (enforced at
    include_router level with dependencies=[Depends(get_current_user)])
  - /api/admin/* additionally requires role=admin (enforced inside admin.py)
"""
from __future__ import annotations

from fastapi import Depends, FastAPI
from fastapi.middleware.cors import CORSMiddleware
from sqlalchemy.orm import Session

from backend.api.middleware.auth import get_current_user, session_or_ingest
from backend.api.routers import admin, analytics, auth, demand, executive, finance, npl, polleo_ai, promo, supply
from backend.config import settings
from backend.models.database import get_db
from backend.repositories.base import BaseRepository
from backend.schemas.common import HealthResponse

app = FastAPI(
    title="Polleo Demand API",
    version="1.0.0",
)

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

# Auth router is mounted without a global auth dependency — its /login
# endpoint must remain public. Each protected endpoint inside auth.py
# declares Depends(get_current_user) on its own.
app.include_router(auth.router, prefix=settings.API_PREFIX)

# Feature routers — all endpoints require a valid Bearer token.
_protected = [Depends(get_current_user)]
# demand + supply carry the automated-ingestion endpoints, so their global gate
# also accepts the machine ingest key — but ONLY on the three /upload-* paths
# (session_or_ingest enforces that scope). Every other route still needs a JWT.
_protected_or_ingest = [Depends(session_or_ingest)]
app.include_router(demand.router, prefix=settings.API_PREFIX, dependencies=_protected_or_ingest)
app.include_router(supply.router, prefix=settings.API_PREFIX, dependencies=_protected_or_ingest)
app.include_router(promo.router,  prefix=settings.API_PREFIX, dependencies=_protected)
app.include_router(npl.router,    prefix=settings.API_PREFIX, dependencies=_protected)
app.include_router(finance.router, prefix=settings.API_PREFIX, dependencies=_protected)
app.include_router(executive.router, prefix=settings.API_PREFIX, dependencies=_protected)
app.include_router(analytics.router, prefix=settings.API_PREFIX, dependencies=_protected)
app.include_router(polleo_ai.router, prefix=settings.API_PREFIX, dependencies=_protected)

# Admin router declares its own require_role("admin") dependency, which
# also calls get_current_user under the hood — no extra dep needed.
app.include_router(admin.router, prefix=settings.API_PREFIX)


@app.get("/")
def root() -> dict:
    return {"status": "ok", "version": app.version}


@app.get(f"{settings.API_PREFIX}/health", response_model=HealthResponse)
def health(db: Session = Depends(get_db)) -> HealthResponse:
    try:
        BaseRepository(db).ping()
        return HealthResponse(status="ok", db="connected", version=app.version)
    except Exception as e:
        return HealthResponse(
            status="degraded",
            db="disconnected",
            detail=str(e),
            version=app.version,
        )
