"""Parsing utilities for grpc-gateway streaming responses."""

from __future__ import annotations

import json
from collections.abc import AsyncIterator
from typing import Any

import httpx


class StreamProtocolError(RuntimeError):
    pass


async def parse_gateway_stream(response: httpx.Response) -> AsyncIterator[dict[str, Any]]:
    """Parse newline-delimited JSON chunks from grpc-gateway stream responses.

    The gateway envelope can include either plain objects or error-wrapped objects.
    """

    async for line in response.aiter_lines():
        if not line:
            continue

        try:
            payload = json.loads(line)
        except json.JSONDecodeError as exc:
            raise StreamProtocolError(f"invalid stream chunk: {line!r}") from exc

        if not isinstance(payload, dict):
            raise StreamProtocolError("stream chunk must be a JSON object")

        # grpc-gateway often emits: {"result": {...}, "error": null}
        if "error" in payload and payload["error"]:
            raise StreamProtocolError(f"gateway stream error: {payload['error']}")

        if "result" in payload and isinstance(payload["result"], dict):
            yield payload["result"]
            continue

        yield payload
