from typing import Optional
from fastapi import FastAPI, Request, Query
from pydantic import BaseModel

### AppSentinels logging - Section Start
from opentelemetry.instrumentation.fastapi import FastAPIInstrumentor
from appsentinels_json_exporter import appsentinels_init_tracing, BodyCaptureMiddleware

appsentinels_init_tracing()
### AppSentinels logging - Section End

app = FastAPI()


### AppSentinels logging - Section Start
# BodyCaptureMiddleware must be added BEFORE instrument_app — instrument_app inserts
# OTel middleware outermost, so OTel creates the span first and BodyCaptureMiddleware
# runs inside it with a valid span context.
app.add_middleware(BodyCaptureMiddleware)
FastAPIInstrumentor().instrument_app(app)
### AppSentinels logging - Section End


class ItemPayload(BaseModel):
    name: str
    value: Optional[str] = None


# GET with query parameters: /testjson?category=books&limit=10
@app.get("/testjson")
async def get_test(
    request: Request,
    category: Optional[str] = Query(default=None, description="Filter by category"),
    limit: int = Query(default=10, ge=1, le=100, description="Max results to return"),
):
    return {
        "message": "Hello from OpenTelemetry-instrumented FastAPI!",
        "method": request.method,
        "path": request.url.path,
        "category": category,
        "limit": limit,
    }


# GET with path parameter: /testjson/items/42
@app.get("/testjson/items/{item_id}")
async def get_item(request: Request, item_id: int):
    return {
        "message": "Hello from OpenTelemetry-instrumented FastAPI!",
        "method": request.method,
        "path": request.url.path,
        "item_id": item_id,
    }


# POST with JSON body: /testjson
@app.post("/testjson")
async def post_test(request: Request, payload: ItemPayload):
    return {
        "message": "Hello from OpenTelemetry-instrumented FastAPI!",
        "method": request.method,
        "path": request.url.path,
        "received": payload.model_dump(),
    }
