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

import typing
import urllib.parse
import uuid
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.pydantic_utilities import pydantic_v1
from ..core.query_encoder import encode_query
from ..core.remove_none_from_dict import remove_none_from_dict
from ..core.request_options import RequestOptions
from .types.create_document_collection_response import CreateDocumentCollectionResponse
from .types.distance_metric import DistanceMetric
from .types.list_document_collection_response import ListDocumentCollectionResponse
from .types.metadata_schema import MetadataSchema

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


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

    def create_document_collection(
        self,
        *,
        collection_name: str,
        embeddings_model: typing.Optional[str] = OMIT,
        distance_metric: typing.Optional[DistanceMetric] = OMIT,
        custom_metadata_schema: typing.Optional[MetadataSchema] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> CreateDocumentCollectionResponse:
        """
        Create a collection of related documents with a shared metadata schema that you can search across.

        Parameters
        ----------
        collection_name : str
            A unique name for the document collection.

        embeddings_model : typing.Optional[str]
            The embeddings model to use for the document collection.


        distance_metric : typing.Optional[DistanceMetric]
            The distance metric to use for the document collection.


        custom_metadata_schema : typing.Optional[MetadataSchema]
            Any custom metadata fields for this collection.


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

        Returns
        -------
        CreateDocumentCollectionResponse

        Examples
        --------
        from credal import MetadataField, MetadataSchema
        from credal.client import CredalApi

        client = CredalApi(
            api_key="YOUR_API_KEY",
        )
        client.document_collections.create_document_collection(
            collection_name="Customer Meeting Transcripts",
            embeddings_model="text-embedding-ada-002",
            distance_metric="EUCLIDEAN",
            custom_metadata_schema=MetadataSchema(
                fields=[
                    MetadataField(
                        name="customerName",
                        type="STRING",
                    ),
                    MetadataField(
                        name="meetingDate",
                        type="DATETIME",
                    ),
                ],
            ),
        )
        """
        _request: typing.Dict[str, typing.Any] = {"collectionName": collection_name}
        if embeddings_model is not OMIT:
            _request["embeddingsModel"] = embeddings_model
        if distance_metric is not OMIT:
            _request["distanceMetric"] = distance_metric
        if custom_metadata_schema is not OMIT:
            _request["customMetadataSchema"] = custom_metadata_schema
        _response = self._client_wrapper.httpx_client.request(
            method="POST",
            url=urllib.parse.urljoin(
                f"{self._client_wrapper.get_base_url()}/", "v0/documentCollections/createDocumentCollection"
            ),
            params=encode_query(
                jsonable_encoder(
                    request_options.get("additional_query_parameters") if request_options is not None else None
                )
            ),
            json=jsonable_encoder(_request)
            if request_options is None or request_options.get("additional_body_parameters") is None
            else {
                **jsonable_encoder(_request),
                **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))),
            },
            headers=jsonable_encoder(
                remove_none_from_dict(
                    {
                        **self._client_wrapper.get_headers(),
                        **(request_options.get("additional_headers", {}) if request_options is not None else {}),
                    }
                )
            ),
            timeout=request_options.get("timeout_in_seconds")
            if request_options is not None and request_options.get("timeout_in_seconds") is not None
            else self._client_wrapper.get_timeout(),
            retries=0,
            max_retries=request_options.get("max_retries") if request_options is not None else 0,  # type: ignore
        )
        if 200 <= _response.status_code < 300:
            return pydantic_v1.parse_obj_as(CreateDocumentCollectionResponse, _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 delete_document_collection(
        self, *, document_collection_id: uuid.UUID, request_options: typing.Optional[RequestOptions] = None
    ) -> None:
        """
        Delete a document collection given its ID.

        Parameters
        ----------
        document_collection_id : uuid.UUID

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

        Returns
        -------
        None

        Examples
        --------
        import uuid

        from credal.client import CredalApi

        client = CredalApi(
            api_key="YOUR_API_KEY",
        )
        client.document_collections.delete_document_collection(
            document_collection_id=uuid.UUID(
                "82e4b12a-6990-45d4-8ebd-85c00e030c24",
            ),
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            method="POST",
            url=urllib.parse.urljoin(
                f"{self._client_wrapper.get_base_url()}/", "v0/documentCollections/deleteDocumentCollection"
            ),
            params=encode_query(
                jsonable_encoder(
                    remove_none_from_dict(
                        {
                            "documentCollectionId": jsonable_encoder(document_collection_id),
                            **(
                                request_options.get("additional_query_parameters", {})
                                if request_options is not None
                                else {}
                            ),
                        }
                    )
                )
            ),
            json=jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))
            if request_options is not None
            else None,
            headers=jsonable_encoder(
                remove_none_from_dict(
                    {
                        **self._client_wrapper.get_headers(),
                        **(request_options.get("additional_headers", {}) if request_options is not None else {}),
                    }
                )
            ),
            timeout=request_options.get("timeout_in_seconds")
            if request_options is not None and request_options.get("timeout_in_seconds") is not None
            else self._client_wrapper.get_timeout(),
            retries=0,
            max_retries=request_options.get("max_retries") if request_options is not None else 0,  # type: ignore
        )
        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 list_documents_in_collection(
        self, *, document_collection_id: uuid.UUID, request_options: typing.Optional[RequestOptions] = None
    ) -> ListDocumentCollectionResponse:
        """
        List all documents in a document collection.

        Parameters
        ----------
        document_collection_id : uuid.UUID

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

        Returns
        -------
        ListDocumentCollectionResponse

        Examples
        --------
        import uuid

        from credal.client import CredalApi

        client = CredalApi(
            api_key="YOUR_API_KEY",
        )
        client.document_collections.list_documents_in_collection(
            document_collection_id=uuid.UUID(
                "82e4b12a-6990-45d4-8ebd-85c00e030c24",
            ),
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            method="POST",
            url=urllib.parse.urljoin(
                f"{self._client_wrapper.get_base_url()}/", "v0/documentCollections/listDocumentsInCollection"
            ),
            params=encode_query(
                jsonable_encoder(
                    remove_none_from_dict(
                        {
                            "documentCollectionId": jsonable_encoder(document_collection_id),
                            **(
                                request_options.get("additional_query_parameters", {})
                                if request_options is not None
                                else {}
                            ),
                        }
                    )
                )
            ),
            json=jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))
            if request_options is not None
            else None,
            headers=jsonable_encoder(
                remove_none_from_dict(
                    {
                        **self._client_wrapper.get_headers(),
                        **(request_options.get("additional_headers", {}) if request_options is not None else {}),
                    }
                )
            ),
            timeout=request_options.get("timeout_in_seconds")
            if request_options is not None and request_options.get("timeout_in_seconds") is not None
            else self._client_wrapper.get_timeout(),
            retries=0,
            max_retries=request_options.get("max_retries") if request_options is not None else 0,  # type: ignore
        )
        if 200 <= _response.status_code < 300:
            return pydantic_v1.parse_obj_as(ListDocumentCollectionResponse, _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 add_document_to_collection(
        self,
        *,
        document_id: uuid.UUID,
        document_collection_id: uuid.UUID,
        custom_metadata: typing.Dict[str, str],
        request_options: typing.Optional[RequestOptions] = None,
    ) -> None:
        """
        Add a document to a document collection. Credal automatically chunks the document and runs the collection's embeddings model on each chunk.
        If you want to chunk the document yourself you can use the addDocumentChunksToCollection endpoint.

        Parameters
        ----------
        document_id : uuid.UUID

        document_collection_id : uuid.UUID

        custom_metadata : typing.Dict[str, str]
            The custom metadata for the document. The fields must match the custom metadata schema for the document collection.


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

        Returns
        -------
        None

        Examples
        --------
        import uuid

        from credal.client import CredalApi

        client = CredalApi(
            api_key="YOUR_API_KEY",
        )
        client.document_collections.add_document_to_collection(
            document_collection_id=uuid.UUID(
                "82e4b12a-6990-45d4-8ebd-85c00e030c24",
            ),
            document_id=uuid.UUID(
                "82e4b12a-6990-45d4-8ebd-85c00e030c24",
            ),
            custom_metadata={
                "customerName": "Credal",
                "meetingDate": "2023-11-06T23:03:42.056Z",
            },
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            method="POST",
            url=urllib.parse.urljoin(
                f"{self._client_wrapper.get_base_url()}/", "v0/documentCollections/addDocumentToCollection"
            ),
            params=encode_query(
                jsonable_encoder(
                    request_options.get("additional_query_parameters") if request_options is not None else None
                )
            ),
            json=jsonable_encoder(
                {
                    "documentId": document_id,
                    "documentCollectionId": document_collection_id,
                    "customMetadata": custom_metadata,
                }
            )
            if request_options is None or request_options.get("additional_body_parameters") is None
            else {
                **jsonable_encoder(
                    {
                        "documentId": document_id,
                        "documentCollectionId": document_collection_id,
                        "customMetadata": custom_metadata,
                    }
                ),
                **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))),
            },
            headers=jsonable_encoder(
                remove_none_from_dict(
                    {
                        **self._client_wrapper.get_headers(),
                        **(request_options.get("additional_headers", {}) if request_options is not None else {}),
                    }
                )
            ),
            timeout=request_options.get("timeout_in_seconds")
            if request_options is not None and request_options.get("timeout_in_seconds") is not None
            else self._client_wrapper.get_timeout(),
            retries=0,
            max_retries=request_options.get("max_retries") if request_options is not None else 0,  # type: ignore
        )
        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 add_document_chunks_to_collection(
        self,
        *,
        document_id: uuid.UUID,
        document_collection_id: uuid.UUID,
        chunks: typing.Sequence[str],
        custom_metadata: typing.Dict[str, str],
        request_options: typing.Optional[RequestOptions] = None,
    ) -> None:
        """
        Add the specified document chunks to a document collection. Credal automatically runs the collection's embeddings model on each chunk.

        Parameters
        ----------
        document_id : uuid.UUID

        document_collection_id : uuid.UUID

        chunks : typing.Sequence[str]
            The document chunks to add to the document collection. Credal will run the collection's embeddings model on each chunk.


        custom_metadata : typing.Dict[str, str]
            The custom metadata for the document. The fields must match the custom metadata schema for the document collection.


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

        Returns
        -------
        None

        Examples
        --------
        import uuid

        from credal.client import CredalApi

        client = CredalApi(
            api_key="YOUR_API_KEY",
        )
        client.document_collections.add_document_chunks_to_collection(
            document_collection_id=uuid.UUID(
                "82e4b12a-6990-45d4-8ebd-85c00e030c24",
            ),
            document_id=uuid.UUID(
                "82e4b12a-6990-45d4-8ebd-85c00e030c24",
            ),
            chunks=[
                "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
                "Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.",
                "Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.",
            ],
            custom_metadata={
                "customerName": "Credal",
                "meetingDate": "2023-11-06T23:03:42.056Z",
            },
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            method="POST",
            url=urllib.parse.urljoin(
                f"{self._client_wrapper.get_base_url()}/", "v0/documentCollections/addDocumentChunksToCollection"
            ),
            params=encode_query(
                jsonable_encoder(
                    request_options.get("additional_query_parameters") if request_options is not None else None
                )
            ),
            json=jsonable_encoder(
                {
                    "documentId": document_id,
                    "documentCollectionId": document_collection_id,
                    "chunks": chunks,
                    "customMetadata": custom_metadata,
                }
            )
            if request_options is None or request_options.get("additional_body_parameters") is None
            else {
                **jsonable_encoder(
                    {
                        "documentId": document_id,
                        "documentCollectionId": document_collection_id,
                        "chunks": chunks,
                        "customMetadata": custom_metadata,
                    }
                ),
                **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))),
            },
            headers=jsonable_encoder(
                remove_none_from_dict(
                    {
                        **self._client_wrapper.get_headers(),
                        **(request_options.get("additional_headers", {}) if request_options is not None else {}),
                    }
                )
            ),
            timeout=request_options.get("timeout_in_seconds")
            if request_options is not None and request_options.get("timeout_in_seconds") is not None
            else self._client_wrapper.get_timeout(),
            retries=0,
            max_retries=request_options.get("max_retries") if request_options is not None else 0,  # type: ignore
        )
        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 reindex_document_in_collection(
        self,
        *,
        document_id: uuid.UUID,
        document_collection_id: uuid.UUID,
        custom_metadata: typing.Optional[typing.Dict[str, str]] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> None:
        """
        Reindex a document in a document collection. Credal automatically deletes the existing chunks, re-chunks the document's latest contents and runs the collection's embeddings model on each chunk.
        You can optionally provide new custom metadata for the document.

        Parameters
        ----------
        document_id : uuid.UUID

        document_collection_id : uuid.UUID

        custom_metadata : typing.Optional[typing.Dict[str, str]]
            The optional custom metadata for the document. The fields must match the custom metadata schema for the document collection.
            If not specified, Credal will use the existing metadata for the document.


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

        Returns
        -------
        None

        Examples
        --------
        import uuid

        from credal.client import CredalApi

        client = CredalApi(
            api_key="YOUR_API_KEY",
        )
        client.document_collections.reindex_document_in_collection(
            document_collection_id=uuid.UUID(
                "82e4b12a-6990-45d4-8ebd-85c00e030c24",
            ),
            document_id=uuid.UUID(
                "82e4b12a-6990-45d4-8ebd-85c00e030c24",
            ),
        )
        """
        _request: typing.Dict[str, typing.Any] = {
            "documentId": document_id,
            "documentCollectionId": document_collection_id,
        }
        if custom_metadata is not OMIT:
            _request["customMetadata"] = custom_metadata
        _response = self._client_wrapper.httpx_client.request(
            method="POST",
            url=urllib.parse.urljoin(
                f"{self._client_wrapper.get_base_url()}/", "v0/documentCollections/reindexDocumentInCollection"
            ),
            params=encode_query(
                jsonable_encoder(
                    request_options.get("additional_query_parameters") if request_options is not None else None
                )
            ),
            json=jsonable_encoder(_request)
            if request_options is None or request_options.get("additional_body_parameters") is None
            else {
                **jsonable_encoder(_request),
                **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))),
            },
            headers=jsonable_encoder(
                remove_none_from_dict(
                    {
                        **self._client_wrapper.get_headers(),
                        **(request_options.get("additional_headers", {}) if request_options is not None else {}),
                    }
                )
            ),
            timeout=request_options.get("timeout_in_seconds")
            if request_options is not None and request_options.get("timeout_in_seconds") is not None
            else self._client_wrapper.get_timeout(),
            retries=0,
            max_retries=request_options.get("max_retries") if request_options is not None else 0,  # type: ignore
        )
        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 remove_document_from_collection(
        self,
        *,
        document_id: uuid.UUID,
        document_collection_id: uuid.UUID,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> None:
        """
        Remove a document from a document collection. The document still exists in the document catalog but will not longer be searchable in
        this document collection.

        Parameters
        ----------
        document_id : uuid.UUID

        document_collection_id : uuid.UUID

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

        Returns
        -------
        None

        Examples
        --------
        import uuid

        from credal.client import CredalApi

        client = CredalApi(
            api_key="YOUR_API_KEY",
        )
        client.document_collections.remove_document_from_collection(
            document_collection_id=uuid.UUID(
                "82e4b12a-6990-45d4-8ebd-85c00e030c24",
            ),
            document_id=uuid.UUID(
                "82e4b12a-6990-45d4-8ebd-85c00e030c24",
            ),
        )
        """
        _response = self._client_wrapper.httpx_client.request(
            method="POST",
            url=urllib.parse.urljoin(
                f"{self._client_wrapper.get_base_url()}/", "v0/documentCollections/removeDocumentFromCollection"
            ),
            params=encode_query(
                jsonable_encoder(
                    request_options.get("additional_query_parameters") if request_options is not None else None
                )
            ),
            json=jsonable_encoder({"documentId": document_id, "documentCollectionId": document_collection_id})
            if request_options is None or request_options.get("additional_body_parameters") is None
            else {
                **jsonable_encoder({"documentId": document_id, "documentCollectionId": document_collection_id}),
                **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))),
            },
            headers=jsonable_encoder(
                remove_none_from_dict(
                    {
                        **self._client_wrapper.get_headers(),
                        **(request_options.get("additional_headers", {}) if request_options is not None else {}),
                    }
                )
            ),
            timeout=request_options.get("timeout_in_seconds")
            if request_options is not None and request_options.get("timeout_in_seconds") is not None
            else self._client_wrapper.get_timeout(),
            retries=0,
            max_retries=request_options.get("max_retries") if request_options is not None else 0,  # type: ignore
        )
        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)


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

    async def create_document_collection(
        self,
        *,
        collection_name: str,
        embeddings_model: typing.Optional[str] = OMIT,
        distance_metric: typing.Optional[DistanceMetric] = OMIT,
        custom_metadata_schema: typing.Optional[MetadataSchema] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> CreateDocumentCollectionResponse:
        """
        Create a collection of related documents with a shared metadata schema that you can search across.

        Parameters
        ----------
        collection_name : str
            A unique name for the document collection.

        embeddings_model : typing.Optional[str]
            The embeddings model to use for the document collection.


        distance_metric : typing.Optional[DistanceMetric]
            The distance metric to use for the document collection.


        custom_metadata_schema : typing.Optional[MetadataSchema]
            Any custom metadata fields for this collection.


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

        Returns
        -------
        CreateDocumentCollectionResponse

        Examples
        --------
        from credal import MetadataField, MetadataSchema
        from credal.client import AsyncCredalApi

        client = AsyncCredalApi(
            api_key="YOUR_API_KEY",
        )
        await client.document_collections.create_document_collection(
            collection_name="Customer Meeting Transcripts",
            embeddings_model="text-embedding-ada-002",
            distance_metric="EUCLIDEAN",
            custom_metadata_schema=MetadataSchema(
                fields=[
                    MetadataField(
                        name="customerName",
                        type="STRING",
                    ),
                    MetadataField(
                        name="meetingDate",
                        type="DATETIME",
                    ),
                ],
            ),
        )
        """
        _request: typing.Dict[str, typing.Any] = {"collectionName": collection_name}
        if embeddings_model is not OMIT:
            _request["embeddingsModel"] = embeddings_model
        if distance_metric is not OMIT:
            _request["distanceMetric"] = distance_metric
        if custom_metadata_schema is not OMIT:
            _request["customMetadataSchema"] = custom_metadata_schema
        _response = await self._client_wrapper.httpx_client.request(
            method="POST",
            url=urllib.parse.urljoin(
                f"{self._client_wrapper.get_base_url()}/", "v0/documentCollections/createDocumentCollection"
            ),
            params=encode_query(
                jsonable_encoder(
                    request_options.get("additional_query_parameters") if request_options is not None else None
                )
            ),
            json=jsonable_encoder(_request)
            if request_options is None or request_options.get("additional_body_parameters") is None
            else {
                **jsonable_encoder(_request),
                **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))),
            },
            headers=jsonable_encoder(
                remove_none_from_dict(
                    {
                        **self._client_wrapper.get_headers(),
                        **(request_options.get("additional_headers", {}) if request_options is not None else {}),
                    }
                )
            ),
            timeout=request_options.get("timeout_in_seconds")
            if request_options is not None and request_options.get("timeout_in_seconds") is not None
            else self._client_wrapper.get_timeout(),
            retries=0,
            max_retries=request_options.get("max_retries") if request_options is not None else 0,  # type: ignore
        )
        if 200 <= _response.status_code < 300:
            return pydantic_v1.parse_obj_as(CreateDocumentCollectionResponse, _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 delete_document_collection(
        self, *, document_collection_id: uuid.UUID, request_options: typing.Optional[RequestOptions] = None
    ) -> None:
        """
        Delete a document collection given its ID.

        Parameters
        ----------
        document_collection_id : uuid.UUID

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

        Returns
        -------
        None

        Examples
        --------
        import uuid

        from credal.client import AsyncCredalApi

        client = AsyncCredalApi(
            api_key="YOUR_API_KEY",
        )
        await client.document_collections.delete_document_collection(
            document_collection_id=uuid.UUID(
                "82e4b12a-6990-45d4-8ebd-85c00e030c24",
            ),
        )
        """
        _response = await self._client_wrapper.httpx_client.request(
            method="POST",
            url=urllib.parse.urljoin(
                f"{self._client_wrapper.get_base_url()}/", "v0/documentCollections/deleteDocumentCollection"
            ),
            params=encode_query(
                jsonable_encoder(
                    remove_none_from_dict(
                        {
                            "documentCollectionId": jsonable_encoder(document_collection_id),
                            **(
                                request_options.get("additional_query_parameters", {})
                                if request_options is not None
                                else {}
                            ),
                        }
                    )
                )
            ),
            json=jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))
            if request_options is not None
            else None,
            headers=jsonable_encoder(
                remove_none_from_dict(
                    {
                        **self._client_wrapper.get_headers(),
                        **(request_options.get("additional_headers", {}) if request_options is not None else {}),
                    }
                )
            ),
            timeout=request_options.get("timeout_in_seconds")
            if request_options is not None and request_options.get("timeout_in_seconds") is not None
            else self._client_wrapper.get_timeout(),
            retries=0,
            max_retries=request_options.get("max_retries") if request_options is not None else 0,  # type: ignore
        )
        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 list_documents_in_collection(
        self, *, document_collection_id: uuid.UUID, request_options: typing.Optional[RequestOptions] = None
    ) -> ListDocumentCollectionResponse:
        """
        List all documents in a document collection.

        Parameters
        ----------
        document_collection_id : uuid.UUID

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

        Returns
        -------
        ListDocumentCollectionResponse

        Examples
        --------
        import uuid

        from credal.client import AsyncCredalApi

        client = AsyncCredalApi(
            api_key="YOUR_API_KEY",
        )
        await client.document_collections.list_documents_in_collection(
            document_collection_id=uuid.UUID(
                "82e4b12a-6990-45d4-8ebd-85c00e030c24",
            ),
        )
        """
        _response = await self._client_wrapper.httpx_client.request(
            method="POST",
            url=urllib.parse.urljoin(
                f"{self._client_wrapper.get_base_url()}/", "v0/documentCollections/listDocumentsInCollection"
            ),
            params=encode_query(
                jsonable_encoder(
                    remove_none_from_dict(
                        {
                            "documentCollectionId": jsonable_encoder(document_collection_id),
                            **(
                                request_options.get("additional_query_parameters", {})
                                if request_options is not None
                                else {}
                            ),
                        }
                    )
                )
            ),
            json=jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))
            if request_options is not None
            else None,
            headers=jsonable_encoder(
                remove_none_from_dict(
                    {
                        **self._client_wrapper.get_headers(),
                        **(request_options.get("additional_headers", {}) if request_options is not None else {}),
                    }
                )
            ),
            timeout=request_options.get("timeout_in_seconds")
            if request_options is not None and request_options.get("timeout_in_seconds") is not None
            else self._client_wrapper.get_timeout(),
            retries=0,
            max_retries=request_options.get("max_retries") if request_options is not None else 0,  # type: ignore
        )
        if 200 <= _response.status_code < 300:
            return pydantic_v1.parse_obj_as(ListDocumentCollectionResponse, _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 add_document_to_collection(
        self,
        *,
        document_id: uuid.UUID,
        document_collection_id: uuid.UUID,
        custom_metadata: typing.Dict[str, str],
        request_options: typing.Optional[RequestOptions] = None,
    ) -> None:
        """
        Add a document to a document collection. Credal automatically chunks the document and runs the collection's embeddings model on each chunk.
        If you want to chunk the document yourself you can use the addDocumentChunksToCollection endpoint.

        Parameters
        ----------
        document_id : uuid.UUID

        document_collection_id : uuid.UUID

        custom_metadata : typing.Dict[str, str]
            The custom metadata for the document. The fields must match the custom metadata schema for the document collection.


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

        Returns
        -------
        None

        Examples
        --------
        import uuid

        from credal.client import AsyncCredalApi

        client = AsyncCredalApi(
            api_key="YOUR_API_KEY",
        )
        await client.document_collections.add_document_to_collection(
            document_collection_id=uuid.UUID(
                "82e4b12a-6990-45d4-8ebd-85c00e030c24",
            ),
            document_id=uuid.UUID(
                "82e4b12a-6990-45d4-8ebd-85c00e030c24",
            ),
            custom_metadata={
                "customerName": "Credal",
                "meetingDate": "2023-11-06T23:03:42.056Z",
            },
        )
        """
        _response = await self._client_wrapper.httpx_client.request(
            method="POST",
            url=urllib.parse.urljoin(
                f"{self._client_wrapper.get_base_url()}/", "v0/documentCollections/addDocumentToCollection"
            ),
            params=encode_query(
                jsonable_encoder(
                    request_options.get("additional_query_parameters") if request_options is not None else None
                )
            ),
            json=jsonable_encoder(
                {
                    "documentId": document_id,
                    "documentCollectionId": document_collection_id,
                    "customMetadata": custom_metadata,
                }
            )
            if request_options is None or request_options.get("additional_body_parameters") is None
            else {
                **jsonable_encoder(
                    {
                        "documentId": document_id,
                        "documentCollectionId": document_collection_id,
                        "customMetadata": custom_metadata,
                    }
                ),
                **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))),
            },
            headers=jsonable_encoder(
                remove_none_from_dict(
                    {
                        **self._client_wrapper.get_headers(),
                        **(request_options.get("additional_headers", {}) if request_options is not None else {}),
                    }
                )
            ),
            timeout=request_options.get("timeout_in_seconds")
            if request_options is not None and request_options.get("timeout_in_seconds") is not None
            else self._client_wrapper.get_timeout(),
            retries=0,
            max_retries=request_options.get("max_retries") if request_options is not None else 0,  # type: ignore
        )
        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 add_document_chunks_to_collection(
        self,
        *,
        document_id: uuid.UUID,
        document_collection_id: uuid.UUID,
        chunks: typing.Sequence[str],
        custom_metadata: typing.Dict[str, str],
        request_options: typing.Optional[RequestOptions] = None,
    ) -> None:
        """
        Add the specified document chunks to a document collection. Credal automatically runs the collection's embeddings model on each chunk.

        Parameters
        ----------
        document_id : uuid.UUID

        document_collection_id : uuid.UUID

        chunks : typing.Sequence[str]
            The document chunks to add to the document collection. Credal will run the collection's embeddings model on each chunk.


        custom_metadata : typing.Dict[str, str]
            The custom metadata for the document. The fields must match the custom metadata schema for the document collection.


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

        Returns
        -------
        None

        Examples
        --------
        import uuid

        from credal.client import AsyncCredalApi

        client = AsyncCredalApi(
            api_key="YOUR_API_KEY",
        )
        await client.document_collections.add_document_chunks_to_collection(
            document_collection_id=uuid.UUID(
                "82e4b12a-6990-45d4-8ebd-85c00e030c24",
            ),
            document_id=uuid.UUID(
                "82e4b12a-6990-45d4-8ebd-85c00e030c24",
            ),
            chunks=[
                "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
                "Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.",
                "Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.",
            ],
            custom_metadata={
                "customerName": "Credal",
                "meetingDate": "2023-11-06T23:03:42.056Z",
            },
        )
        """
        _response = await self._client_wrapper.httpx_client.request(
            method="POST",
            url=urllib.parse.urljoin(
                f"{self._client_wrapper.get_base_url()}/", "v0/documentCollections/addDocumentChunksToCollection"
            ),
            params=encode_query(
                jsonable_encoder(
                    request_options.get("additional_query_parameters") if request_options is not None else None
                )
            ),
            json=jsonable_encoder(
                {
                    "documentId": document_id,
                    "documentCollectionId": document_collection_id,
                    "chunks": chunks,
                    "customMetadata": custom_metadata,
                }
            )
            if request_options is None or request_options.get("additional_body_parameters") is None
            else {
                **jsonable_encoder(
                    {
                        "documentId": document_id,
                        "documentCollectionId": document_collection_id,
                        "chunks": chunks,
                        "customMetadata": custom_metadata,
                    }
                ),
                **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))),
            },
            headers=jsonable_encoder(
                remove_none_from_dict(
                    {
                        **self._client_wrapper.get_headers(),
                        **(request_options.get("additional_headers", {}) if request_options is not None else {}),
                    }
                )
            ),
            timeout=request_options.get("timeout_in_seconds")
            if request_options is not None and request_options.get("timeout_in_seconds") is not None
            else self._client_wrapper.get_timeout(),
            retries=0,
            max_retries=request_options.get("max_retries") if request_options is not None else 0,  # type: ignore
        )
        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 reindex_document_in_collection(
        self,
        *,
        document_id: uuid.UUID,
        document_collection_id: uuid.UUID,
        custom_metadata: typing.Optional[typing.Dict[str, str]] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> None:
        """
        Reindex a document in a document collection. Credal automatically deletes the existing chunks, re-chunks the document's latest contents and runs the collection's embeddings model on each chunk.
        You can optionally provide new custom metadata for the document.

        Parameters
        ----------
        document_id : uuid.UUID

        document_collection_id : uuid.UUID

        custom_metadata : typing.Optional[typing.Dict[str, str]]
            The optional custom metadata for the document. The fields must match the custom metadata schema for the document collection.
            If not specified, Credal will use the existing metadata for the document.


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

        Returns
        -------
        None

        Examples
        --------
        import uuid

        from credal.client import AsyncCredalApi

        client = AsyncCredalApi(
            api_key="YOUR_API_KEY",
        )
        await client.document_collections.reindex_document_in_collection(
            document_collection_id=uuid.UUID(
                "82e4b12a-6990-45d4-8ebd-85c00e030c24",
            ),
            document_id=uuid.UUID(
                "82e4b12a-6990-45d4-8ebd-85c00e030c24",
            ),
        )
        """
        _request: typing.Dict[str, typing.Any] = {
            "documentId": document_id,
            "documentCollectionId": document_collection_id,
        }
        if custom_metadata is not OMIT:
            _request["customMetadata"] = custom_metadata
        _response = await self._client_wrapper.httpx_client.request(
            method="POST",
            url=urllib.parse.urljoin(
                f"{self._client_wrapper.get_base_url()}/", "v0/documentCollections/reindexDocumentInCollection"
            ),
            params=encode_query(
                jsonable_encoder(
                    request_options.get("additional_query_parameters") if request_options is not None else None
                )
            ),
            json=jsonable_encoder(_request)
            if request_options is None or request_options.get("additional_body_parameters") is None
            else {
                **jsonable_encoder(_request),
                **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))),
            },
            headers=jsonable_encoder(
                remove_none_from_dict(
                    {
                        **self._client_wrapper.get_headers(),
                        **(request_options.get("additional_headers", {}) if request_options is not None else {}),
                    }
                )
            ),
            timeout=request_options.get("timeout_in_seconds")
            if request_options is not None and request_options.get("timeout_in_seconds") is not None
            else self._client_wrapper.get_timeout(),
            retries=0,
            max_retries=request_options.get("max_retries") if request_options is not None else 0,  # type: ignore
        )
        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 remove_document_from_collection(
        self,
        *,
        document_id: uuid.UUID,
        document_collection_id: uuid.UUID,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> None:
        """
        Remove a document from a document collection. The document still exists in the document catalog but will not longer be searchable in
        this document collection.

        Parameters
        ----------
        document_id : uuid.UUID

        document_collection_id : uuid.UUID

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

        Returns
        -------
        None

        Examples
        --------
        import uuid

        from credal.client import AsyncCredalApi

        client = AsyncCredalApi(
            api_key="YOUR_API_KEY",
        )
        await client.document_collections.remove_document_from_collection(
            document_collection_id=uuid.UUID(
                "82e4b12a-6990-45d4-8ebd-85c00e030c24",
            ),
            document_id=uuid.UUID(
                "82e4b12a-6990-45d4-8ebd-85c00e030c24",
            ),
        )
        """
        _response = await self._client_wrapper.httpx_client.request(
            method="POST",
            url=urllib.parse.urljoin(
                f"{self._client_wrapper.get_base_url()}/", "v0/documentCollections/removeDocumentFromCollection"
            ),
            params=encode_query(
                jsonable_encoder(
                    request_options.get("additional_query_parameters") if request_options is not None else None
                )
            ),
            json=jsonable_encoder({"documentId": document_id, "documentCollectionId": document_collection_id})
            if request_options is None or request_options.get("additional_body_parameters") is None
            else {
                **jsonable_encoder({"documentId": document_id, "documentCollectionId": document_collection_id}),
                **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))),
            },
            headers=jsonable_encoder(
                remove_none_from_dict(
                    {
                        **self._client_wrapper.get_headers(),
                        **(request_options.get("additional_headers", {}) if request_options is not None else {}),
                    }
                )
            ),
            timeout=request_options.get("timeout_in_seconds")
            if request_options is not None and request_options.get("timeout_in_seconds") is not None
            else self._client_wrapper.get_timeout(),
            retries=0,
            max_retries=request_options.get("max_retries") if request_options is not None else 0,  # type: ignore
        )
        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)
