"""
Dünner /v1-Roh-Weiterleiter (UMBAU v3, P1).

Wenn MC_V1_UPSTREAM gesetzt ist (Unit-Env), reicht das Steuerpult /v1 unangefasst an
den eigenständigen mc2-gateway-Prozess (Loopback :9010) durch — LAN-Clients wie die
IDE-Lane erreichen den Gateway sonst nicht. Hier passiert BEWUSST nichts: kein
Routing, keine Bild-Weiche, keine Token-Zählung — all das macht genau einmal der
Gateway-Prozess (routers/gateway_proxy.py). Rollback = Env-Zeile aus der Unit
entfernen → app.py bindet wieder den lokalen Gateway ein.
"""

import logging

from fastapi import APIRouter, Request
from fastapi.responses import JSONResponse, StreamingResponse

from config import V1_UPSTREAM

log = logging.getLogger(__name__)

router = APIRouter(prefix="/v1")

# Hop-by-hop-Header dürfen nicht blind weitergereicht werden; content-length wird von
# httpx (Request) bzw. Starlette-Chunking (Response) neu bestimmt.
_HOP_HEADERS = {
    "host", "content-length", "connection", "keep-alive", "transfer-encoding",
    "upgrade", "proxy-authenticate", "proxy-authorization", "te", "trailer",
}


def _clean(headers) -> dict:
    return {k: v for k, v in headers.items() if k.lower() not in _HOP_HEADERS}


@router.api_route("/{path:path}", methods=["GET", "POST"])
async def forward(path: str, request: Request):
    client = request.app.state.gw_client  # geteilter Keep-Alive-Client (app.py lifespan)
    url = f"{V1_UPSTREAM}/v1/{path}"
    if request.url.query:
        url = f"{url}?{request.url.query}"
    body = await request.body()
    req = client.build_request(
        request.method, url, content=body or None, headers=_clean(request.headers),
        timeout=None,
    )
    try:
        upstream = await client.send(req, stream=True)
    except Exception as exc:  # Gateway-Prozess weg → ehrlicher 502 statt Hänger
        log.warning("/v1-Weiterleitung an %s fehlgeschlagen: %s", V1_UPSTREAM, exc)
        return JSONResponse(
            {"error": {"message": f"mc2-gateway ({V1_UPSTREAM}) nicht erreichbar: {exc}",
                       "type": "gateway_unavailable"}},
            status_code=502,
        )

    async def gen():
        try:
            async for chunk in upstream.aiter_raw():
                yield chunk
        finally:
            await upstream.aclose()

    # Streaming-Passthrough für BEIDE Fälle (SSE + normale JSON-Antwort): Starlette
    # chunkt selbst, Status/Header (inkl. x-mc-routed-to) kommen vom Gateway.
    return StreamingResponse(
        gen(), status_code=upstream.status_code, headers=_clean(upstream.headers)
    )
