# 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.request_options import RequestOptions
from ..core.serialization import convert_and_respect_annotation_metadata
from ..core.unchecked_base_model import construct_type
from ..errors.bad_request_error import BadRequestError
from ..errors.not_found_error import NotFoundError
from ..errors.unauthorized_error import UnauthorizedError
from ..types.error import Error
from ..types.provided_processor_output import ProvidedProcessorOutput
from .types.evaluation_set_item_create_batch_request_items_item import EvaluationSetItemCreateBatchRequestItemsItem
from .types.evaluation_set_item_create_batch_response import EvaluationSetItemCreateBatchResponse
from .types.evaluation_set_item_create_response import EvaluationSetItemCreateResponse
from .types.evaluation_set_item_update_response import EvaluationSetItemUpdateResponse

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


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

    def create(
        self,
        *,
        evaluation_set_id: str,
        file_id: str,
        expected_output: ProvidedProcessorOutput,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[EvaluationSetItemCreateResponse]:
        """
        Evaluation set items are the individual files and expected outputs that are used to evaluate the performance of a given processor in Extend. This endpoint will create a new evaluation set item in Extend, which will be used during an evaluation run.

        Best Practices for Outputs in Evaluation Sets:
        - **Configure First, Output Later**
          - Always create and finalize your processor configuration before creating evaluation sets
          - Field IDs in outputs must match those defined in your processor configuration
        - **Type Consistency**
          - Ensure output types exactly match your processor configuration
          - For example, if a field is configured as "currency", don't submit a simple number value
        - **Field IDs**
          - Use the exact field IDs from your processor configuration
          - Create your own semantic IDs instead in the configs for each field/type instead of using the generated ones
        - **Value**
          - Remember that all results are inside the value key of a result object, except the values within nested structures.

        Parameters
        ----------
        evaluation_set_id : str
            The ID of the evaluation set to add the item to.

            Example: `"ev_Xj8mK2pL9nR4vT7qY5wZ"`

        file_id : str
            Extend's internal ID for the file. It will always start with "file_".

            Example: `"file_xK9mLPqRtN3vS8wF5hB2cQ"`

        expected_output : ProvidedProcessorOutput
            The expected output that will be used to evaluate the processor's performance.

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

        Returns
        -------
        HttpResponse[EvaluationSetItemCreateResponse]
            Successfully created evaluation set item
        """
        _response = self._client_wrapper.httpx_client.request(
            "evaluation_set_items",
            method="POST",
            json={
                "evaluationSetId": evaluation_set_id,
                "fileId": file_id,
                "expectedOutput": convert_and_respect_annotation_metadata(
                    object_=expected_output, annotation=ProvidedProcessorOutput, direction="write"
                ),
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    EvaluationSetItemCreateResponse,
                    construct_type(
                        type_=EvaluationSetItemCreateResponse,  # 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],
                        construct_type(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        Error,
                        construct_type(
                            type_=Error,  # 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 update(
        self,
        id: str,
        *,
        expected_output: ProvidedProcessorOutput,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[EvaluationSetItemUpdateResponse]:
        """
        If you need to change the expected output for a given evaluation set item, you can use this endpoint to update the item. This can be useful if you need to correct an error in the expected output or if the output of the processor has changed.

        Parameters
        ----------
        id : str
            The ID of the evaluation set item to update.

            Example: `"evi_kR9mNP12Qw4yTv8BdR3H"`

        expected_output : ProvidedProcessorOutput
            The expected output of the processor when run against the file

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

        Returns
        -------
        HttpResponse[EvaluationSetItemUpdateResponse]
            Successfully updated evaluation set item
        """
        _response = self._client_wrapper.httpx_client.request(
            f"evaluation_set_items/{jsonable_encoder(id)}",
            method="POST",
            json={
                "expectedOutput": convert_and_respect_annotation_metadata(
                    object_=expected_output, annotation=ProvidedProcessorOutput, direction="write"
                ),
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    EvaluationSetItemUpdateResponse,
                    construct_type(
                        type_=EvaluationSetItemUpdateResponse,  # 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],
                        construct_type(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        Error,
                        construct_type(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        Error,
                        construct_type(
                            type_=Error,  # 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_batch(
        self,
        *,
        evaluation_set_id: str,
        items: typing.Sequence[EvaluationSetItemCreateBatchRequestItemsItem],
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[EvaluationSetItemCreateBatchResponse]:
        """
        If you have a large number of files that you need to add to an evaluation set, you can use this endpoint to create multiple evaluation set items at once. This can be useful if you have a large dataset that you need to evaluate the performance of a processor against.

        Note: you still need to create each File first using the file API.

        Parameters
        ----------
        evaluation_set_id : str
            The ID of the evaluation set to add the items to.

            Example: `"ev_2LcgeY_mp2T5yPaEuq5Lw"`

        items : typing.Sequence[EvaluationSetItemCreateBatchRequestItemsItem]
            An array of objects representing the evaluation set items to create

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

        Returns
        -------
        HttpResponse[EvaluationSetItemCreateBatchResponse]
            Successfully created evaluation set items
        """
        _response = self._client_wrapper.httpx_client.request(
            "evaluation_set_items/bulk",
            method="POST",
            json={
                "evaluationSetId": evaluation_set_id,
                "items": convert_and_respect_annotation_metadata(
                    object_=items,
                    annotation=typing.Sequence[EvaluationSetItemCreateBatchRequestItemsItem],
                    direction="write",
                ),
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    EvaluationSetItemCreateBatchResponse,
                    construct_type(
                        type_=EvaluationSetItemCreateBatchResponse,  # 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],
                        construct_type(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        Error,
                        construct_type(
                            type_=Error,  # 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 AsyncRawEvaluationSetItemClient:
    def __init__(self, *, client_wrapper: AsyncClientWrapper):
        self._client_wrapper = client_wrapper

    async def create(
        self,
        *,
        evaluation_set_id: str,
        file_id: str,
        expected_output: ProvidedProcessorOutput,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[EvaluationSetItemCreateResponse]:
        """
        Evaluation set items are the individual files and expected outputs that are used to evaluate the performance of a given processor in Extend. This endpoint will create a new evaluation set item in Extend, which will be used during an evaluation run.

        Best Practices for Outputs in Evaluation Sets:
        - **Configure First, Output Later**
          - Always create and finalize your processor configuration before creating evaluation sets
          - Field IDs in outputs must match those defined in your processor configuration
        - **Type Consistency**
          - Ensure output types exactly match your processor configuration
          - For example, if a field is configured as "currency", don't submit a simple number value
        - **Field IDs**
          - Use the exact field IDs from your processor configuration
          - Create your own semantic IDs instead in the configs for each field/type instead of using the generated ones
        - **Value**
          - Remember that all results are inside the value key of a result object, except the values within nested structures.

        Parameters
        ----------
        evaluation_set_id : str
            The ID of the evaluation set to add the item to.

            Example: `"ev_Xj8mK2pL9nR4vT7qY5wZ"`

        file_id : str
            Extend's internal ID for the file. It will always start with "file_".

            Example: `"file_xK9mLPqRtN3vS8wF5hB2cQ"`

        expected_output : ProvidedProcessorOutput
            The expected output that will be used to evaluate the processor's performance.

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

        Returns
        -------
        AsyncHttpResponse[EvaluationSetItemCreateResponse]
            Successfully created evaluation set item
        """
        _response = await self._client_wrapper.httpx_client.request(
            "evaluation_set_items",
            method="POST",
            json={
                "evaluationSetId": evaluation_set_id,
                "fileId": file_id,
                "expectedOutput": convert_and_respect_annotation_metadata(
                    object_=expected_output, annotation=ProvidedProcessorOutput, direction="write"
                ),
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    EvaluationSetItemCreateResponse,
                    construct_type(
                        type_=EvaluationSetItemCreateResponse,  # 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],
                        construct_type(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        Error,
                        construct_type(
                            type_=Error,  # 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 update(
        self,
        id: str,
        *,
        expected_output: ProvidedProcessorOutput,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[EvaluationSetItemUpdateResponse]:
        """
        If you need to change the expected output for a given evaluation set item, you can use this endpoint to update the item. This can be useful if you need to correct an error in the expected output or if the output of the processor has changed.

        Parameters
        ----------
        id : str
            The ID of the evaluation set item to update.

            Example: `"evi_kR9mNP12Qw4yTv8BdR3H"`

        expected_output : ProvidedProcessorOutput
            The expected output of the processor when run against the file

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

        Returns
        -------
        AsyncHttpResponse[EvaluationSetItemUpdateResponse]
            Successfully updated evaluation set item
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"evaluation_set_items/{jsonable_encoder(id)}",
            method="POST",
            json={
                "expectedOutput": convert_and_respect_annotation_metadata(
                    object_=expected_output, annotation=ProvidedProcessorOutput, direction="write"
                ),
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    EvaluationSetItemUpdateResponse,
                    construct_type(
                        type_=EvaluationSetItemUpdateResponse,  # 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],
                        construct_type(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        Error,
                        construct_type(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        Error,
                        construct_type(
                            type_=Error,  # 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_batch(
        self,
        *,
        evaluation_set_id: str,
        items: typing.Sequence[EvaluationSetItemCreateBatchRequestItemsItem],
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[EvaluationSetItemCreateBatchResponse]:
        """
        If you have a large number of files that you need to add to an evaluation set, you can use this endpoint to create multiple evaluation set items at once. This can be useful if you have a large dataset that you need to evaluate the performance of a processor against.

        Note: you still need to create each File first using the file API.

        Parameters
        ----------
        evaluation_set_id : str
            The ID of the evaluation set to add the items to.

            Example: `"ev_2LcgeY_mp2T5yPaEuq5Lw"`

        items : typing.Sequence[EvaluationSetItemCreateBatchRequestItemsItem]
            An array of objects representing the evaluation set items to create

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

        Returns
        -------
        AsyncHttpResponse[EvaluationSetItemCreateBatchResponse]
            Successfully created evaluation set items
        """
        _response = await self._client_wrapper.httpx_client.request(
            "evaluation_set_items/bulk",
            method="POST",
            json={
                "evaluationSetId": evaluation_set_id,
                "items": convert_and_respect_annotation_metadata(
                    object_=items,
                    annotation=typing.Sequence[EvaluationSetItemCreateBatchRequestItemsItem],
                    direction="write",
                ),
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    EvaluationSetItemCreateBatchResponse,
                    construct_type(
                        type_=EvaluationSetItemCreateBatchResponse,  # 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],
                        construct_type(
                            type_=typing.Optional[typing.Any],  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        Error,
                        construct_type(
                            type_=Error,  # 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)
