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

import typing
from json.decoder import JSONDecodeError

from .. import core
from ..core.api_error import ApiError
from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
from ..core.http_response import AsyncHttpResponse, HttpResponse
from ..core.jsonable_encoder import jsonable_encoder
from ..core.pagination import AsyncPager, BaseHttpResponse, SyncPager
from ..core.pydantic_utilities import parse_obj_as
from ..core.request_options import RequestOptions
from ..errors.bad_request_error import BadRequestError
from ..types.asset import Asset
from .types.assets_create_request_method import AssetsCreateRequestMethod
from .types.assets_list_request_asset_types_item import AssetsListRequestAssetTypesItem
from .types.assets_list_response import AssetsListResponse

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


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

    def list(
        self,
        *,
        page: typing.Optional[int] = None,
        page_limit: typing.Optional[int] = None,
        asset_ids: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None,
        asset_types: typing.Optional[
            typing.Union[AssetsListRequestAssetTypesItem, typing.Sequence[AssetsListRequestAssetTypesItem]]
        ] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> SyncPager[Asset]:
        """
        This method returns a list of assets in your account.

        The platform returns your assets sorted by creation date, with the newest at the top of the list.

        Parameters
        ----------
        page : typing.Optional[int]
            A number that identifies the page to retrieve.

            **Default**: `1`.

        page_limit : typing.Optional[int]
            The number of items to return on each page.

            **Default**: `10`.
            **Max**: `50`.

        asset_ids : typing.Optional[typing.Union[str, typing.Sequence[str]]]
            Filters the response to include only assets with the specified IDs. Provide one or more asset IDs. When you specify multiple IDs, the platform returns all matching assets.

        asset_types : typing.Optional[typing.Union[AssetsListRequestAssetTypesItem, typing.Sequence[AssetsListRequestAssetTypesItem]]]
            Filters the response to include only assets of the specified types. Provide one or more asset types. When you specify multiple types, the platform returns all matching assets.

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

        Returns
        -------
        SyncPager[Asset]
            The assets have been successfully retrieved.
        """
        page = page if page is not None else 1

        _response = self._client_wrapper.httpx_client.request(
            "assets",
            method="GET",
            params={
                "page": page,
                "page_limit": page_limit,
                "asset_ids": asset_ids,
                "asset_types": asset_types,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _parsed_response = typing.cast(
                    AssetsListResponse,
                    parse_obj_as(
                        type_=AssetsListResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                _items = _parsed_response.data
                _has_next = True
                _get_next = lambda: self.list(
                    page=page + 1,
                    page_limit=page_limit,
                    asset_ids=asset_ids,
                    asset_types=asset_types,
                    request_options=request_options,
                )
                return SyncPager(
                    has_next=_has_next, items=_items, get_next=_get_next, response=BaseHttpResponse(response=_response)
                )
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _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 create(
        self,
        *,
        method: AssetsCreateRequestMethod,
        file: typing.Optional[core.File] = OMIT,
        url: typing.Optional[str] = OMIT,
        filename: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[Asset]:
        """
        This method creates an asset by uploading a file to the platform. Assets are media files that you can use in downstream workflows, including indexing, analyzing video content, and creating entities.

        **Supported content**: Video, audio, and images.

        **Upload methods**:
        - **Local file**: Set the `method` parameter to `direct` and use the `file` parameter to specify the file.
        - **Publicly accessible URL**: Set the `method` parameter to `url` and use the `url` parameter to specify the URL of your file.

        **File size**: 200MB maximum for local file uploads, 4GB maximum for URL uploads.

        **Additional requirements** depend on your workflow:
        - **Search**: [Marengo requirements](/v1.3/docs/concepts/models/marengo#video-file-requirements)
        - **Video analysis**: [Pegasus requirements](/v1.3/docs/concepts/models/pegasus#input-requirements)
        - **Entity search**: [Marengo image requirements](/v1.3/docs/concepts/models/marengo#image-file-requirements)
        - **Create embeddings**: [Marengo requirements](/v1.3/docs/concepts/models/marengo#input-requirements)

        <Note title="Note">
        This endpoint is rate-limited. For details, see the [Rate limits](/v1.3/docs/get-started/rate-limits) page.
        </Note>

        Parameters
        ----------
        method : AssetsCreateRequestMethod
            Specifies the upload method for the asset. Use `direct` to upload a local file or `url` for a publicly accessible URL.

        file : typing.Optional[core.File]
            See core.File for more documentation

        url : typing.Optional[str]
            Specify this parameter to upload a file from a publicly accessible URL. This parameter is required when `method` is set to `url`.

            URL uploads have a maximum limit of 4GB.

        filename : typing.Optional[str]
            The optional filename of the asset. If not provided, the platform will determine the filename from the file or URL.

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

        Returns
        -------
        HttpResponse[Asset]
            The asset has been successfully created.
        """
        _response = self._client_wrapper.httpx_client.request(
            "assets",
            method="POST",
            data={
                "method": method,
                "url": url,
                "filename": filename,
            },
            files={
                **({"file": file} if file is not None else {}),
            },
            request_options=request_options,
            omit=OMIT,
            force_multipart=True,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    Asset,
                    parse_obj_as(
                        type_=Asset,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _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 retrieve(
        self, asset_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> HttpResponse[Asset]:
        """
        This method retrieves details about the specified asset.

        Parameters
        ----------
        asset_id : str
            The unique identifier of the asset to retrieve.

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

        Returns
        -------
        HttpResponse[Asset]
            The asset has been successfully retrieved.
        """
        _response = self._client_wrapper.httpx_client.request(
            f"assets/{jsonable_encoder(asset_id)}",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    Asset,
                    parse_obj_as(
                        type_=Asset,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _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 delete(self, asset_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> HttpResponse[None]:
        """
        This method deletes the specified asset. This action cannot be undone.

        Parameters
        ----------
        asset_id : str
            The unique identifier of the asset to delete.

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

        Returns
        -------
        HttpResponse[None]
        """
        _response = self._client_wrapper.httpx_client.request(
            f"assets/{jsonable_encoder(asset_id)}",
            method="DELETE",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return HttpResponse(response=_response, data=None)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _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 AsyncRawAssetsClient:
    def __init__(self, *, client_wrapper: AsyncClientWrapper):
        self._client_wrapper = client_wrapper

    async def list(
        self,
        *,
        page: typing.Optional[int] = None,
        page_limit: typing.Optional[int] = None,
        asset_ids: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None,
        asset_types: typing.Optional[
            typing.Union[AssetsListRequestAssetTypesItem, typing.Sequence[AssetsListRequestAssetTypesItem]]
        ] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncPager[Asset]:
        """
        This method returns a list of assets in your account.

        The platform returns your assets sorted by creation date, with the newest at the top of the list.

        Parameters
        ----------
        page : typing.Optional[int]
            A number that identifies the page to retrieve.

            **Default**: `1`.

        page_limit : typing.Optional[int]
            The number of items to return on each page.

            **Default**: `10`.
            **Max**: `50`.

        asset_ids : typing.Optional[typing.Union[str, typing.Sequence[str]]]
            Filters the response to include only assets with the specified IDs. Provide one or more asset IDs. When you specify multiple IDs, the platform returns all matching assets.

        asset_types : typing.Optional[typing.Union[AssetsListRequestAssetTypesItem, typing.Sequence[AssetsListRequestAssetTypesItem]]]
            Filters the response to include only assets of the specified types. Provide one or more asset types. When you specify multiple types, the platform returns all matching assets.

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

        Returns
        -------
        AsyncPager[Asset]
            The assets have been successfully retrieved.
        """
        page = page if page is not None else 1

        _response = await self._client_wrapper.httpx_client.request(
            "assets",
            method="GET",
            params={
                "page": page,
                "page_limit": page_limit,
                "asset_ids": asset_ids,
                "asset_types": asset_types,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _parsed_response = typing.cast(
                    AssetsListResponse,
                    parse_obj_as(
                        type_=AssetsListResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                _items = _parsed_response.data
                _has_next = True

                async def _get_next():
                    return await self.list(
                        page=page + 1,
                        page_limit=page_limit,
                        asset_ids=asset_ids,
                        asset_types=asset_types,
                        request_options=request_options,
                    )

                return AsyncPager(
                    has_next=_has_next, items=_items, get_next=_get_next, response=BaseHttpResponse(response=_response)
                )
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _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 create(
        self,
        *,
        method: AssetsCreateRequestMethod,
        file: typing.Optional[core.File] = OMIT,
        url: typing.Optional[str] = OMIT,
        filename: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[Asset]:
        """
        This method creates an asset by uploading a file to the platform. Assets are media files that you can use in downstream workflows, including indexing, analyzing video content, and creating entities.

        **Supported content**: Video, audio, and images.

        **Upload methods**:
        - **Local file**: Set the `method` parameter to `direct` and use the `file` parameter to specify the file.
        - **Publicly accessible URL**: Set the `method` parameter to `url` and use the `url` parameter to specify the URL of your file.

        **File size**: 200MB maximum for local file uploads, 4GB maximum for URL uploads.

        **Additional requirements** depend on your workflow:
        - **Search**: [Marengo requirements](/v1.3/docs/concepts/models/marengo#video-file-requirements)
        - **Video analysis**: [Pegasus requirements](/v1.3/docs/concepts/models/pegasus#input-requirements)
        - **Entity search**: [Marengo image requirements](/v1.3/docs/concepts/models/marengo#image-file-requirements)
        - **Create embeddings**: [Marengo requirements](/v1.3/docs/concepts/models/marengo#input-requirements)

        <Note title="Note">
        This endpoint is rate-limited. For details, see the [Rate limits](/v1.3/docs/get-started/rate-limits) page.
        </Note>

        Parameters
        ----------
        method : AssetsCreateRequestMethod
            Specifies the upload method for the asset. Use `direct` to upload a local file or `url` for a publicly accessible URL.

        file : typing.Optional[core.File]
            See core.File for more documentation

        url : typing.Optional[str]
            Specify this parameter to upload a file from a publicly accessible URL. This parameter is required when `method` is set to `url`.

            URL uploads have a maximum limit of 4GB.

        filename : typing.Optional[str]
            The optional filename of the asset. If not provided, the platform will determine the filename from the file or URL.

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

        Returns
        -------
        AsyncHttpResponse[Asset]
            The asset has been successfully created.
        """
        _response = await self._client_wrapper.httpx_client.request(
            "assets",
            method="POST",
            data={
                "method": method,
                "url": url,
                "filename": filename,
            },
            files={
                **({"file": file} if file is not None else {}),
            },
            request_options=request_options,
            omit=OMIT,
            force_multipart=True,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    Asset,
                    parse_obj_as(
                        type_=Asset,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _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 retrieve(
        self, asset_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> AsyncHttpResponse[Asset]:
        """
        This method retrieves details about the specified asset.

        Parameters
        ----------
        asset_id : str
            The unique identifier of the asset to retrieve.

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

        Returns
        -------
        AsyncHttpResponse[Asset]
            The asset has been successfully retrieved.
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"assets/{jsonable_encoder(asset_id)}",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    Asset,
                    parse_obj_as(
                        type_=Asset,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _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 delete(
        self, asset_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> AsyncHttpResponse[None]:
        """
        This method deletes the specified asset. This action cannot be undone.

        Parameters
        ----------
        asset_id : str
            The unique identifier of the asset to delete.

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

        Returns
        -------
        AsyncHttpResponse[None]
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"assets/{jsonable_encoder(asset_id)}",
            method="DELETE",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return AsyncHttpResponse(response=_response, data=None)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Optional[typing.Any],
                        parse_obj_as(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _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)
