# Generated by smithplates HTTP codegen. Do not edit.

from __future__ import annotations

import httpx2
from generated.example.auth_output import AuthOutput
from generated.example.query_auth_api.client.operation_bindings import ClientOperationHttpBinding
from generated.example.query_auth_api.model_validation import validate_api_model
from pydantic import BaseModel


class ClientResponseError(Exception):
    """Raised when an HTTP response cannot be mapped to a generated API model."""


_MODEL_TYPES: dict[str, type[object]] = {
    "AuthOutput": AuthOutput,
}


def parse_client_response(
    response: httpx2.Response,
    binding: ClientOperationHttpBinding,
) -> BaseModel | object | None:
    """Map an HTTP response to a generated API model using Smithy-derived bindings."""
    if response.status_code == 204 or binding.variants_by_status.get(response.status_code) == "__empty__":
        if response.status_code >= 400:
            response.raise_for_status()
        return None

    variant = binding.variant_for_status(response.status_code)
    type_name = binding.type_name_for_status(response.status_code)
    model_type = _resolve_model_type(type_name)

    payload: dict[str, object] = {}
    if variant.media_type is not None and response.content:
        body = response.json()
        if isinstance(body, dict):
            payload = dict(body)

    for member_name, header_name in variant.header_bindings:
        if header_name in response.headers:
            payload[member_name] = response.headers[header_name]

    if variant.media_type is None and not variant.header_bindings:
        if response.status_code >= 400:
            response.raise_for_status()
        return None

    if response.status_code >= 400:
        return validate_api_model(model_type, payload)

    response.raise_for_status()
    if not payload and variant.media_type is None:
        return None
    return validate_api_model(model_type, payload)


def _resolve_model_type(type_name: str) -> type[object]:
    model_type = _MODEL_TYPES.get(type_name)
    if model_type is None:
        msg = f"Unknown generated API model type {type_name!r}"
        raise ClientResponseError(msg)
    return model_type
