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

import typing
from json.decoder import JSONDecodeError

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 ....core.serialization import convert_and_respect_annotation_metadata
from ....errors.bad_request_error import BadRequestError
from ....errors.internal_server_error import InternalServerError
from ....errors.not_found_error import NotFoundError
from ....types.audio_input_request import AudioInputRequest
from ....types.embedding_task_response import EmbeddingTaskResponse
from ....types.media_embedding_task import MediaEmbeddingTask
from ....types.video_input_request import VideoInputRequest
from .types.create_async_embedding_request_input_type import CreateAsyncEmbeddingRequestInputType
from .types.create_async_embedding_request_model_name import CreateAsyncEmbeddingRequestModelName
from .types.tasks_create_response import TasksCreateResponse
from .types.tasks_list_response import TasksListResponse

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


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

    def list(
        self,
        *,
        started_at: typing.Optional[str] = None,
        ended_at: typing.Optional[str] = None,
        status: typing.Optional[str] = None,
        page: typing.Optional[int] = None,
        page_limit: typing.Optional[int] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> SyncPager[MediaEmbeddingTask]:
        """
        This method returns a list of the async embedding tasks in your account. The platform returns your async embedding tasks sorted by creation date, with the newest at the top of the list.

        Parameters
        ----------
        started_at : typing.Optional[str]
            Retrieve the embedding tasks that were created after the given date and time, expressed in the RFC 3339 format ("YYYY-MM-DDTHH:mm:ssZ").

        ended_at : typing.Optional[str]
            Retrieve the embedding tasks that were created before the given date and time, expressed in the RFC 3339 format ("YYYY-MM-DDTHH:mm:ssZ").

        status : typing.Optional[str]
            Filter the embedding tasks by their current status.

            **Values**: `processing`, `ready`, or `failed`.

        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`.

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

        Returns
        -------
        SyncPager[MediaEmbeddingTask]
            A list of async embedding tasks has successfully been retrieved.
        """
        page = page if page is not None else 1

        _response = self._client_wrapper.httpx_client.request(
            "embed-v2/tasks",
            method="GET",
            params={
                "started_at": started_at,
                "ended_at": ended_at,
                "status": status,
                "page": page,
                "page_limit": page_limit,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _parsed_response = typing.cast(
                    TasksListResponse,
                    parse_obj_as(
                        type_=TasksListResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                _items = _parsed_response.data
                _has_next = True
                _get_next = lambda: self.list(
                    started_at=started_at,
                    ended_at=ended_at,
                    status=status,
                    page=page + 1,
                    page_limit=page_limit,
                    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,
        *,
        input_type: CreateAsyncEmbeddingRequestInputType,
        model_name: CreateAsyncEmbeddingRequestModelName,
        audio: typing.Optional[AudioInputRequest] = OMIT,
        video: typing.Optional[VideoInputRequest] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[TasksCreateResponse]:
        """
        This endpoint creates embeddings for audio and video content asynchronously.

        **When to use this endpoint**:
        - Process audio or video files longer than 10 minutes
        - Process files up to 4 hours in duration

        <Accordion title="Input requirements">
          **Video**:
          - Minimum duration: 4 seconds
          - Maximum duration: 4 hours
          - Maximum file size: 4 GB
          - Formats: [FFmpeg supported formats](https://ffmpeg.org/ffmpeg-formats.html)
          - Resolution: 360x360 to 5184x2160 pixels
          - Aspect ratio: Between 1:1 and 1:2.4, or between 2.4:1 and 1:1

          **Audio**:
          - Minimum duration: 4 seconds
          - Maximum duration: 4 hours
          - Maximum file size: 2 GB
          - Formats: WAV (uncompressed), MP3 (lossy), FLAC (lossless)
        </Accordion>

          Creating embeddings asynchronously requires three steps:

          1. Create a task using this endpoint. The platform returns a task ID.
          2. Poll for the status of the task using the [`GET`](/v1.3/api-reference/create-embeddings-v2/retrieve-embeddings) method of the `/embed-v2/tasks/{task_id}` endpoint. Wait until the status is `ready`.
          3. Retrieve the embeddings from the response when the status is `ready` using the [`GET`](/v1.3/api-reference/create-embeddings-v2/retrieve-embeddings) method of the `/embed-v2/tasks/{task_id}` endpoint.

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

        Parameters
        ----------
        input_type : CreateAsyncEmbeddingRequestInputType
            The type of content for the embeddings.

            **Values**:
            - `audio`: Audio files
            - `video`: Video content

        model_name : CreateAsyncEmbeddingRequestModelName
            The model you wish to use. Value: `"marengo3.0"`.

        audio : typing.Optional[AudioInputRequest]

        video : typing.Optional[VideoInputRequest]

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

        Returns
        -------
        HttpResponse[TasksCreateResponse]
            An embedding task has successfully been created.
        """
        _response = self._client_wrapper.httpx_client.request(
            "embed-v2/tasks",
            method="POST",
            json={
                "input_type": input_type,
                "model_name": model_name,
                "audio": convert_and_respect_annotation_metadata(
                    object_=audio, annotation=AudioInputRequest, direction="write"
                ),
                "video": convert_and_respect_annotation_metadata(
                    object_=video, annotation=VideoInputRequest, direction="write"
                ),
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    TasksCreateResponse,
                    parse_obj_as(
                        type_=TasksCreateResponse,  # 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(),
                        ),
                    ),
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    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, task_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> HttpResponse[EmbeddingTaskResponse]:
        """
        This method retrieves the status and the results of an async embedding task.

        **Task statuses**:
        - `processing`: The platform is creating the embeddings.
        - `ready`: Processing is complete. Embeddings are available in the response.
        - `failed`: The task failed. Embeddings were not created.

        Invoke this method repeatedly until the `status` field is `ready`. When `status` is `ready`, use the embeddings from the response.

        Parameters
        ----------
        task_id : str
            The unique identifier of the embedding task.

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

        Returns
        -------
        HttpResponse[EmbeddingTaskResponse]
            Task status and results retrieved successfully
        """
        _response = self._client_wrapper.httpx_client.request(
            f"embed-v2/tasks/{jsonable_encoder(task_id)}",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    EmbeddingTaskResponse,
                    parse_obj_as(
                        type_=EmbeddingTaskResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 404:
                raise NotFoundError(
                    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 AsyncRawTasksClient:
    def __init__(self, *, client_wrapper: AsyncClientWrapper):
        self._client_wrapper = client_wrapper

    async def list(
        self,
        *,
        started_at: typing.Optional[str] = None,
        ended_at: typing.Optional[str] = None,
        status: typing.Optional[str] = None,
        page: typing.Optional[int] = None,
        page_limit: typing.Optional[int] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncPager[MediaEmbeddingTask]:
        """
        This method returns a list of the async embedding tasks in your account. The platform returns your async embedding tasks sorted by creation date, with the newest at the top of the list.

        Parameters
        ----------
        started_at : typing.Optional[str]
            Retrieve the embedding tasks that were created after the given date and time, expressed in the RFC 3339 format ("YYYY-MM-DDTHH:mm:ssZ").

        ended_at : typing.Optional[str]
            Retrieve the embedding tasks that were created before the given date and time, expressed in the RFC 3339 format ("YYYY-MM-DDTHH:mm:ssZ").

        status : typing.Optional[str]
            Filter the embedding tasks by their current status.

            **Values**: `processing`, `ready`, or `failed`.

        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`.

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

        Returns
        -------
        AsyncPager[MediaEmbeddingTask]
            A list of async embedding tasks has successfully been retrieved.
        """
        page = page if page is not None else 1

        _response = await self._client_wrapper.httpx_client.request(
            "embed-v2/tasks",
            method="GET",
            params={
                "started_at": started_at,
                "ended_at": ended_at,
                "status": status,
                "page": page,
                "page_limit": page_limit,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _parsed_response = typing.cast(
                    TasksListResponse,
                    parse_obj_as(
                        type_=TasksListResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                _items = _parsed_response.data
                _has_next = True

                async def _get_next():
                    return await self.list(
                        started_at=started_at,
                        ended_at=ended_at,
                        status=status,
                        page=page + 1,
                        page_limit=page_limit,
                        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,
        *,
        input_type: CreateAsyncEmbeddingRequestInputType,
        model_name: CreateAsyncEmbeddingRequestModelName,
        audio: typing.Optional[AudioInputRequest] = OMIT,
        video: typing.Optional[VideoInputRequest] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[TasksCreateResponse]:
        """
        This endpoint creates embeddings for audio and video content asynchronously.

        **When to use this endpoint**:
        - Process audio or video files longer than 10 minutes
        - Process files up to 4 hours in duration

        <Accordion title="Input requirements">
          **Video**:
          - Minimum duration: 4 seconds
          - Maximum duration: 4 hours
          - Maximum file size: 4 GB
          - Formats: [FFmpeg supported formats](https://ffmpeg.org/ffmpeg-formats.html)
          - Resolution: 360x360 to 5184x2160 pixels
          - Aspect ratio: Between 1:1 and 1:2.4, or between 2.4:1 and 1:1

          **Audio**:
          - Minimum duration: 4 seconds
          - Maximum duration: 4 hours
          - Maximum file size: 2 GB
          - Formats: WAV (uncompressed), MP3 (lossy), FLAC (lossless)
        </Accordion>

          Creating embeddings asynchronously requires three steps:

          1. Create a task using this endpoint. The platform returns a task ID.
          2. Poll for the status of the task using the [`GET`](/v1.3/api-reference/create-embeddings-v2/retrieve-embeddings) method of the `/embed-v2/tasks/{task_id}` endpoint. Wait until the status is `ready`.
          3. Retrieve the embeddings from the response when the status is `ready` using the [`GET`](/v1.3/api-reference/create-embeddings-v2/retrieve-embeddings) method of the `/embed-v2/tasks/{task_id}` endpoint.

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

        Parameters
        ----------
        input_type : CreateAsyncEmbeddingRequestInputType
            The type of content for the embeddings.

            **Values**:
            - `audio`: Audio files
            - `video`: Video content

        model_name : CreateAsyncEmbeddingRequestModelName
            The model you wish to use. Value: `"marengo3.0"`.

        audio : typing.Optional[AudioInputRequest]

        video : typing.Optional[VideoInputRequest]

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

        Returns
        -------
        AsyncHttpResponse[TasksCreateResponse]
            An embedding task has successfully been created.
        """
        _response = await self._client_wrapper.httpx_client.request(
            "embed-v2/tasks",
            method="POST",
            json={
                "input_type": input_type,
                "model_name": model_name,
                "audio": convert_and_respect_annotation_metadata(
                    object_=audio, annotation=AudioInputRequest, direction="write"
                ),
                "video": convert_and_respect_annotation_metadata(
                    object_=video, annotation=VideoInputRequest, direction="write"
                ),
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    TasksCreateResponse,
                    parse_obj_as(
                        type_=TasksCreateResponse,  # 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(),
                        ),
                    ),
                )
            if _response.status_code == 500:
                raise InternalServerError(
                    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, task_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> AsyncHttpResponse[EmbeddingTaskResponse]:
        """
        This method retrieves the status and the results of an async embedding task.

        **Task statuses**:
        - `processing`: The platform is creating the embeddings.
        - `ready`: Processing is complete. Embeddings are available in the response.
        - `failed`: The task failed. Embeddings were not created.

        Invoke this method repeatedly until the `status` field is `ready`. When `status` is `ready`, use the embeddings from the response.

        Parameters
        ----------
        task_id : str
            The unique identifier of the embedding task.

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

        Returns
        -------
        AsyncHttpResponse[EmbeddingTaskResponse]
            Task status and results retrieved successfully
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"embed-v2/tasks/{jsonable_encoder(task_id)}",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    EmbeddingTaskResponse,
                    parse_obj_as(
                        type_=EmbeddingTaskResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 404:
                raise NotFoundError(
                    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)
