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

import typing
from ....core.client_wrapper import SyncClientWrapper
from ....requests.loyalty_promotion import LoyaltyPromotionParams
from ....core.request_options import RequestOptions
from ....core.http_response import HttpResponse
from ....types.create_loyalty_promotion_response import CreateLoyaltyPromotionResponse
from ....core.jsonable_encoder import jsonable_encoder
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 ....types.get_loyalty_promotion_response import GetLoyaltyPromotionResponse
from ....types.cancel_loyalty_promotion_response import CancelLoyaltyPromotionResponse
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 RawPromotionsClient:
    def __init__(self, *, client_wrapper: SyncClientWrapper):
        self._client_wrapper = client_wrapper

    def create(
        self,
        program_id: str,
        *,
        loyalty_promotion: LoyaltyPromotionParams,
        idempotency_key: str,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[CreateLoyaltyPromotionResponse]:
        """
        Creates a loyalty promotion for a [loyalty program](entity:LoyaltyProgram). A loyalty promotion
        enables buyers to earn points in addition to those earned from the base loyalty program.

        This endpoint sets the loyalty promotion to the `ACTIVE` or `SCHEDULED` status, depending on the
        `available_time` setting. A loyalty program can have a maximum of 10 loyalty promotions with an
        `ACTIVE` or `SCHEDULED` status.

        Parameters
        ----------
        program_id : str
            The ID of the [loyalty program](entity:LoyaltyProgram) to associate with the promotion.
            To get the program ID, call [RetrieveLoyaltyProgram](api-endpoint:Loyalty-RetrieveLoyaltyProgram)
            using the `main` keyword.

        loyalty_promotion : LoyaltyPromotionParams
            The loyalty promotion to create.

        idempotency_key : str
            A unique identifier for this request, which is used to ensure idempotency. For more information,
            see [Idempotency](https://developer.squareup.com/docs/build-basics/common-api-patterns/idempotency).

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

        Returns
        -------
        HttpResponse[CreateLoyaltyPromotionResponse]
            Success
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v2/loyalty/programs/{jsonable_encoder(program_id)}/promotions",
            method="POST",
            json={
                "loyalty_promotion": convert_and_respect_annotation_metadata(
                    object_=loyalty_promotion, annotation=LoyaltyPromotionParams, direction="write"
                ),
                "idempotency_key": idempotency_key,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    CreateLoyaltyPromotionResponse,
                    construct_type(
                        type_=CreateLoyaltyPromotionResponse,  # 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, promotion_id: str, program_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> HttpResponse[GetLoyaltyPromotionResponse]:
        """
        Retrieves a loyalty promotion.

        Parameters
        ----------
        promotion_id : str
            The ID of the [loyalty promotion](entity:LoyaltyPromotion) to retrieve.

        program_id : str
            The ID of the base [loyalty program](entity:LoyaltyProgram). To get the program ID,
            call [RetrieveLoyaltyProgram](api-endpoint:Loyalty-RetrieveLoyaltyProgram) using the `main` keyword.

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

        Returns
        -------
        HttpResponse[GetLoyaltyPromotionResponse]
            Success
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v2/loyalty/programs/{jsonable_encoder(program_id)}/promotions/{jsonable_encoder(promotion_id)}",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    GetLoyaltyPromotionResponse,
                    construct_type(
                        type_=GetLoyaltyPromotionResponse,  # 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 cancel(
        self, promotion_id: str, program_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> HttpResponse[CancelLoyaltyPromotionResponse]:
        """
        Cancels a loyalty promotion. Use this endpoint to cancel an `ACTIVE` promotion earlier than the
        end date, cancel an `ACTIVE` promotion when an end date is not specified, or cancel a `SCHEDULED` promotion.
        Because updating a promotion is not supported, you can also use this endpoint to cancel a promotion before
        you create a new one.

        This endpoint sets the loyalty promotion to the `CANCELED` state

        Parameters
        ----------
        promotion_id : str
            The ID of the [loyalty promotion](entity:LoyaltyPromotion) to cancel. You can cancel a
            promotion that has an `ACTIVE` or `SCHEDULED` status.

        program_id : str
            The ID of the base [loyalty program](entity:LoyaltyProgram).

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

        Returns
        -------
        HttpResponse[CancelLoyaltyPromotionResponse]
            Success
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v2/loyalty/programs/{jsonable_encoder(program_id)}/promotions/{jsonable_encoder(promotion_id)}/cancel",
            method="POST",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    CancelLoyaltyPromotionResponse,
                    construct_type(
                        type_=CancelLoyaltyPromotionResponse,  # 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 AsyncRawPromotionsClient:
    def __init__(self, *, client_wrapper: AsyncClientWrapper):
        self._client_wrapper = client_wrapper

    async def create(
        self,
        program_id: str,
        *,
        loyalty_promotion: LoyaltyPromotionParams,
        idempotency_key: str,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[CreateLoyaltyPromotionResponse]:
        """
        Creates a loyalty promotion for a [loyalty program](entity:LoyaltyProgram). A loyalty promotion
        enables buyers to earn points in addition to those earned from the base loyalty program.

        This endpoint sets the loyalty promotion to the `ACTIVE` or `SCHEDULED` status, depending on the
        `available_time` setting. A loyalty program can have a maximum of 10 loyalty promotions with an
        `ACTIVE` or `SCHEDULED` status.

        Parameters
        ----------
        program_id : str
            The ID of the [loyalty program](entity:LoyaltyProgram) to associate with the promotion.
            To get the program ID, call [RetrieveLoyaltyProgram](api-endpoint:Loyalty-RetrieveLoyaltyProgram)
            using the `main` keyword.

        loyalty_promotion : LoyaltyPromotionParams
            The loyalty promotion to create.

        idempotency_key : str
            A unique identifier for this request, which is used to ensure idempotency. For more information,
            see [Idempotency](https://developer.squareup.com/docs/build-basics/common-api-patterns/idempotency).

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

        Returns
        -------
        AsyncHttpResponse[CreateLoyaltyPromotionResponse]
            Success
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v2/loyalty/programs/{jsonable_encoder(program_id)}/promotions",
            method="POST",
            json={
                "loyalty_promotion": convert_and_respect_annotation_metadata(
                    object_=loyalty_promotion, annotation=LoyaltyPromotionParams, direction="write"
                ),
                "idempotency_key": idempotency_key,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    CreateLoyaltyPromotionResponse,
                    construct_type(
                        type_=CreateLoyaltyPromotionResponse,  # 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, promotion_id: str, program_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> AsyncHttpResponse[GetLoyaltyPromotionResponse]:
        """
        Retrieves a loyalty promotion.

        Parameters
        ----------
        promotion_id : str
            The ID of the [loyalty promotion](entity:LoyaltyPromotion) to retrieve.

        program_id : str
            The ID of the base [loyalty program](entity:LoyaltyProgram). To get the program ID,
            call [RetrieveLoyaltyProgram](api-endpoint:Loyalty-RetrieveLoyaltyProgram) using the `main` keyword.

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

        Returns
        -------
        AsyncHttpResponse[GetLoyaltyPromotionResponse]
            Success
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v2/loyalty/programs/{jsonable_encoder(program_id)}/promotions/{jsonable_encoder(promotion_id)}",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    GetLoyaltyPromotionResponse,
                    construct_type(
                        type_=GetLoyaltyPromotionResponse,  # 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 cancel(
        self, promotion_id: str, program_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> AsyncHttpResponse[CancelLoyaltyPromotionResponse]:
        """
        Cancels a loyalty promotion. Use this endpoint to cancel an `ACTIVE` promotion earlier than the
        end date, cancel an `ACTIVE` promotion when an end date is not specified, or cancel a `SCHEDULED` promotion.
        Because updating a promotion is not supported, you can also use this endpoint to cancel a promotion before
        you create a new one.

        This endpoint sets the loyalty promotion to the `CANCELED` state

        Parameters
        ----------
        promotion_id : str
            The ID of the [loyalty promotion](entity:LoyaltyPromotion) to cancel. You can cancel a
            promotion that has an `ACTIVE` or `SCHEDULED` status.

        program_id : str
            The ID of the base [loyalty program](entity:LoyaltyProgram).

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

        Returns
        -------
        AsyncHttpResponse[CancelLoyaltyPromotionResponse]
            Success
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v2/loyalty/programs/{jsonable_encoder(program_id)}/promotions/{jsonable_encoder(promotion_id)}/cancel",
            method="POST",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    CancelLoyaltyPromotionResponse,
                    construct_type(
                        type_=CancelLoyaltyPromotionResponse,  # 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)
