# This file was auto-generated by Fern from our API Definition.

import typing
import urllib.parse
from json.decoder import JSONDecodeError

from ...core.api_error import ApiError
from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
from ...core.jsonable_encoder import jsonable_encoder
from ...core.remove_none_from_dict import remove_none_from_dict
from ...errors.bad_request_error import BadRequestError
from ...errors.not_found_error import NotFoundError
from ...types.api_response import ApiResponse
from ...types.pet import Pet
from .types.find_pets_by_status_request_status import FindPetsByStatusRequestStatus

try:
    import pydantic.v1 as pydantic  # type: ignore
except ImportError:
    import pydantic  # type: ignore

# this is used as the default value for optional parameters
OMIT = typing.cast(typing.Any, ...)


class PetClient:
    def __init__(self, *, client_wrapper: SyncClientWrapper):
        self._client_wrapper = client_wrapper

    def add_pet(self, *, request: Pet) -> Pet:
        """
        Add a new pet to the store

        Parameters:
            - request: Pet.
        ---
        from Petstore import Pet
        from Petstore.client import PetstoreApi

        client = PetstoreApi(
            api_key="YOUR_API_KEY",
            token="YOUR_TOKEN",
        )
        client.pet.add_pet(
            request=Pet(
                id=1,
                name="doggie",
                photo_urls=["photoUrls"],
            ),
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            "POST",
            urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "pet"),
            json=jsonable_encoder(request),
            headers=self._client_wrapper.get_headers(),
            timeout=60,
        )
        if 200 <= _response.status_code < 300:
            return pydantic.parse_obj_as(Pet, _response.json())  # type: ignore
        try:
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def update_pet(self, *, request: Pet) -> Pet:
        """
        Update an existing pet by Id

        Parameters:
            - request: Pet.
        ---
        from Petstore import Pet
        from Petstore.client import PetstoreApi

        client = PetstoreApi(
            api_key="YOUR_API_KEY",
            token="YOUR_TOKEN",
        )
        client.pet.update_pet(
            request=Pet(
                id=1,
                name="doggie",
                photo_urls=["photoUrls"],
            ),
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            "PUT",
            urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "pet"),
            json=jsonable_encoder(request),
            headers=self._client_wrapper.get_headers(),
            timeout=60,
        )
        if 200 <= _response.status_code < 300:
            return pydantic.parse_obj_as(Pet, _response.json())  # type: ignore
        if _response.status_code == 400:
            raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json()))  # type: ignore
        if _response.status_code == 404:
            raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json()))  # type: ignore
        try:
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def find_pets_by_status(self, *, status: typing.Optional[FindPetsByStatusRequestStatus] = None) -> typing.List[Pet]:
        """
        Multiple status values can be provided with comma separated strings

        Parameters:
            - status: typing.Optional[FindPetsByStatusRequestStatus]. Status values that need to be considered for filter
        ---
        from Petstore.client import PetstoreApi

        client = PetstoreApi(
            api_key="YOUR_API_KEY",
            token="YOUR_TOKEN",
        )
        client.pet.find_pets_by_status()
        """
        _response = self._client_wrapper.httpx_client.request(
            "GET",
            urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "pet/findByStatus"),
            params=remove_none_from_dict({"status": status}),
            headers=self._client_wrapper.get_headers(),
            timeout=60,
        )
        if 200 <= _response.status_code < 300:
            return pydantic.parse_obj_as(typing.List[Pet], _response.json())  # type: ignore
        if _response.status_code == 400:
            raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json()))  # type: ignore
        try:
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def find_pets_by_tags(
        self, *, tags: typing.Optional[typing.Union[str, typing.List[str]]] = None
    ) -> typing.List[Pet]:
        """
        Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing.

        Parameters:
            - tags: typing.Optional[typing.Union[str, typing.List[str]]]. Tags to filter by
        ---
        from Petstore.client import PetstoreApi

        client = PetstoreApi(
            api_key="YOUR_API_KEY",
            token="YOUR_TOKEN",
        )
        client.pet.find_pets_by_tags()
        """
        _response = self._client_wrapper.httpx_client.request(
            "GET",
            urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "pet/findByTags"),
            params=remove_none_from_dict({"tags": tags}),
            headers=self._client_wrapper.get_headers(),
            timeout=60,
        )
        if 200 <= _response.status_code < 300:
            return pydantic.parse_obj_as(typing.List[Pet], _response.json())  # type: ignore
        if _response.status_code == 400:
            raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json()))  # type: ignore
        try:
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def get_pet_by_id(self, pet_id: int) -> Pet:
        """
        Returns a single pet

        Parameters:
            - pet_id: int. ID of pet to return
        ---
        from Petstore.client import PetstoreApi

        client = PetstoreApi(
            api_key="YOUR_API_KEY",
            token="YOUR_TOKEN",
        )
        client.pet.get_pet_by_id(
            pet_id=1,
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            "GET",
            urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", f"pet/{pet_id}"),
            headers=self._client_wrapper.get_headers(),
            timeout=60,
        )
        if 200 <= _response.status_code < 300:
            return pydantic.parse_obj_as(Pet, _response.json())  # type: ignore
        if _response.status_code == 400:
            raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json()))  # type: ignore
        if _response.status_code == 404:
            raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json()))  # type: ignore
        try:
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def update_pet_with_form(
        self, pet_id: int, *, name: typing.Optional[str] = None, status: typing.Optional[str] = None
    ) -> None:
        """


        Parameters:
            - pet_id: int. ID of pet that needs to be updated

            - name: typing.Optional[str]. Name of pet that needs to be updated

            - status: typing.Optional[str]. Status of pet that needs to be updated
        ---
        from Petstore.client import PetstoreApi

        client = PetstoreApi(
            api_key="YOUR_API_KEY",
            token="YOUR_TOKEN",
        )
        client.pet.update_pet_with_form(
            pet_id=1,
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            "POST",
            urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", f"pet/{pet_id}"),
            params=remove_none_from_dict({"name": name, "status": status}),
            headers=self._client_wrapper.get_headers(),
            timeout=60,
        )
        if 200 <= _response.status_code < 300:
            return
        try:
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def delete_pet(self, pet_id: int) -> None:
        """


        Parameters:
            - pet_id: int. Pet id to delete
        ---
        from Petstore.client import PetstoreApi

        client = PetstoreApi(
            api_key="YOUR_API_KEY",
            token="YOUR_TOKEN",
        )
        client.pet.delete_pet(
            pet_id=1,
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            "DELETE",
            urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", f"pet/{pet_id}"),
            headers=self._client_wrapper.get_headers(),
            timeout=60,
        )
        if 200 <= _response.status_code < 300:
            return
        if _response.status_code == 400:
            raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json()))  # type: ignore
        try:
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def upload_file(self, pet_id: int, *, request: bytes) -> ApiResponse:
        """


        Parameters:
            - pet_id: int. ID of pet to update

            - request: bytes.
        """
        _response = self._client_wrapper.httpx_client.request(
            "POST",
            urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", f"pet/{pet_id}/uploadImage"),
            content=request,
            headers=self._client_wrapper.get_headers(),
            timeout=60,
        )
        if 200 <= _response.status_code < 300:
            return pydantic.parse_obj_as(ApiResponse, _response.json())  # type: ignore
        try:
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)


class AsyncPetClient:
    def __init__(self, *, client_wrapper: AsyncClientWrapper):
        self._client_wrapper = client_wrapper

    async def add_pet(self, *, request: Pet) -> Pet:
        """
        Add a new pet to the store

        Parameters:
            - request: Pet.
        ---
        from Petstore import Pet
        from Petstore.client import AsyncPetstoreApi

        client = AsyncPetstoreApi(
            api_key="YOUR_API_KEY",
            token="YOUR_TOKEN",
        )
        await client.pet.add_pet(
            request=Pet(
                id=1,
                name="doggie",
                photo_urls=["photoUrls"],
            ),
        )
        """
        _response = await self._client_wrapper.httpx_client.request(
            "POST",
            urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "pet"),
            json=jsonable_encoder(request),
            headers=self._client_wrapper.get_headers(),
            timeout=60,
        )
        if 200 <= _response.status_code < 300:
            return pydantic.parse_obj_as(Pet, _response.json())  # type: ignore
        try:
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def update_pet(self, *, request: Pet) -> Pet:
        """
        Update an existing pet by Id

        Parameters:
            - request: Pet.
        ---
        from Petstore import Pet
        from Petstore.client import AsyncPetstoreApi

        client = AsyncPetstoreApi(
            api_key="YOUR_API_KEY",
            token="YOUR_TOKEN",
        )
        await client.pet.update_pet(
            request=Pet(
                id=1,
                name="doggie",
                photo_urls=["photoUrls"],
            ),
        )
        """
        _response = await self._client_wrapper.httpx_client.request(
            "PUT",
            urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "pet"),
            json=jsonable_encoder(request),
            headers=self._client_wrapper.get_headers(),
            timeout=60,
        )
        if 200 <= _response.status_code < 300:
            return pydantic.parse_obj_as(Pet, _response.json())  # type: ignore
        if _response.status_code == 400:
            raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json()))  # type: ignore
        if _response.status_code == 404:
            raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json()))  # type: ignore
        try:
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def find_pets_by_status(
        self, *, status: typing.Optional[FindPetsByStatusRequestStatus] = None
    ) -> typing.List[Pet]:
        """
        Multiple status values can be provided with comma separated strings

        Parameters:
            - status: typing.Optional[FindPetsByStatusRequestStatus]. Status values that need to be considered for filter
        ---
        from Petstore.client import AsyncPetstoreApi

        client = AsyncPetstoreApi(
            api_key="YOUR_API_KEY",
            token="YOUR_TOKEN",
        )
        await client.pet.find_pets_by_status()
        """
        _response = await self._client_wrapper.httpx_client.request(
            "GET",
            urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "pet/findByStatus"),
            params=remove_none_from_dict({"status": status}),
            headers=self._client_wrapper.get_headers(),
            timeout=60,
        )
        if 200 <= _response.status_code < 300:
            return pydantic.parse_obj_as(typing.List[Pet], _response.json())  # type: ignore
        if _response.status_code == 400:
            raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json()))  # type: ignore
        try:
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def find_pets_by_tags(
        self, *, tags: typing.Optional[typing.Union[str, typing.List[str]]] = None
    ) -> typing.List[Pet]:
        """
        Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing.

        Parameters:
            - tags: typing.Optional[typing.Union[str, typing.List[str]]]. Tags to filter by
        ---
        from Petstore.client import AsyncPetstoreApi

        client = AsyncPetstoreApi(
            api_key="YOUR_API_KEY",
            token="YOUR_TOKEN",
        )
        await client.pet.find_pets_by_tags()
        """
        _response = await self._client_wrapper.httpx_client.request(
            "GET",
            urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "pet/findByTags"),
            params=remove_none_from_dict({"tags": tags}),
            headers=self._client_wrapper.get_headers(),
            timeout=60,
        )
        if 200 <= _response.status_code < 300:
            return pydantic.parse_obj_as(typing.List[Pet], _response.json())  # type: ignore
        if _response.status_code == 400:
            raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json()))  # type: ignore
        try:
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def get_pet_by_id(self, pet_id: int) -> Pet:
        """
        Returns a single pet

        Parameters:
            - pet_id: int. ID of pet to return
        ---
        from Petstore.client import AsyncPetstoreApi

        client = AsyncPetstoreApi(
            api_key="YOUR_API_KEY",
            token="YOUR_TOKEN",
        )
        await client.pet.get_pet_by_id(
            pet_id=1,
        )
        """
        _response = await self._client_wrapper.httpx_client.request(
            "GET",
            urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", f"pet/{pet_id}"),
            headers=self._client_wrapper.get_headers(),
            timeout=60,
        )
        if 200 <= _response.status_code < 300:
            return pydantic.parse_obj_as(Pet, _response.json())  # type: ignore
        if _response.status_code == 400:
            raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json()))  # type: ignore
        if _response.status_code == 404:
            raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json()))  # type: ignore
        try:
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def update_pet_with_form(
        self, pet_id: int, *, name: typing.Optional[str] = None, status: typing.Optional[str] = None
    ) -> None:
        """


        Parameters:
            - pet_id: int. ID of pet that needs to be updated

            - name: typing.Optional[str]. Name of pet that needs to be updated

            - status: typing.Optional[str]. Status of pet that needs to be updated
        ---
        from Petstore.client import AsyncPetstoreApi

        client = AsyncPetstoreApi(
            api_key="YOUR_API_KEY",
            token="YOUR_TOKEN",
        )
        await client.pet.update_pet_with_form(
            pet_id=1,
        )
        """
        _response = await self._client_wrapper.httpx_client.request(
            "POST",
            urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", f"pet/{pet_id}"),
            params=remove_none_from_dict({"name": name, "status": status}),
            headers=self._client_wrapper.get_headers(),
            timeout=60,
        )
        if 200 <= _response.status_code < 300:
            return
        try:
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def delete_pet(self, pet_id: int) -> None:
        """


        Parameters:
            - pet_id: int. Pet id to delete
        ---
        from Petstore.client import AsyncPetstoreApi

        client = AsyncPetstoreApi(
            api_key="YOUR_API_KEY",
            token="YOUR_TOKEN",
        )
        await client.pet.delete_pet(
            pet_id=1,
        )
        """
        _response = await self._client_wrapper.httpx_client.request(
            "DELETE",
            urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", f"pet/{pet_id}"),
            headers=self._client_wrapper.get_headers(),
            timeout=60,
        )
        if 200 <= _response.status_code < 300:
            return
        if _response.status_code == 400:
            raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json()))  # type: ignore
        try:
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def upload_file(self, pet_id: int, *, request: bytes) -> ApiResponse:
        """


        Parameters:
            - pet_id: int. ID of pet to update

            - request: bytes.
        """
        _response = await self._client_wrapper.httpx_client.request(
            "POST",
            urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", f"pet/{pet_id}/uploadImage"),
            content=request,
            headers=self._client_wrapper.get_headers(),
            timeout=60,
        )
        if 200 <= _response.status_code < 300:
            return pydantic.parse_obj_as(ApiResponse, _response.json())  # type: ignore
        try:
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)
