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

import typing
from json.decoder import JSONDecodeError

from .. import core
from ..common.types.custom_metadata_value import CustomMetadataValue
from ..core.api_error import ApiError
from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
from ..core.http_response import AsyncHttpResponse, HttpResponse
from ..core.pydantic_utilities import parse_obj_as
from ..core.request_options import RequestOptions
from ..core.serialization import convert_and_respect_annotation_metadata
from .types.document_metadata_patch import DocumentMetadataPatch
from .types.sync_source_by_url_response import SyncSourceByUrlResponse
from .types.upload_document_response import UploadDocumentResponse

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


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

    def upload_document_contents(
        self,
        *,
        document_name: str,
        document_contents: str,
        allowed_users_email_addresses: typing.Sequence[str],
        upload_as_user_email: str,
        document_external_id: str,
        document_external_url: typing.Optional[str] = OMIT,
        custom_metadata: typing.Optional[typing.Dict[str, CustomMetadataValue]] = OMIT,
        collection_id: typing.Optional[str] = OMIT,
        force_update: typing.Optional[bool] = OMIT,
        internal_public: typing.Optional[bool] = OMIT,
        await_vector_store_sync: typing.Optional[bool] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[UploadDocumentResponse]:
        """
        Parameters
        ----------
        document_name : str
            The name of the document you want to upload.

        document_contents : str
            The full LLM-formatted text contents of the document you want to upload.

        allowed_users_email_addresses : typing.Sequence[str]
            Users allowed to access the document. Unlike Credal's out of the box connectors which reconcile various permissions models from 3rd party software, for custom uploads the caller is responsible for specifying who can access the document and currently flattening groups if applicable. Documents can also be marked as internal public.

        upload_as_user_email : str
            [Legacy] The user on behalf of whom the document should be uploaded. In most cases, this can simply be the email of the developer making the API call. This field will be removed in the future in favor of purely specifying permissions via allowedUsersEmailAddresses.

        document_external_id : str
            The external ID of the document. This is typically the ID as it exists in its original external system. Uploads to the same external ID will update the document in Credal.

        document_external_url : typing.Optional[str]
            The external URL of the document you want to upload. If provided Credal will link to this URL.

        custom_metadata : typing.Optional[typing.Dict[str, CustomMetadataValue]]
            Optional JSON representing any custom metadata for this document

        collection_id : typing.Optional[str]
            If specified, the document will also be added to the provided document collection. This operation is eventually consistent, meaning the document does not immediately start appearing in searches of that collection due to an asynchronous embedding process. To achieve strong consistency use the `awaitVectorStoreSync` parameter.

        force_update : typing.Optional[bool]
            If specified, document contents will be re-uploaded and re-embedded even if the document already exists in Credal

        internal_public : typing.Optional[bool]
            If specified, document will be accessible to everyone within the organization of the uploader

        await_vector_store_sync : typing.Optional[bool]
            Document uploads are eventually consistent by default. If specified `true` the API will wait for the vector store to be updated before returning. This is useful if you want to ensure that the document is immediately searchable after this call returns.

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

        Returns
        -------
        HttpResponse[UploadDocumentResponse]
        """
        _response = self._client_wrapper.httpx_client.request(
            "v0/catalog/uploadDocumentContents",
            method="POST",
            json={
                "documentName": document_name,
                "documentContents": document_contents,
                "allowedUsersEmailAddresses": allowed_users_email_addresses,
                "uploadAsUserEmail": upload_as_user_email,
                "documentExternalId": document_external_id,
                "documentExternalUrl": document_external_url,
                "customMetadata": convert_and_respect_annotation_metadata(
                    object_=custom_metadata, annotation=typing.Dict[str, CustomMetadataValue], direction="write"
                ),
                "collectionId": collection_id,
                "forceUpdate": force_update,
                "internalPublic": internal_public,
                "awaitVectorStoreSync": await_vector_store_sync,
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    UploadDocumentResponse,
                    parse_obj_as(
                        type_=UploadDocumentResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def upload_file(
        self,
        *,
        file: core.File,
        upload_as_user_email: str,
        document_external_id: str,
        document_name: typing.Optional[str] = OMIT,
        allowed_users_email_addresses: typing.Optional[str] = OMIT,
        document_external_url: typing.Optional[str] = OMIT,
        custom_metadata: typing.Optional[str] = OMIT,
        collection_id: typing.Optional[str] = OMIT,
        force_update: typing.Optional[str] = OMIT,
        internal_public: typing.Optional[str] = OMIT,
        source_system_updated: typing.Optional[str] = OMIT,
        await_vector_store_sync: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[UploadDocumentResponse]:
        """
        Upload a file (PDF, Word, Excel, CSV, PowerPoint) to Credal. Unlike uploadDocumentContents which requires pre-parsed text, this endpoint accepts actual file uploads and automatically parses them using Credal's parsing service.

        Parameters
        ----------
        file : core.File
            See core.File for more documentation

        upload_as_user_email : str
            [Legacy] The user on behalf of whom the document should be uploaded. In most cases, this can simply be the email of the developer making the API call. This field will be removed in the future in favor of purely specifying permissions via allowedUsersEmailAddresses.

        document_external_id : str
            The external ID of the document. This is typically the ID as it exists in its original external system. Uploads to the same external ID will update the document in Credal.

        document_name : typing.Optional[str]
            The name of the document you want to upload. If not provided, the original filename will be used.

        allowed_users_email_addresses : typing.Optional[str]
            Users allowed to access the document. Can be provided as a JSON array string (e.g., ["user1@example.com","user2@example.com"]) or comma-separated list (e.g., "user1@example.com,user2@example.com"). Unlike Credal's out of the box connectors which reconcile various permissions models from 3rd party software, for custom uploads the caller is responsible for specifying who can access the document and currently flattening groups if applicable. Documents can also be marked as internal public.

        document_external_url : typing.Optional[str]
            The external URL of the document you want to upload. If provided Credal will link to this URL.

        custom_metadata : typing.Optional[str]
            Optional JSON string representing any custom metadata for this document (e.g., '{"key1":"value1","key2":"value2"}').

        collection_id : typing.Optional[str]
            If specified, the document will also be added to the provided document collection. This operation is eventually consistent, meaning the document does not immediately start appearing in searches of that collection due to an asynchronous embedding process. To achieve strong consistency use the `awaitVectorStoreSync` parameter.

        force_update : typing.Optional[str]
            If set to "true", document contents will be re-uploaded and re-embedded even if the document already exists in Credal.

        internal_public : typing.Optional[str]
            If set to "true", document will be accessible to everyone within the organization of the uploader.

        source_system_updated : typing.Optional[str]
            ISO 8601 date string indicating when the document was last updated in the source system (e.g., "2025-11-03T21:15:00Z").

        await_vector_store_sync : typing.Optional[str]
            Document uploads are eventually consistent by default. If set to "true" the API will wait for the vector store to be updated before returning. This is useful if you want to ensure that the document is immediately searchable after this call returns.

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

        Returns
        -------
        HttpResponse[UploadDocumentResponse]
        """
        _response = self._client_wrapper.httpx_client.request(
            "v0/catalog/uploadFile",
            method="POST",
            data={
                "documentName": document_name,
                "uploadAsUserEmail": upload_as_user_email,
                "documentExternalId": document_external_id,
                "allowedUsersEmailAddresses": allowed_users_email_addresses,
                "documentExternalUrl": document_external_url,
                "customMetadata": custom_metadata,
                "collectionId": collection_id,
                "forceUpdate": force_update,
                "internalPublic": internal_public,
                "sourceSystemUpdated": source_system_updated,
                "awaitVectorStoreSync": await_vector_store_sync,
            },
            files={
                "file": file,
            },
            request_options=request_options,
            omit=OMIT,
            force_multipart=True,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    UploadDocumentResponse,
                    parse_obj_as(
                        type_=UploadDocumentResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def sync_source_by_url(
        self, *, upload_as_user_email: str, source_url: str, request_options: typing.Optional[RequestOptions] = None
    ) -> HttpResponse[SyncSourceByUrlResponse]:
        """
        Sync a document from a source URL. Does not support recursive web search. Reach out to a Credal representative for access.

        Parameters
        ----------
        upload_as_user_email : str

        source_url : str

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

        Returns
        -------
        HttpResponse[SyncSourceByUrlResponse]
        """
        _response = self._client_wrapper.httpx_client.request(
            "v0/catalog/syncSourceByUrl",
            method="POST",
            json={
                "uploadAsUserEmail": upload_as_user_email,
                "sourceUrl": source_url,
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    SyncSourceByUrlResponse,
                    parse_obj_as(
                        type_=SyncSourceByUrlResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def metadata(
        self,
        *,
        sources: typing.Sequence[DocumentMetadataPatch],
        upload_as_user_email: str,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[None]:
        """
        Bulk patch metadata for documents, synced natively by Credal or manual API uploads

        Parameters
        ----------
        sources : typing.Sequence[DocumentMetadataPatch]

        upload_as_user_email : str

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

        Returns
        -------
        HttpResponse[None]
        """
        _response = self._client_wrapper.httpx_client.request(
            "v0/catalog/metadata",
            method="PATCH",
            json={
                "sources": convert_and_respect_annotation_metadata(
                    object_=sources, annotation=typing.Sequence[DocumentMetadataPatch], direction="write"
                ),
                "uploadAsUserEmail": upload_as_user_email,
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return HttpResponse(response=_response, data=None)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)


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

    async def upload_document_contents(
        self,
        *,
        document_name: str,
        document_contents: str,
        allowed_users_email_addresses: typing.Sequence[str],
        upload_as_user_email: str,
        document_external_id: str,
        document_external_url: typing.Optional[str] = OMIT,
        custom_metadata: typing.Optional[typing.Dict[str, CustomMetadataValue]] = OMIT,
        collection_id: typing.Optional[str] = OMIT,
        force_update: typing.Optional[bool] = OMIT,
        internal_public: typing.Optional[bool] = OMIT,
        await_vector_store_sync: typing.Optional[bool] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[UploadDocumentResponse]:
        """
        Parameters
        ----------
        document_name : str
            The name of the document you want to upload.

        document_contents : str
            The full LLM-formatted text contents of the document you want to upload.

        allowed_users_email_addresses : typing.Sequence[str]
            Users allowed to access the document. Unlike Credal's out of the box connectors which reconcile various permissions models from 3rd party software, for custom uploads the caller is responsible for specifying who can access the document and currently flattening groups if applicable. Documents can also be marked as internal public.

        upload_as_user_email : str
            [Legacy] The user on behalf of whom the document should be uploaded. In most cases, this can simply be the email of the developer making the API call. This field will be removed in the future in favor of purely specifying permissions via allowedUsersEmailAddresses.

        document_external_id : str
            The external ID of the document. This is typically the ID as it exists in its original external system. Uploads to the same external ID will update the document in Credal.

        document_external_url : typing.Optional[str]
            The external URL of the document you want to upload. If provided Credal will link to this URL.

        custom_metadata : typing.Optional[typing.Dict[str, CustomMetadataValue]]
            Optional JSON representing any custom metadata for this document

        collection_id : typing.Optional[str]
            If specified, the document will also be added to the provided document collection. This operation is eventually consistent, meaning the document does not immediately start appearing in searches of that collection due to an asynchronous embedding process. To achieve strong consistency use the `awaitVectorStoreSync` parameter.

        force_update : typing.Optional[bool]
            If specified, document contents will be re-uploaded and re-embedded even if the document already exists in Credal

        internal_public : typing.Optional[bool]
            If specified, document will be accessible to everyone within the organization of the uploader

        await_vector_store_sync : typing.Optional[bool]
            Document uploads are eventually consistent by default. If specified `true` the API will wait for the vector store to be updated before returning. This is useful if you want to ensure that the document is immediately searchable after this call returns.

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

        Returns
        -------
        AsyncHttpResponse[UploadDocumentResponse]
        """
        _response = await self._client_wrapper.httpx_client.request(
            "v0/catalog/uploadDocumentContents",
            method="POST",
            json={
                "documentName": document_name,
                "documentContents": document_contents,
                "allowedUsersEmailAddresses": allowed_users_email_addresses,
                "uploadAsUserEmail": upload_as_user_email,
                "documentExternalId": document_external_id,
                "documentExternalUrl": document_external_url,
                "customMetadata": convert_and_respect_annotation_metadata(
                    object_=custom_metadata, annotation=typing.Dict[str, CustomMetadataValue], direction="write"
                ),
                "collectionId": collection_id,
                "forceUpdate": force_update,
                "internalPublic": internal_public,
                "awaitVectorStoreSync": await_vector_store_sync,
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    UploadDocumentResponse,
                    parse_obj_as(
                        type_=UploadDocumentResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def upload_file(
        self,
        *,
        file: core.File,
        upload_as_user_email: str,
        document_external_id: str,
        document_name: typing.Optional[str] = OMIT,
        allowed_users_email_addresses: typing.Optional[str] = OMIT,
        document_external_url: typing.Optional[str] = OMIT,
        custom_metadata: typing.Optional[str] = OMIT,
        collection_id: typing.Optional[str] = OMIT,
        force_update: typing.Optional[str] = OMIT,
        internal_public: typing.Optional[str] = OMIT,
        source_system_updated: typing.Optional[str] = OMIT,
        await_vector_store_sync: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[UploadDocumentResponse]:
        """
        Upload a file (PDF, Word, Excel, CSV, PowerPoint) to Credal. Unlike uploadDocumentContents which requires pre-parsed text, this endpoint accepts actual file uploads and automatically parses them using Credal's parsing service.

        Parameters
        ----------
        file : core.File
            See core.File for more documentation

        upload_as_user_email : str
            [Legacy] The user on behalf of whom the document should be uploaded. In most cases, this can simply be the email of the developer making the API call. This field will be removed in the future in favor of purely specifying permissions via allowedUsersEmailAddresses.

        document_external_id : str
            The external ID of the document. This is typically the ID as it exists in its original external system. Uploads to the same external ID will update the document in Credal.

        document_name : typing.Optional[str]
            The name of the document you want to upload. If not provided, the original filename will be used.

        allowed_users_email_addresses : typing.Optional[str]
            Users allowed to access the document. Can be provided as a JSON array string (e.g., ["user1@example.com","user2@example.com"]) or comma-separated list (e.g., "user1@example.com,user2@example.com"). Unlike Credal's out of the box connectors which reconcile various permissions models from 3rd party software, for custom uploads the caller is responsible for specifying who can access the document and currently flattening groups if applicable. Documents can also be marked as internal public.

        document_external_url : typing.Optional[str]
            The external URL of the document you want to upload. If provided Credal will link to this URL.

        custom_metadata : typing.Optional[str]
            Optional JSON string representing any custom metadata for this document (e.g., '{"key1":"value1","key2":"value2"}').

        collection_id : typing.Optional[str]
            If specified, the document will also be added to the provided document collection. This operation is eventually consistent, meaning the document does not immediately start appearing in searches of that collection due to an asynchronous embedding process. To achieve strong consistency use the `awaitVectorStoreSync` parameter.

        force_update : typing.Optional[str]
            If set to "true", document contents will be re-uploaded and re-embedded even if the document already exists in Credal.

        internal_public : typing.Optional[str]
            If set to "true", document will be accessible to everyone within the organization of the uploader.

        source_system_updated : typing.Optional[str]
            ISO 8601 date string indicating when the document was last updated in the source system (e.g., "2025-11-03T21:15:00Z").

        await_vector_store_sync : typing.Optional[str]
            Document uploads are eventually consistent by default. If set to "true" the API will wait for the vector store to be updated before returning. This is useful if you want to ensure that the document is immediately searchable after this call returns.

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

        Returns
        -------
        AsyncHttpResponse[UploadDocumentResponse]
        """
        _response = await self._client_wrapper.httpx_client.request(
            "v0/catalog/uploadFile",
            method="POST",
            data={
                "documentName": document_name,
                "uploadAsUserEmail": upload_as_user_email,
                "documentExternalId": document_external_id,
                "allowedUsersEmailAddresses": allowed_users_email_addresses,
                "documentExternalUrl": document_external_url,
                "customMetadata": custom_metadata,
                "collectionId": collection_id,
                "forceUpdate": force_update,
                "internalPublic": internal_public,
                "sourceSystemUpdated": source_system_updated,
                "awaitVectorStoreSync": await_vector_store_sync,
            },
            files={
                "file": file,
            },
            request_options=request_options,
            omit=OMIT,
            force_multipart=True,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    UploadDocumentResponse,
                    parse_obj_as(
                        type_=UploadDocumentResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def sync_source_by_url(
        self, *, upload_as_user_email: str, source_url: str, request_options: typing.Optional[RequestOptions] = None
    ) -> AsyncHttpResponse[SyncSourceByUrlResponse]:
        """
        Sync a document from a source URL. Does not support recursive web search. Reach out to a Credal representative for access.

        Parameters
        ----------
        upload_as_user_email : str

        source_url : str

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

        Returns
        -------
        AsyncHttpResponse[SyncSourceByUrlResponse]
        """
        _response = await self._client_wrapper.httpx_client.request(
            "v0/catalog/syncSourceByUrl",
            method="POST",
            json={
                "uploadAsUserEmail": upload_as_user_email,
                "sourceUrl": source_url,
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    SyncSourceByUrlResponse,
                    parse_obj_as(
                        type_=SyncSourceByUrlResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def metadata(
        self,
        *,
        sources: typing.Sequence[DocumentMetadataPatch],
        upload_as_user_email: str,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[None]:
        """
        Bulk patch metadata for documents, synced natively by Credal or manual API uploads

        Parameters
        ----------
        sources : typing.Sequence[DocumentMetadataPatch]

        upload_as_user_email : str

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

        Returns
        -------
        AsyncHttpResponse[None]
        """
        _response = await self._client_wrapper.httpx_client.request(
            "v0/catalog/metadata",
            method="PATCH",
            json={
                "sources": convert_and_respect_annotation_metadata(
                    object_=sources, annotation=typing.Sequence[DocumentMetadataPatch], direction="write"
                ),
                "uploadAsUserEmail": upload_as_user_email,
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                return AsyncHttpResponse(response=_response, data=None)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
