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

import contextlib
import typing
from json.decoder import JSONDecodeError

from ..commons.errors.bad_request_error import BadRequestError
from ..commons.errors.not_found_error import NotFoundError
from ..commons.errors.server_error import ServerError
from ..commons.types.error_message import ErrorMessage
from ..commons.types.event_field import EventField
from ..commons.types.event_filter import EventFilter
from ..commons.types.event_request import EventRequest
from ..commons.types.event_response import EventResponse
from ..commons.types.events_search_response import EventsSearchResponse
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.pydantic_utilities import parse_obj_as
from ..core.request_options import RequestOptions
from ..core.serialization import convert_and_respect_annotation_metadata

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


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

    def create(
        self, *, request: EventRequest, request_options: typing.Optional[RequestOptions] = None
    ) -> HttpResponse[EventResponse]:
        """
        Create a new event

        Parameters
        ----------
        request : EventRequest

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

        Returns
        -------
        HttpResponse[EventResponse]
            A response indicating the event was successfully accepted
        """
        _response = self._client_wrapper.httpx_client.request(
            "v1/events",
            method="POST",
            json=convert_and_respect_annotation_metadata(object_=request, annotation=EventRequest, direction="write"),
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    EventResponse,
                    parse_obj_as(
                        type_=EventResponse,  # 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(
                        ErrorMessage,
                        parse_obj_as(
                            type_=ErrorMessage,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        ErrorMessage,
                        parse_obj_as(
                            type_=ErrorMessage,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 500:
                raise ServerError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        ErrorMessage,
                        parse_obj_as(
                            type_=ErrorMessage,  # 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 search(
        self,
        *,
        sort: typing.Optional[EventField] = OMIT,
        filter: typing.Optional[EventFilter] = OMIT,
        page: typing.Optional[int] = OMIT,
        size: typing.Optional[int] = OMIT,
        sort_desc: typing.Optional[bool] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[EventsSearchResponse]:
        """
        Search events

        Parameters
        ----------
        sort : typing.Optional[EventField]

        filter : typing.Optional[EventFilter]

        page : typing.Optional[int]
            Page number to return, defaults to 0

        size : typing.Optional[int]
            The size of the page to return, defaults to 20

        sort_desc : typing.Optional[bool]
            Whether to sort descending, defaults to true

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

        Returns
        -------
        HttpResponse[EventsSearchResponse]
        """
        _response = self._client_wrapper.httpx_client.request(
            "v1/events/search",
            method="POST",
            json={
                "sort": sort,
                "filter": convert_and_respect_annotation_metadata(
                    object_=filter, annotation=EventFilter, direction="write"
                ),
                "page": page,
                "size": size,
                "sortDesc": sort_desc,
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    EventsSearchResponse,
                    parse_obj_as(
                        type_=EventsSearchResponse,  # 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(
                        ErrorMessage,
                        parse_obj_as(
                            type_=ErrorMessage,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        ErrorMessage,
                        parse_obj_as(
                            type_=ErrorMessage,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 500:
                raise ServerError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        ErrorMessage,
                        parse_obj_as(
                            type_=ErrorMessage,  # 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 get(
        self, event_id: str, *, app_id: str, request_options: typing.Optional[RequestOptions] = None
    ) -> HttpResponse[EventResponse]:
        """
        Retrieve details of a specific Event item by its ID.

        Parameters
        ----------
        event_id : str
            The ID of the Event to get.

        app_id : str
            The App ID of the Event to retrieve

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

        Returns
        -------
        HttpResponse[EventResponse]
            Details of the specified Event
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v1/events/{jsonable_encoder(event_id)}",
            method="GET",
            params={
                "appId": app_id,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    EventResponse,
                    parse_obj_as(
                        type_=EventResponse,  # 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(
                        ErrorMessage,
                        parse_obj_as(
                            type_=ErrorMessage,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        ErrorMessage,
                        parse_obj_as(
                            type_=ErrorMessage,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 500:
                raise ServerError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        ErrorMessage,
                        parse_obj_as(
                            type_=ErrorMessage,  # 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)

    @contextlib.contextmanager
    def export(
        self,
        *,
        sort: typing.Optional[EventField] = OMIT,
        filter: typing.Optional[EventFilter] = OMIT,
        page: typing.Optional[int] = OMIT,
        size: typing.Optional[int] = OMIT,
        sort_desc: typing.Optional[bool] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> typing.Iterator[HttpResponse[typing.Iterator[bytes]]]:
        """
        Export events to a CSV file.

        This will output a summary of each event that matches the supplied filter. A maximum of 10,000 events can be exported at a time. For most use cases it is recommended to use the search API instead and convert the JSON response to your desired format. The CSV format may change over time and should not be relied upon by code consumers.

        Parameters
        ----------
        sort : typing.Optional[EventField]

        filter : typing.Optional[EventFilter]

        page : typing.Optional[int]
            Page number to return, defaults to 0

        size : typing.Optional[int]
            The size of the page to return, defaults to 20

        sort_desc : typing.Optional[bool]
            Whether to sort descending, defaults to true

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration. You can pass in configuration such as `chunk_size`, and more to customize the request and response.

        Returns
        -------
        typing.Iterator[HttpResponse[typing.Iterator[bytes]]]
            A CSV containing one event per row
        """
        with self._client_wrapper.httpx_client.stream(
            "v1/events/export",
            method="POST",
            json={
                "sort": sort,
                "filter": convert_and_respect_annotation_metadata(
                    object_=filter, annotation=EventFilter, direction="write"
                ),
                "page": page,
                "size": size,
                "sortDesc": sort_desc,
            },
            request_options=request_options,
            omit=OMIT,
        ) as _response:

            def _stream() -> HttpResponse[typing.Iterator[bytes]]:
                try:
                    if 200 <= _response.status_code < 300:
                        _chunk_size = request_options.get("chunk_size", None) if request_options is not None else None
                        return HttpResponse(
                            response=_response, data=(_chunk for _chunk in _response.iter_bytes(chunk_size=_chunk_size))
                        )
                    _response.read()
                    if _response.status_code == 404:
                        raise NotFoundError(
                            headers=dict(_response.headers),
                            body=typing.cast(
                                ErrorMessage,
                                parse_obj_as(
                                    type_=ErrorMessage,  # type: ignore
                                    object_=_response.json(),
                                ),
                            ),
                        )
                    if _response.status_code == 400:
                        raise BadRequestError(
                            headers=dict(_response.headers),
                            body=typing.cast(
                                ErrorMessage,
                                parse_obj_as(
                                    type_=ErrorMessage,  # type: ignore
                                    object_=_response.json(),
                                ),
                            ),
                        )
                    if _response.status_code == 500:
                        raise ServerError(
                            headers=dict(_response.headers),
                            body=typing.cast(
                                ErrorMessage,
                                parse_obj_as(
                                    type_=ErrorMessage,  # 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)

            yield _stream()


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

    async def create(
        self, *, request: EventRequest, request_options: typing.Optional[RequestOptions] = None
    ) -> AsyncHttpResponse[EventResponse]:
        """
        Create a new event

        Parameters
        ----------
        request : EventRequest

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

        Returns
        -------
        AsyncHttpResponse[EventResponse]
            A response indicating the event was successfully accepted
        """
        _response = await self._client_wrapper.httpx_client.request(
            "v1/events",
            method="POST",
            json=convert_and_respect_annotation_metadata(object_=request, annotation=EventRequest, direction="write"),
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    EventResponse,
                    parse_obj_as(
                        type_=EventResponse,  # 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(
                        ErrorMessage,
                        parse_obj_as(
                            type_=ErrorMessage,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        ErrorMessage,
                        parse_obj_as(
                            type_=ErrorMessage,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 500:
                raise ServerError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        ErrorMessage,
                        parse_obj_as(
                            type_=ErrorMessage,  # 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 search(
        self,
        *,
        sort: typing.Optional[EventField] = OMIT,
        filter: typing.Optional[EventFilter] = OMIT,
        page: typing.Optional[int] = OMIT,
        size: typing.Optional[int] = OMIT,
        sort_desc: typing.Optional[bool] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[EventsSearchResponse]:
        """
        Search events

        Parameters
        ----------
        sort : typing.Optional[EventField]

        filter : typing.Optional[EventFilter]

        page : typing.Optional[int]
            Page number to return, defaults to 0

        size : typing.Optional[int]
            The size of the page to return, defaults to 20

        sort_desc : typing.Optional[bool]
            Whether to sort descending, defaults to true

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

        Returns
        -------
        AsyncHttpResponse[EventsSearchResponse]
        """
        _response = await self._client_wrapper.httpx_client.request(
            "v1/events/search",
            method="POST",
            json={
                "sort": sort,
                "filter": convert_and_respect_annotation_metadata(
                    object_=filter, annotation=EventFilter, direction="write"
                ),
                "page": page,
                "size": size,
                "sortDesc": sort_desc,
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    EventsSearchResponse,
                    parse_obj_as(
                        type_=EventsSearchResponse,  # 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(
                        ErrorMessage,
                        parse_obj_as(
                            type_=ErrorMessage,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        ErrorMessage,
                        parse_obj_as(
                            type_=ErrorMessage,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 500:
                raise ServerError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        ErrorMessage,
                        parse_obj_as(
                            type_=ErrorMessage,  # 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 get(
        self, event_id: str, *, app_id: str, request_options: typing.Optional[RequestOptions] = None
    ) -> AsyncHttpResponse[EventResponse]:
        """
        Retrieve details of a specific Event item by its ID.

        Parameters
        ----------
        event_id : str
            The ID of the Event to get.

        app_id : str
            The App ID of the Event to retrieve

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

        Returns
        -------
        AsyncHttpResponse[EventResponse]
            Details of the specified Event
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v1/events/{jsonable_encoder(event_id)}",
            method="GET",
            params={
                "appId": app_id,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    EventResponse,
                    parse_obj_as(
                        type_=EventResponse,  # 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(
                        ErrorMessage,
                        parse_obj_as(
                            type_=ErrorMessage,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        ErrorMessage,
                        parse_obj_as(
                            type_=ErrorMessage,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 500:
                raise ServerError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        ErrorMessage,
                        parse_obj_as(
                            type_=ErrorMessage,  # 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)

    @contextlib.asynccontextmanager
    async def export(
        self,
        *,
        sort: typing.Optional[EventField] = OMIT,
        filter: typing.Optional[EventFilter] = OMIT,
        page: typing.Optional[int] = OMIT,
        size: typing.Optional[int] = OMIT,
        sort_desc: typing.Optional[bool] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> typing.AsyncIterator[AsyncHttpResponse[typing.AsyncIterator[bytes]]]:
        """
        Export events to a CSV file.

        This will output a summary of each event that matches the supplied filter. A maximum of 10,000 events can be exported at a time. For most use cases it is recommended to use the search API instead and convert the JSON response to your desired format. The CSV format may change over time and should not be relied upon by code consumers.

        Parameters
        ----------
        sort : typing.Optional[EventField]

        filter : typing.Optional[EventFilter]

        page : typing.Optional[int]
            Page number to return, defaults to 0

        size : typing.Optional[int]
            The size of the page to return, defaults to 20

        sort_desc : typing.Optional[bool]
            Whether to sort descending, defaults to true

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration. You can pass in configuration such as `chunk_size`, and more to customize the request and response.

        Returns
        -------
        typing.AsyncIterator[AsyncHttpResponse[typing.AsyncIterator[bytes]]]
            A CSV containing one event per row
        """
        async with self._client_wrapper.httpx_client.stream(
            "v1/events/export",
            method="POST",
            json={
                "sort": sort,
                "filter": convert_and_respect_annotation_metadata(
                    object_=filter, annotation=EventFilter, direction="write"
                ),
                "page": page,
                "size": size,
                "sortDesc": sort_desc,
            },
            request_options=request_options,
            omit=OMIT,
        ) as _response:

            async def _stream() -> AsyncHttpResponse[typing.AsyncIterator[bytes]]:
                try:
                    if 200 <= _response.status_code < 300:
                        _chunk_size = request_options.get("chunk_size", None) if request_options is not None else None
                        return AsyncHttpResponse(
                            response=_response,
                            data=(_chunk async for _chunk in _response.aiter_bytes(chunk_size=_chunk_size)),
                        )
                    await _response.aread()
                    if _response.status_code == 404:
                        raise NotFoundError(
                            headers=dict(_response.headers),
                            body=typing.cast(
                                ErrorMessage,
                                parse_obj_as(
                                    type_=ErrorMessage,  # type: ignore
                                    object_=_response.json(),
                                ),
                            ),
                        )
                    if _response.status_code == 400:
                        raise BadRequestError(
                            headers=dict(_response.headers),
                            body=typing.cast(
                                ErrorMessage,
                                parse_obj_as(
                                    type_=ErrorMessage,  # type: ignore
                                    object_=_response.json(),
                                ),
                            ),
                        )
                    if _response.status_code == 500:
                        raise ServerError(
                            headers=dict(_response.headers),
                            body=typing.cast(
                                ErrorMessage,
                                parse_obj_as(
                                    type_=ErrorMessage,  # 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)

            yield await _stream()
