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

import { dumpApiModel } from "generated/petstore/api/petstore/modelValidation";
import { parseClientResponse } from "generated/petstore/api/petstore/client/clientResponse";
import { OPERATION_HTTP_BINDINGS } from "generated/petstore/api/petstore/client/operationBindings";
import type { CreatePetInput } from "generated/petstore/api/createPetInput";
import type { CreatePetOutput } from "generated/petstore/api/createPetOutput";
import type { GetPetOutput } from "generated/petstore/api/getPetOutput";
import type { PetAttribute } from "generated/petstore/api/petAttribute";
import type { PetLocationRedirect } from "generated/petstore/api/petLocationRedirect";
import type { PetNotFound } from "generated/petstore/api/petNotFound";
import type { PetSpecies } from "generated/petstore/api/petSpecies";
import type { PetStatus } from "generated/petstore/api/petStatus";
import type { UpdatePetBody } from "generated/petstore/api/updatePetBody";
import type { UpdatePetOutput } from "generated/petstore/api/updatePetOutput";
import type { ValidationError } from "generated/petstore/api/validationError";

function encodeRfc3986(value: string): string {
  return encodeURIComponent(value).replace(
    /[!'()*]/g,
    (character) => "%" + character.charCodeAt(0).toString(16).toUpperCase(),
  );
}

export class PetsApiClient {
  private readonly baseUrl: string;
  private readonly fetchFn: typeof fetch;

  constructor(baseUrl: string, fetchFn: typeof fetch = fetch) {
    this.baseUrl = baseUrl.replace(/\/+$/, "");
    this.fetchFn = fetchFn;
  }

  async createPet(
    createPetInput: CreatePetInput,
  ): Promise<CreatePetOutput | ValidationError> {
    const headers: Record<string, string> = {};
    headers["Content-Type"] = "application/json";
    const queryParts: string[] = [];
    const queryString = queryParts.join("&");
    const requestUrl = `${this.baseUrl}/pets` + (queryString ? "?" + queryString : "");
    const requestBody = JSON.stringify(dumpApiModel(createPetInput));
    const response = await this.fetchFn(
      requestUrl,
      {
        method: "POST",
        headers,
        body: requestBody,
      },
    );
    const normalized = {
      status: response.status,
      headers: Object.fromEntries(response.headers.entries()),
      text: () => response.text(),
      json: async () => await response.json(),
    };
    const parsed = await parseClientResponse(normalized, OPERATION_HTTP_BINDINGS["createPet"]);
    return parsed as CreatePetOutput | ValidationError;
  }

  async deletePet(
    petId: string,
  ): Promise<PetNotFound | void> {
    const headers: Record<string, string> = {};
    const queryParts: string[] = [];
    const queryString = queryParts.join("&");
    const requestUrl = `${this.baseUrl}/pets/${encodeRfc3986(String(petId))}` + (queryString ? "?" + queryString : "");
    const response = await this.fetchFn(
      requestUrl,
      {
        method: "DELETE",
        headers,
      },
    );
    const normalized = {
      status: response.status,
      headers: Object.fromEntries(response.headers.entries()),
      text: () => response.text(),
      json: async () => await response.json(),
    };
    const parsed = await parseClientResponse(normalized, OPERATION_HTTP_BINDINGS["deletePet"]);
    return parsed as PetNotFound | void;
  }

  async getPet(
    petId: string,
  ): Promise<GetPetOutput | PetNotFound> {
    const headers: Record<string, string> = {};
    const queryParts: string[] = [];
    const queryString = queryParts.join("&");
    const requestUrl = `${this.baseUrl}/pets/${encodeRfc3986(String(petId))}` + (queryString ? "?" + queryString : "");
    const response = await this.fetchFn(
      requestUrl,
      {
        method: "GET",
        headers,
      },
    );
    const normalized = {
      status: response.status,
      headers: Object.fromEntries(response.headers.entries()),
      text: () => response.text(),
      json: async () => await response.json(),
    };
    const parsed = await parseClientResponse(normalized, OPERATION_HTTP_BINDINGS["getPet"]);
    return parsed as GetPetOutput | PetNotFound;
  }

  async resolvePetLocation(
    petId: string,
  ): Promise<PetLocationRedirect | PetNotFound> {
    const headers: Record<string, string> = {};
    const queryParts: string[] = [];
    const queryString = queryParts.join("&");
    const requestUrl = `${this.baseUrl}/pets/${encodeRfc3986(String(petId))}/location` + (queryString ? "?" + queryString : "");
    const response = await this.fetchFn(
      requestUrl,
      {
        method: "GET",
        headers,
      },
    );
    const normalized = {
      status: response.status,
      headers: Object.fromEntries(response.headers.entries()),
      text: () => response.text(),
      json: async () => await response.json(),
    };
    const parsed = await parseClientResponse(normalized, OPERATION_HTTP_BINDINGS["resolvePetLocation"]);
    return parsed as PetLocationRedirect | PetNotFound;
  }

  async updatePet(
    petId: string,
    body: UpdatePetBody,
  ): Promise<UpdatePetOutput | PetNotFound | ValidationError> {
    const headers: Record<string, string> = {};
    headers["Content-Type"] = "application/json";
    const queryParts: string[] = [];
    const queryString = queryParts.join("&");
    const requestUrl = `${this.baseUrl}/pets/${encodeRfc3986(String(petId))}` + (queryString ? "?" + queryString : "");
    const requestBody = JSON.stringify(dumpApiModel(body));
    const response = await this.fetchFn(
      requestUrl,
      {
        method: "PUT",
        headers,
        body: requestBody,
      },
    );
    const normalized = {
      status: response.status,
      headers: Object.fromEntries(response.headers.entries()),
      text: () => response.text(),
      json: async () => await response.json(),
    };
    const parsed = await parseClientResponse(normalized, OPERATION_HTTP_BINDINGS["updatePet"]);
    return parsed as UpdatePetOutput | PetNotFound | ValidationError;
  }
}
