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

import typing
from ...core.client_wrapper import SyncClientWrapper
from ...requests.shift import ShiftParams
from ...core.request_options import RequestOptions
from ...core.http_response import HttpResponse
from ...types.create_shift_response import CreateShiftResponse
from ...core.serialization import convert_and_respect_annotation_metadata
from ...core.unchecked_base_model import construct_type
from json.decoder import JSONDecodeError
from ...core.api_error import ApiError
from ...requests.shift_query import ShiftQueryParams
from ...types.search_shifts_response import SearchShiftsResponse
from ...types.get_shift_response import GetShiftResponse
from ...core.jsonable_encoder import jsonable_encoder
from ...types.update_shift_response import UpdateShiftResponse
from ...types.delete_shift_response import DeleteShiftResponse
from ...core.client_wrapper import AsyncClientWrapper
from ...core.http_response import AsyncHttpResponse

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


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

    def create(
        self,
        *,
        shift: ShiftParams,
        idempotency_key: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[CreateShiftResponse]:
        """
        Creates a new `Shift`.

        A `Shift` represents a complete workday for a single team member.
        You must provide the following values in your request to this
        endpoint:

        - `location_id`
        - `team_member_id`
        - `start_at`

        An attempt to create a new `Shift` can result in a `BAD_REQUEST` error when:
        - The `status` of the new `Shift` is `OPEN` and the team member has another
        shift with an `OPEN` status.
        - The `start_at` date is in the future.
        - The `start_at` or `end_at` date overlaps another shift for the same team member.
        - The `Break` instances are set in the request and a break `start_at`
        is before the `Shift.start_at`, a break `end_at` is after
        the `Shift.end_at`, or both.

        Parameters
        ----------
        shift : ShiftParams
            The `Shift` to be created.

        idempotency_key : typing.Optional[str]
            A unique string value to ensure the idempotency of the operation.

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

        Returns
        -------
        HttpResponse[CreateShiftResponse]
            Success
        """
        _response = self._client_wrapper.httpx_client.request(
            "v2/labor/shifts",
            method="POST",
            json={
                "idempotency_key": idempotency_key,
                "shift": convert_and_respect_annotation_metadata(
                    object_=shift, annotation=ShiftParams, direction="write"
                ),
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    CreateShiftResponse,
                    construct_type(
                        type_=CreateShiftResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def search(
        self,
        *,
        query: typing.Optional[ShiftQueryParams] = OMIT,
        limit: typing.Optional[int] = OMIT,
        cursor: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[SearchShiftsResponse]:
        """
        Returns a paginated list of `Shift` records for a business.
        The list to be returned can be filtered by:
        - Location IDs
        - Team member IDs
        - Shift status (`OPEN` or `CLOSED`)
        - Shift start
        - Shift end
        - Workday details

        The list can be sorted by:
        - `START_AT`
        - `END_AT`
        - `CREATED_AT`
        - `UPDATED_AT`

        Parameters
        ----------
        query : typing.Optional[ShiftQueryParams]
            Query filters.

        limit : typing.Optional[int]
            The number of resources in a page (200 by default).

        cursor : typing.Optional[str]
            An opaque cursor for fetching the next page.

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

        Returns
        -------
        HttpResponse[SearchShiftsResponse]
            Success
        """
        _response = self._client_wrapper.httpx_client.request(
            "v2/labor/shifts/search",
            method="POST",
            json={
                "query": convert_and_respect_annotation_metadata(
                    object_=query, annotation=ShiftQueryParams, direction="write"
                ),
                "limit": limit,
                "cursor": cursor,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    SearchShiftsResponse,
                    construct_type(
                        type_=SearchShiftsResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def get(
        self, id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> HttpResponse[GetShiftResponse]:
        """
        Returns a single `Shift` specified by `id`.

        Parameters
        ----------
        id : str
            The UUID for the `Shift` being retrieved.

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

        Returns
        -------
        HttpResponse[GetShiftResponse]
            Success
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v2/labor/shifts/{jsonable_encoder(id)}",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    GetShiftResponse,
                    construct_type(
                        type_=GetShiftResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def update(
        self, id: str, *, shift: ShiftParams, request_options: typing.Optional[RequestOptions] = None
    ) -> HttpResponse[UpdateShiftResponse]:
        """
        Updates an existing `Shift`.

        When adding a `Break` to a `Shift`, any earlier `Break` instances in the `Shift` have
        the `end_at` property set to a valid RFC-3339 datetime string.

        When closing a `Shift`, all `Break` instances in the `Shift` must be complete with `end_at`
        set on each `Break`.

        Parameters
        ----------
        id : str
            The ID of the object being updated.

        shift : ShiftParams
            The updated `Shift` object.

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

        Returns
        -------
        HttpResponse[UpdateShiftResponse]
            Success
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v2/labor/shifts/{jsonable_encoder(id)}",
            method="PUT",
            json={
                "shift": convert_and_respect_annotation_metadata(
                    object_=shift, annotation=ShiftParams, direction="write"
                ),
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    UpdateShiftResponse,
                    construct_type(
                        type_=UpdateShiftResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    def delete(
        self, id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> HttpResponse[DeleteShiftResponse]:
        """
        Deletes a `Shift`.

        Parameters
        ----------
        id : str
            The UUID for the `Shift` being deleted.

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

        Returns
        -------
        HttpResponse[DeleteShiftResponse]
            Success
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v2/labor/shifts/{jsonable_encoder(id)}",
            method="DELETE",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    DeleteShiftResponse,
                    construct_type(
                        type_=DeleteShiftResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)


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

    async def create(
        self,
        *,
        shift: ShiftParams,
        idempotency_key: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[CreateShiftResponse]:
        """
        Creates a new `Shift`.

        A `Shift` represents a complete workday for a single team member.
        You must provide the following values in your request to this
        endpoint:

        - `location_id`
        - `team_member_id`
        - `start_at`

        An attempt to create a new `Shift` can result in a `BAD_REQUEST` error when:
        - The `status` of the new `Shift` is `OPEN` and the team member has another
        shift with an `OPEN` status.
        - The `start_at` date is in the future.
        - The `start_at` or `end_at` date overlaps another shift for the same team member.
        - The `Break` instances are set in the request and a break `start_at`
        is before the `Shift.start_at`, a break `end_at` is after
        the `Shift.end_at`, or both.

        Parameters
        ----------
        shift : ShiftParams
            The `Shift` to be created.

        idempotency_key : typing.Optional[str]
            A unique string value to ensure the idempotency of the operation.

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

        Returns
        -------
        AsyncHttpResponse[CreateShiftResponse]
            Success
        """
        _response = await self._client_wrapper.httpx_client.request(
            "v2/labor/shifts",
            method="POST",
            json={
                "idempotency_key": idempotency_key,
                "shift": convert_and_respect_annotation_metadata(
                    object_=shift, annotation=ShiftParams, direction="write"
                ),
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    CreateShiftResponse,
                    construct_type(
                        type_=CreateShiftResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def search(
        self,
        *,
        query: typing.Optional[ShiftQueryParams] = OMIT,
        limit: typing.Optional[int] = OMIT,
        cursor: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[SearchShiftsResponse]:
        """
        Returns a paginated list of `Shift` records for a business.
        The list to be returned can be filtered by:
        - Location IDs
        - Team member IDs
        - Shift status (`OPEN` or `CLOSED`)
        - Shift start
        - Shift end
        - Workday details

        The list can be sorted by:
        - `START_AT`
        - `END_AT`
        - `CREATED_AT`
        - `UPDATED_AT`

        Parameters
        ----------
        query : typing.Optional[ShiftQueryParams]
            Query filters.

        limit : typing.Optional[int]
            The number of resources in a page (200 by default).

        cursor : typing.Optional[str]
            An opaque cursor for fetching the next page.

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

        Returns
        -------
        AsyncHttpResponse[SearchShiftsResponse]
            Success
        """
        _response = await self._client_wrapper.httpx_client.request(
            "v2/labor/shifts/search",
            method="POST",
            json={
                "query": convert_and_respect_annotation_metadata(
                    object_=query, annotation=ShiftQueryParams, direction="write"
                ),
                "limit": limit,
                "cursor": cursor,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    SearchShiftsResponse,
                    construct_type(
                        type_=SearchShiftsResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def get(
        self, id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> AsyncHttpResponse[GetShiftResponse]:
        """
        Returns a single `Shift` specified by `id`.

        Parameters
        ----------
        id : str
            The UUID for the `Shift` being retrieved.

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

        Returns
        -------
        AsyncHttpResponse[GetShiftResponse]
            Success
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v2/labor/shifts/{jsonable_encoder(id)}",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    GetShiftResponse,
                    construct_type(
                        type_=GetShiftResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def update(
        self, id: str, *, shift: ShiftParams, request_options: typing.Optional[RequestOptions] = None
    ) -> AsyncHttpResponse[UpdateShiftResponse]:
        """
        Updates an existing `Shift`.

        When adding a `Break` to a `Shift`, any earlier `Break` instances in the `Shift` have
        the `end_at` property set to a valid RFC-3339 datetime string.

        When closing a `Shift`, all `Break` instances in the `Shift` must be complete with `end_at`
        set on each `Break`.

        Parameters
        ----------
        id : str
            The ID of the object being updated.

        shift : ShiftParams
            The updated `Shift` object.

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

        Returns
        -------
        AsyncHttpResponse[UpdateShiftResponse]
            Success
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v2/labor/shifts/{jsonable_encoder(id)}",
            method="PUT",
            json={
                "shift": convert_and_respect_annotation_metadata(
                    object_=shift, annotation=ShiftParams, direction="write"
                ),
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    UpdateShiftResponse,
                    construct_type(
                        type_=UpdateShiftResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)

    async def delete(
        self, id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> AsyncHttpResponse[DeleteShiftResponse]:
        """
        Deletes a `Shift`.

        Parameters
        ----------
        id : str
            The UUID for the `Shift` being deleted.

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

        Returns
        -------
        AsyncHttpResponse[DeleteShiftResponse]
            Success
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v2/labor/shifts/{jsonable_encoder(id)}",
            method="DELETE",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    DeleteShiftResponse,
                    construct_type(
                        type_=DeleteShiftResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, body=_response.text)
        raise ApiError(status_code=_response.status_code, body=_response_json)
