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

import typing
from ..core.client_wrapper import SyncClientWrapper
from ..core.request_options import RequestOptions
from ..core.pagination import SyncPager
from ..types.corpus import Corpus
from ..types.list_corpora_response import ListCorporaResponse
from ..core.pydantic_utilities import parse_obj_as
from ..errors.forbidden_error import ForbiddenError
from ..types.error import Error
from json.decoder import JSONDecodeError
from ..core.api_error import ApiError
from ..types.corpus_key import CorpusKey
from ..types.filter_attribute import FilterAttribute
from ..types.corpus_custom_dimension import CorpusCustomDimension
from ..errors.bad_request_error import BadRequestError
from ..types.bad_request_error_body import BadRequestErrorBody
from ..core.jsonable_encoder import jsonable_encoder
from ..errors.not_found_error import NotFoundError
from ..types.not_found_error_body import NotFoundErrorBody
from ..types.replace_filter_attributes_response import ReplaceFilterAttributesResponse
from ..core.client_wrapper import AsyncClientWrapper
from ..core.pagination import AsyncPager

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


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

    def list(
        self,
        *,
        limit: typing.Optional[int] = None,
        filter: typing.Optional[str] = None,
        page_key: typing.Optional[str] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> SyncPager[Corpus]:
        """
        List corpora in the account. The corpus objects that are returned are less
        detailed than the direct corpus retrieval operation.

        Parameters
        ----------
        limit : typing.Optional[int]
            The maximum number of corpora to return at one time.

        filter : typing.Optional[str]
            A regular expression to filter the corpora by their name or summary.

        page_key : typing.Optional[str]
            Used to retrieve the next page of corpora after the limit has been reached.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        SyncPager[Corpus]
            List of corpora.

        Examples
        --------
        from vectara import Vectara

        client = Vectara(
            api_key="YOUR_API_KEY",
            client_id="YOUR_CLIENT_ID",
            client_secret="YOUR_CLIENT_SECRET",
        )
        response = client.corpora.list()
        for item in response:
            yield item
        # alternatively, you can paginate page-by-page
        for page in response.iter_pages():
            yield page
        """
        _response = self._client_wrapper.httpx_client.request(
            "v2/corpora",
            base_url=self._client_wrapper.get_environment().default,
            method="GET",
            params={
                "limit": limit,
                "filter": filter,
                "page_key": page_key,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _parsed_response = typing.cast(
                    ListCorporaResponse,
                    parse_obj_as(
                        type_=ListCorporaResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                _has_next = False
                _get_next = None
                if _parsed_response.metadata is not None:
                    _parsed_next = _parsed_response.metadata.page_key
                    _has_next = _parsed_next is not None and _parsed_next != ""
                    _get_next = lambda: self.list(
                        limit=limit,
                        filter=filter,
                        page_key=_parsed_next,
                        request_options=request_options,
                    )
                _items = _parsed_response.corpora
                return SyncPager(has_next=_has_next, items=_items, get_next=_get_next)
            if _response.status_code == 403:
                raise ForbiddenError(
                    typing.cast(
                        Error,
                        parse_obj_as(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _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 create(
        self,
        *,
        key: CorpusKey,
        name: typing.Optional[str] = OMIT,
        description: typing.Optional[str] = OMIT,
        queries_are_answers: typing.Optional[bool] = OMIT,
        documents_are_questions: typing.Optional[bool] = OMIT,
        encoder_id: typing.Optional[str] = OMIT,
        filter_attributes: typing.Optional[typing.Sequence[FilterAttribute]] = OMIT,
        custom_dimensions: typing.Optional[typing.Sequence[CorpusCustomDimension]] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> Corpus:
        """
        Create a corpus, which is a container to store documents and associated metadata.

        Parameters
        ----------
        key : CorpusKey

        name : typing.Optional[str]
            The name for the corpus. This value defaults to the key.

        description : typing.Optional[str]
            Description for the corpus.

        queries_are_answers : typing.Optional[bool]
            Queries made to this corpus are considered answers, and not questions.

        documents_are_questions : typing.Optional[bool]
            Documents inside this corpus are considered questions, and not answers.

        encoder_id : typing.Optional[str]
            The encoder used by the corpus. This value defaults to the most recent Vectara encoder.

        filter_attributes : typing.Optional[typing.Sequence[FilterAttribute]]
            The new filter attributes of the corpus.
            If unset then the corpus will not have filter attributes.


        custom_dimensions : typing.Optional[typing.Sequence[CorpusCustomDimension]]
            A custom dimension is an additional numerical field attached to a document part. You
            can then multiply this numerical field with a query time custom dimension of the same
            name. This allows boosting (or deboosting) document parts for arbitrary reasons.
            This feature is only enabled for Scale customers.


        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        Corpus
            The corpus has been created.

        Examples
        --------
        from vectara import Vectara

        client = Vectara(
            api_key="YOUR_API_KEY",
            client_id="YOUR_CLIENT_ID",
            client_secret="YOUR_CLIENT_SECRET",
        )
        client.corpora.create(
            key="my-corpus",
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            "v2/corpora",
            base_url=self._client_wrapper.get_environment().default,
            method="POST",
            json={
                "key": key,
                "name": name,
                "description": description,
                "queries_are_answers": queries_are_answers,
                "documents_are_questions": documents_are_questions,
                "encoder_id": encoder_id,
                "filter_attributes": filter_attributes,
                "custom_dimensions": custom_dimensions,
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    Corpus,
                    parse_obj_as(
                        type_=Corpus,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 400:
                raise BadRequestError(
                    typing.cast(
                        BadRequestErrorBody,
                        parse_obj_as(
                            type_=BadRequestErrorBody,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 403:
                raise ForbiddenError(
                    typing.cast(
                        Error,
                        parse_obj_as(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _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(self, corpus_key: CorpusKey, *, request_options: typing.Optional[RequestOptions] = None) -> Corpus:
        """
        Get metadata about a corpus. This operation is not a method of searching a corpus.

        Parameters
        ----------
        corpus_key : CorpusKey
            The unique key identifying the corpus to retrieve.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        Corpus
            A corpus.

        Examples
        --------
        from vectara import Vectara

        client = Vectara(
            api_key="YOUR_API_KEY",
            client_id="YOUR_CLIENT_ID",
            client_secret="YOUR_CLIENT_SECRET",
        )
        client.corpora.get(
            corpus_key="my-corpus",
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v2/corpora/{jsonable_encoder(corpus_key)}",
            base_url=self._client_wrapper.get_environment().default,
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    Corpus,
                    parse_obj_as(
                        type_=Corpus,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 403:
                raise ForbiddenError(
                    typing.cast(
                        Error,
                        parse_obj_as(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    typing.cast(
                        NotFoundErrorBody,
                        parse_obj_as(
                            type_=NotFoundErrorBody,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _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(self, corpus_key: CorpusKey, *, request_options: typing.Optional[RequestOptions] = None) -> None:
        """
        Delete a corpus and all the data that it contains.

        Parameters
        ----------
        corpus_key : CorpusKey
            The unique key identifying the corpus to delete

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        None

        Examples
        --------
        from vectara import Vectara

        client = Vectara(
            api_key="YOUR_API_KEY",
            client_id="YOUR_CLIENT_ID",
            client_secret="YOUR_CLIENT_SECRET",
        )
        client.corpora.delete(
            corpus_key="my-corpus",
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v2/corpora/{jsonable_encoder(corpus_key)}",
            base_url=self._client_wrapper.get_environment().default,
            method="DELETE",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return
            if _response.status_code == 403:
                raise ForbiddenError(
                    typing.cast(
                        Error,
                        parse_obj_as(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    typing.cast(
                        NotFoundErrorBody,
                        parse_obj_as(
                            type_=NotFoundErrorBody,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _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(
        self,
        corpus_key: CorpusKey,
        *,
        enabled: typing.Optional[bool] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> Corpus:
        """
        Enable or disable a corpus.

        Parameters
        ----------
        corpus_key : CorpusKey
            The unique key identifying the corpus to update.

        enabled : typing.Optional[bool]
            Set whether or not the corpus is enabled. If unset then the corpus will remain in the same state.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        Corpus
            Successfully modified the corpus.

        Examples
        --------
        from vectara import Vectara

        client = Vectara(
            api_key="YOUR_API_KEY",
            client_id="YOUR_CLIENT_ID",
            client_secret="YOUR_CLIENT_SECRET",
        )
        client.corpora.update(
            corpus_key="my-corpus",
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v2/corpora/{jsonable_encoder(corpus_key)}",
            base_url=self._client_wrapper.get_environment().default,
            method="PATCH",
            json={
                "enabled": enabled,
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    Corpus,
                    parse_obj_as(
                        type_=Corpus,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 403:
                raise ForbiddenError(
                    typing.cast(
                        Error,
                        parse_obj_as(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    typing.cast(
                        NotFoundErrorBody,
                        parse_obj_as(
                            type_=NotFoundErrorBody,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _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 reset(self, corpus_key: CorpusKey, *, request_options: typing.Optional[RequestOptions] = None) -> None:
        """
        Resets a corpus, which removes all documents and data from the specified corpus, while keeping the corpus itself.

        Parameters
        ----------
        corpus_key : CorpusKey
            The unique key identifying the corpus to reset.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        None

        Examples
        --------
        from vectara import Vectara

        client = Vectara(
            api_key="YOUR_API_KEY",
            client_id="YOUR_CLIENT_ID",
            client_secret="YOUR_CLIENT_SECRET",
        )
        client.corpora.reset(
            corpus_key="my-corpus",
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v2/corpora/{jsonable_encoder(corpus_key)}/reset",
            base_url=self._client_wrapper.get_environment().default,
            method="POST",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return
            if _response.status_code == 403:
                raise ForbiddenError(
                    typing.cast(
                        Error,
                        parse_obj_as(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    typing.cast(
                        NotFoundErrorBody,
                        parse_obj_as(
                            type_=NotFoundErrorBody,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _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 replace_filters(
        self,
        corpus_key: CorpusKey,
        *,
        filter_attributes: typing.Sequence[FilterAttribute],
        request_options: typing.Optional[RequestOptions] = None,
    ) -> ReplaceFilterAttributesResponse:
        """
        Replace the filter attributes of a corpus. This does not happen immediately, but
        instead creates a job and will complete when that job completes. Until that
        job completes, using new filter attributes will not work.

        You can monitor the status of the filter change using the returned job id.

        Parameters
        ----------
        corpus_key : CorpusKey
            Key of the corpus to have filters replaced.

        filter_attributes : typing.Sequence[FilterAttribute]
            The new filter attributes.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        ReplaceFilterAttributesResponse
            Successfully created a job that will replace the filter attributes.

        Examples
        --------
        from vectara import FilterAttribute, Vectara

        client = Vectara(
            api_key="YOUR_API_KEY",
            client_id="YOUR_CLIENT_ID",
            client_secret="YOUR_CLIENT_SECRET",
        )
        client.corpora.replace_filters(
            corpus_key="my-corpus",
            filter_attributes=[
                FilterAttribute(
                    name="Title",
                    level="document",
                    type="integer",
                )
            ],
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v2/corpora/{jsonable_encoder(corpus_key)}/replace_filter_attributes",
            base_url=self._client_wrapper.get_environment().default,
            method="POST",
            json={
                "filter_attributes": filter_attributes,
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    ReplaceFilterAttributesResponse,
                    parse_obj_as(
                        type_=ReplaceFilterAttributesResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 403:
                raise ForbiddenError(
                    typing.cast(
                        Error,
                        parse_obj_as(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    typing.cast(
                        NotFoundErrorBody,
                        parse_obj_as(
                            type_=NotFoundErrorBody,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _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 AsyncCorporaClient:
    def __init__(self, *, client_wrapper: AsyncClientWrapper):
        self._client_wrapper = client_wrapper

    async def list(
        self,
        *,
        limit: typing.Optional[int] = None,
        filter: typing.Optional[str] = None,
        page_key: typing.Optional[str] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncPager[Corpus]:
        """
        List corpora in the account. The corpus objects that are returned are less
        detailed than the direct corpus retrieval operation.

        Parameters
        ----------
        limit : typing.Optional[int]
            The maximum number of corpora to return at one time.

        filter : typing.Optional[str]
            A regular expression to filter the corpora by their name or summary.

        page_key : typing.Optional[str]
            Used to retrieve the next page of corpora after the limit has been reached.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        AsyncPager[Corpus]
            List of corpora.

        Examples
        --------
        import asyncio

        from vectara import AsyncVectara

        client = AsyncVectara(
            api_key="YOUR_API_KEY",
            client_id="YOUR_CLIENT_ID",
            client_secret="YOUR_CLIENT_SECRET",
        )


        async def main() -> None:
            response = await client.corpora.list()
            async for item in response:
                yield item
            # alternatively, you can paginate page-by-page
            async for page in response.iter_pages():
                yield page


        asyncio.run(main())
        """
        _response = await self._client_wrapper.httpx_client.request(
            "v2/corpora",
            base_url=self._client_wrapper.get_environment().default,
            method="GET",
            params={
                "limit": limit,
                "filter": filter,
                "page_key": page_key,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _parsed_response = typing.cast(
                    ListCorporaResponse,
                    parse_obj_as(
                        type_=ListCorporaResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                _has_next = False
                _get_next = None
                if _parsed_response.metadata is not None:
                    _parsed_next = _parsed_response.metadata.page_key
                    _has_next = _parsed_next is not None and _parsed_next != ""
                    _get_next = lambda: self.list(
                        limit=limit,
                        filter=filter,
                        page_key=_parsed_next,
                        request_options=request_options,
                    )
                _items = _parsed_response.corpora
                return AsyncPager(has_next=_has_next, items=_items, get_next=_get_next)
            if _response.status_code == 403:
                raise ForbiddenError(
                    typing.cast(
                        Error,
                        parse_obj_as(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _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 create(
        self,
        *,
        key: CorpusKey,
        name: typing.Optional[str] = OMIT,
        description: typing.Optional[str] = OMIT,
        queries_are_answers: typing.Optional[bool] = OMIT,
        documents_are_questions: typing.Optional[bool] = OMIT,
        encoder_id: typing.Optional[str] = OMIT,
        filter_attributes: typing.Optional[typing.Sequence[FilterAttribute]] = OMIT,
        custom_dimensions: typing.Optional[typing.Sequence[CorpusCustomDimension]] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> Corpus:
        """
        Create a corpus, which is a container to store documents and associated metadata.

        Parameters
        ----------
        key : CorpusKey

        name : typing.Optional[str]
            The name for the corpus. This value defaults to the key.

        description : typing.Optional[str]
            Description for the corpus.

        queries_are_answers : typing.Optional[bool]
            Queries made to this corpus are considered answers, and not questions.

        documents_are_questions : typing.Optional[bool]
            Documents inside this corpus are considered questions, and not answers.

        encoder_id : typing.Optional[str]
            The encoder used by the corpus. This value defaults to the most recent Vectara encoder.

        filter_attributes : typing.Optional[typing.Sequence[FilterAttribute]]
            The new filter attributes of the corpus.
            If unset then the corpus will not have filter attributes.


        custom_dimensions : typing.Optional[typing.Sequence[CorpusCustomDimension]]
            A custom dimension is an additional numerical field attached to a document part. You
            can then multiply this numerical field with a query time custom dimension of the same
            name. This allows boosting (or deboosting) document parts for arbitrary reasons.
            This feature is only enabled for Scale customers.


        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        Corpus
            The corpus has been created.

        Examples
        --------
        import asyncio

        from vectara import AsyncVectara

        client = AsyncVectara(
            api_key="YOUR_API_KEY",
            client_id="YOUR_CLIENT_ID",
            client_secret="YOUR_CLIENT_SECRET",
        )


        async def main() -> None:
            await client.corpora.create(
                key="my-corpus",
            )


        asyncio.run(main())
        """
        _response = await self._client_wrapper.httpx_client.request(
            "v2/corpora",
            base_url=self._client_wrapper.get_environment().default,
            method="POST",
            json={
                "key": key,
                "name": name,
                "description": description,
                "queries_are_answers": queries_are_answers,
                "documents_are_questions": documents_are_questions,
                "encoder_id": encoder_id,
                "filter_attributes": filter_attributes,
                "custom_dimensions": custom_dimensions,
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    Corpus,
                    parse_obj_as(
                        type_=Corpus,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 400:
                raise BadRequestError(
                    typing.cast(
                        BadRequestErrorBody,
                        parse_obj_as(
                            type_=BadRequestErrorBody,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 403:
                raise ForbiddenError(
                    typing.cast(
                        Error,
                        parse_obj_as(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _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(self, corpus_key: CorpusKey, *, request_options: typing.Optional[RequestOptions] = None) -> Corpus:
        """
        Get metadata about a corpus. This operation is not a method of searching a corpus.

        Parameters
        ----------
        corpus_key : CorpusKey
            The unique key identifying the corpus to retrieve.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        Corpus
            A corpus.

        Examples
        --------
        import asyncio

        from vectara import AsyncVectara

        client = AsyncVectara(
            api_key="YOUR_API_KEY",
            client_id="YOUR_CLIENT_ID",
            client_secret="YOUR_CLIENT_SECRET",
        )


        async def main() -> None:
            await client.corpora.get(
                corpus_key="my-corpus",
            )


        asyncio.run(main())
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v2/corpora/{jsonable_encoder(corpus_key)}",
            base_url=self._client_wrapper.get_environment().default,
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    Corpus,
                    parse_obj_as(
                        type_=Corpus,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 403:
                raise ForbiddenError(
                    typing.cast(
                        Error,
                        parse_obj_as(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    typing.cast(
                        NotFoundErrorBody,
                        parse_obj_as(
                            type_=NotFoundErrorBody,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _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(self, corpus_key: CorpusKey, *, request_options: typing.Optional[RequestOptions] = None) -> None:
        """
        Delete a corpus and all the data that it contains.

        Parameters
        ----------
        corpus_key : CorpusKey
            The unique key identifying the corpus to delete

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        None

        Examples
        --------
        import asyncio

        from vectara import AsyncVectara

        client = AsyncVectara(
            api_key="YOUR_API_KEY",
            client_id="YOUR_CLIENT_ID",
            client_secret="YOUR_CLIENT_SECRET",
        )


        async def main() -> None:
            await client.corpora.delete(
                corpus_key="my-corpus",
            )


        asyncio.run(main())
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v2/corpora/{jsonable_encoder(corpus_key)}",
            base_url=self._client_wrapper.get_environment().default,
            method="DELETE",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return
            if _response.status_code == 403:
                raise ForbiddenError(
                    typing.cast(
                        Error,
                        parse_obj_as(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    typing.cast(
                        NotFoundErrorBody,
                        parse_obj_as(
                            type_=NotFoundErrorBody,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _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(
        self,
        corpus_key: CorpusKey,
        *,
        enabled: typing.Optional[bool] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> Corpus:
        """
        Enable or disable a corpus.

        Parameters
        ----------
        corpus_key : CorpusKey
            The unique key identifying the corpus to update.

        enabled : typing.Optional[bool]
            Set whether or not the corpus is enabled. If unset then the corpus will remain in the same state.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        Corpus
            Successfully modified the corpus.

        Examples
        --------
        import asyncio

        from vectara import AsyncVectara

        client = AsyncVectara(
            api_key="YOUR_API_KEY",
            client_id="YOUR_CLIENT_ID",
            client_secret="YOUR_CLIENT_SECRET",
        )


        async def main() -> None:
            await client.corpora.update(
                corpus_key="my-corpus",
            )


        asyncio.run(main())
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v2/corpora/{jsonable_encoder(corpus_key)}",
            base_url=self._client_wrapper.get_environment().default,
            method="PATCH",
            json={
                "enabled": enabled,
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    Corpus,
                    parse_obj_as(
                        type_=Corpus,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 403:
                raise ForbiddenError(
                    typing.cast(
                        Error,
                        parse_obj_as(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    typing.cast(
                        NotFoundErrorBody,
                        parse_obj_as(
                            type_=NotFoundErrorBody,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _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 reset(self, corpus_key: CorpusKey, *, request_options: typing.Optional[RequestOptions] = None) -> None:
        """
        Resets a corpus, which removes all documents and data from the specified corpus, while keeping the corpus itself.

        Parameters
        ----------
        corpus_key : CorpusKey
            The unique key identifying the corpus to reset.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        None

        Examples
        --------
        import asyncio

        from vectara import AsyncVectara

        client = AsyncVectara(
            api_key="YOUR_API_KEY",
            client_id="YOUR_CLIENT_ID",
            client_secret="YOUR_CLIENT_SECRET",
        )


        async def main() -> None:
            await client.corpora.reset(
                corpus_key="my-corpus",
            )


        asyncio.run(main())
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v2/corpora/{jsonable_encoder(corpus_key)}/reset",
            base_url=self._client_wrapper.get_environment().default,
            method="POST",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return
            if _response.status_code == 403:
                raise ForbiddenError(
                    typing.cast(
                        Error,
                        parse_obj_as(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    typing.cast(
                        NotFoundErrorBody,
                        parse_obj_as(
                            type_=NotFoundErrorBody,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _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 replace_filters(
        self,
        corpus_key: CorpusKey,
        *,
        filter_attributes: typing.Sequence[FilterAttribute],
        request_options: typing.Optional[RequestOptions] = None,
    ) -> ReplaceFilterAttributesResponse:
        """
        Replace the filter attributes of a corpus. This does not happen immediately, but
        instead creates a job and will complete when that job completes. Until that
        job completes, using new filter attributes will not work.

        You can monitor the status of the filter change using the returned job id.

        Parameters
        ----------
        corpus_key : CorpusKey
            Key of the corpus to have filters replaced.

        filter_attributes : typing.Sequence[FilterAttribute]
            The new filter attributes.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        ReplaceFilterAttributesResponse
            Successfully created a job that will replace the filter attributes.

        Examples
        --------
        import asyncio

        from vectara import AsyncVectara, FilterAttribute

        client = AsyncVectara(
            api_key="YOUR_API_KEY",
            client_id="YOUR_CLIENT_ID",
            client_secret="YOUR_CLIENT_SECRET",
        )


        async def main() -> None:
            await client.corpora.replace_filters(
                corpus_key="my-corpus",
                filter_attributes=[
                    FilterAttribute(
                        name="Title",
                        level="document",
                        type="integer",
                    )
                ],
            )


        asyncio.run(main())
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v2/corpora/{jsonable_encoder(corpus_key)}/replace_filter_attributes",
            base_url=self._client_wrapper.get_environment().default,
            method="POST",
            json={
                "filter_attributes": filter_attributes,
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return typing.cast(
                    ReplaceFilterAttributesResponse,
                    parse_obj_as(
                        type_=ReplaceFilterAttributesResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
            if _response.status_code == 403:
                raise ForbiddenError(
                    typing.cast(
                        Error,
                        parse_obj_as(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    typing.cast(
                        NotFoundErrorBody,
                        parse_obj_as(
                            type_=NotFoundErrorBody,  # type: ignore
                            object_=_response.json(),
                        ),
                    )
                )
            _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)
