// Generated by smithplates HTTP codegen. Do not edit.

import { ClientOperationHttpBinding, variantForStatus, typeNameForStatus } from "generated/petstore/api/petstore/client/operationBindings";
import { parseCategoryNotFound as _parse_CategoryNotFound } from "generated/petstore/api/categoryNotFound";
import { parseCreatePetOutput as _parse_CreatePetOutput } from "generated/petstore/api/createPetOutput";
import { parseGetCategoryOutput as _parse_GetCategoryOutput } from "generated/petstore/api/getCategoryOutput";
import { parseGetOrderOutput as _parse_GetOrderOutput } from "generated/petstore/api/getOrderOutput";
import { parseGetPetOutput as _parse_GetPetOutput } from "generated/petstore/api/getPetOutput";
import { parseHealthCheckOutput as _parse_HealthCheckOutput } from "generated/petstore/api/healthCheckOutput";
import { parseOrderNotFound as _parse_OrderNotFound } from "generated/petstore/api/orderNotFound";
import { parsePetEventsOutput as _parse_PetEventsOutput } from "generated/petstore/api/petEventsOutput";
import { parsePetLocationRedirect as _parse_PetLocationRedirect } from "generated/petstore/api/petLocationRedirect";
import { parsePetNotFound as _parse_PetNotFound } from "generated/petstore/api/petNotFound";
import { parsePlaceOrderOutput as _parse_PlaceOrderOutput } from "generated/petstore/api/placeOrderOutput";
import { parseUpdatePetOutput as _parse_UpdatePetOutput } from "generated/petstore/api/updatePetOutput";
import { parseValidationError as _parse_ValidationError } from "generated/petstore/api/validationError";

/** Normalized fetch/axios response shape consumed by the generated client. */
export interface NormalizedResponse {
  status: number;
  headers: Record<string, string>;
  text(): Promise<string>;
  json(): Promise<unknown>;
}

/** Raised when an HTTP response cannot be mapped to a generated API model. */
export class ClientResponseError extends Error {
  constructor(message: string) {
    super(message);
    this.name = "ClientResponseError";
  }
}

const _MODEL_PARSERS: Record<string, (value: unknown) => unknown> = {
  "CategoryNotFound": _parse_CategoryNotFound,
  "CreatePetOutput": _parse_CreatePetOutput,
  "GetCategoryOutput": _parse_GetCategoryOutput,
  "GetOrderOutput": _parse_GetOrderOutput,
  "GetPetOutput": _parse_GetPetOutput,
  "HealthCheckOutput": _parse_HealthCheckOutput,
  "OrderNotFound": _parse_OrderNotFound,
  "PetEventsOutput": _parse_PetEventsOutput,
  "PetLocationRedirect": _parse_PetLocationRedirect,
  "PetNotFound": _parse_PetNotFound,
  "PlaceOrderOutput": _parse_PlaceOrderOutput,
  "UpdatePetOutput": _parse_UpdatePetOutput,
  "ValidationError": _parse_ValidationError,
};

function _resolveModelParser(typeName: string): (value: unknown) => unknown {
  const parser = _MODEL_PARSERS[typeName];
  if (parser === undefined) {
    throw new ClientResponseError("Unknown generated API model type " + typeName);
  }
  return parser;
}

function _headerValue(response: NormalizedResponse, headerName: string): string | undefined {
  const lower = headerName.toLowerCase();
  const direct = response.headers[headerName];
  if (direct !== undefined) {
    return direct;
  }
  return response.headers[lower];
}

/** Map an HTTP response to a generated API model using Smithy-derived bindings. */
export async function parseClientResponse(
  response: NormalizedResponse,
  binding: ClientOperationHttpBinding,
): Promise<unknown> {
  if (response.status === 204 || binding.variantsByStatus[response.status] === "__empty__") {
    if (response.status >= 400) {
      throw new ClientResponseError("HTTP " + response.status);
    }
    return null;
  }

  const variant = variantForStatus(binding, response.status);
  const typeName = typeNameForStatus(binding, response.status);
  const parse = _resolveModelParser(typeName);

  let payload: Record<string, unknown> = {};
  if (variant.mediaType !== null) {
    const body = await response.json();
    if (body !== null && body !== undefined) {
      if (typeof body === "object" && !Array.isArray(body)) {
        payload = { ...(body as Record<string, unknown>) };
      } else {
        payload = { value: body };
      }
    }
  }

  for (const [memberName, headerName] of variant.headerBindings) {
    const headerValue = _headerValue(response, headerName);
    if (headerValue !== undefined) {
      payload[memberName] = headerValue;
    }
  }

  if (variant.mediaType === null && variant.headerBindings.length === 0) {
    if (response.status >= 400) {
      throw new ClientResponseError("HTTP " + response.status);
    }
    return null;
  }

  if (response.status >= 400) {
    return parse(payload);
  }

  if (Object.keys(payload).length === 0 && variant.mediaType === null) {
    return null;
  }

  return parse(payload);
}
