import logging
from contextlib import asynccontextmanager

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

from slowapi.errors import RateLimitExceeded
from slowapi.middleware import SlowAPIMiddleware

from app.api.v1 import router as v1_router
from app.rate_limit import limiter
from starlette.responses import JSONResponse
from fastapi import Request

from app.api import (
    admin, alerts, analysis, auth, companies, competitors, contracts,
    admin_api_keys, alvara_api, court_filings, dashboard, dre, graph,
    insolvencies, intelligence, people,
    processes, search, settings_api, users,
)
from app.config import settings
from app.jobs import scheduler as scheduler_module

logging.basicConfig(level=settings.LOG_LEVEL)


@asynccontextmanager
async def lifespan(app: FastAPI):
    # Any 'running' rows left over from a previous (now-dead) process are
    # orphans — mark them failed before the new scheduler starts.
    await scheduler_module.reap_stale_running_on_startup()
    scheduler_module.start()
    yield
    scheduler_module.shutdown()


app = FastAPI(title="Segunor Intel Grid", version="0.1.0", lifespan=lifespan)

# CORS for the publicacoes.mj.pt bookmarklet — when the admin runs the
# bookmarklet while viewing a search result on publicacoes.mj.pt, the POST
# originates from that domain. Scope kept tight: only this one domain, only
# the import endpoint path is meant to accept it (the endpoint itself
# authenticates via X-Intel-Token, so CORS permissiveness doesn't let
# unauthenticated calls through).
app.add_middleware(
    CORSMiddleware,
    allow_origins=[
        "https://publicacoes.mj.pt",
        "http://publicacoes.mj.pt",
    ],
    allow_credentials=False,
    allow_methods=["GET", "POST", "OPTIONS"],
    allow_headers=["Content-Type", "X-Intel-Token"],
)

app.include_router(auth.router, prefix="/api")
app.include_router(users.router, prefix="/api")
app.include_router(companies.router, prefix="/api")
app.include_router(processes.router, prefix="/api")
app.include_router(dashboard.router, prefix="/api")
app.include_router(admin.router, prefix="/api")
app.include_router(alerts.router, prefix="/api")
app.include_router(dre.router, prefix="/api")
app.include_router(search.router, prefix="/api")
app.include_router(competitors.router, prefix="/api")
app.include_router(analysis.router, prefix="/api")
app.include_router(contracts.router, prefix="/api")
app.include_router(intelligence.router, prefix="/api")
app.include_router(people.router, prefix="/api")
app.include_router(alvara_api.router, prefix="/api")
app.include_router(admin_api_keys.router, prefix="/api")
app.include_router(insolvencies.router, prefix="/api")
app.include_router(court_filings.router, prefix="/api")
app.include_router(graph.router, prefix="/api")
app.include_router(settings_api.router, prefix="/api")
app.include_router(v1_router, prefix="/api")

# slowapi rate limiter — keyed by X-API-Key (fallback IP). Only applied
# to endpoints that decorate @limiter.limit.
app.state.limiter = limiter
app.add_middleware(SlowAPIMiddleware)


async def _rate_limit_handler(request: Request, exc: RateLimitExceeded) -> JSONResponse:
    return JSONResponse(
        status_code=429,
        content={"detail": f"rate limit exceeded: {exc.detail}"},
        headers={"Retry-After": "60"},
    )


app.add_exception_handler(RateLimitExceeded, _rate_limit_handler)


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