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

import typing
from ..core.client_wrapper import SyncClientWrapper
from .raw_client import RawGiftCardsClient
from .activities.client import ActivitiesClient
from ..core.request_options import RequestOptions
from ..core.pagination import SyncPager
from ..types.gift_card import GiftCard
from ..types.list_gift_cards_response import ListGiftCardsResponse
from ..core.unchecked_base_model import construct_type
from json.decoder import JSONDecodeError
from ..core.api_error import ApiError
from ..requests.gift_card import GiftCardParams
from ..types.create_gift_card_response import CreateGiftCardResponse
from ..types.get_gift_card_from_gan_response import GetGiftCardFromGanResponse
from ..types.get_gift_card_from_nonce_response import GetGiftCardFromNonceResponse
from ..types.link_customer_to_gift_card_response import LinkCustomerToGiftCardResponse
from ..types.unlink_customer_from_gift_card_response import UnlinkCustomerFromGiftCardResponse
from ..types.get_gift_card_response import GetGiftCardResponse
from ..core.client_wrapper import AsyncClientWrapper
from .raw_client import AsyncRawGiftCardsClient
from .activities.client import AsyncActivitiesClient
from ..core.pagination import AsyncPager

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


class GiftCardsClient:
    def __init__(self, *, client_wrapper: SyncClientWrapper):
        self._raw_client = RawGiftCardsClient(client_wrapper=client_wrapper)
        self.activities = ActivitiesClient(client_wrapper=client_wrapper)

    @property
    def with_raw_response(self) -> RawGiftCardsClient:
        """
        Retrieves a raw implementation of this client that returns raw responses.

        Returns
        -------
        RawGiftCardsClient
        """
        return self._raw_client

    def list(
        self,
        *,
        type: typing.Optional[str] = None,
        state: typing.Optional[str] = None,
        limit: typing.Optional[int] = None,
        cursor: typing.Optional[str] = None,
        customer_id: typing.Optional[str] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> SyncPager[GiftCard]:
        """
        Lists all gift cards. You can specify optional filters to retrieve
        a subset of the gift cards. Results are sorted by `created_at` in ascending order.

        Parameters
        ----------
        type : typing.Optional[str]
            If a [type](entity:GiftCardType) is provided, the endpoint returns gift cards of the specified type.
            Otherwise, the endpoint returns gift cards of all types.

        state : typing.Optional[str]
            If a [state](entity:GiftCardStatus) is provided, the endpoint returns the gift cards in the specified state.
            Otherwise, the endpoint returns the gift cards of all states.

        limit : typing.Optional[int]
            If a limit is provided, the endpoint returns only the specified number of results per page.
            The maximum value is 200. The default value is 30.
            For more information, see [Pagination](https://developer.squareup.com/docs/working-with-apis/pagination).

        cursor : typing.Optional[str]
            A pagination cursor returned by a previous call to this endpoint.
            Provide this cursor to retrieve the next set of results for the original query.
            If a cursor is not provided, the endpoint returns the first page of the results.
            For more information, see [Pagination](https://developer.squareup.com/docs/working-with-apis/pagination).

        customer_id : typing.Optional[str]
            If a customer ID is provided, the endpoint returns only the gift cards linked to the specified customer.

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

        Returns
        -------
        SyncPager[GiftCard]
            Success

        Examples
        --------
        from square import Square

        client = Square(
            token="YOUR_TOKEN",
        )
        response = client.gift_cards.list()
        for item in response:
            yield item
        # alternatively, you can paginate page-by-page
        for page in response.iter_pages():
            yield page
        """
        _response = self._raw_client._client_wrapper.httpx_client.request(
            "v2/gift-cards",
            method="GET",
            params={
                "type": type,
                "state": state,
                "limit": limit,
                "cursor": cursor,
                "customer_id": customer_id,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _parsed_response = typing.cast(
                    ListGiftCardsResponse,
                    construct_type(
                        type_=ListGiftCardsResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                _parsed_next = _parsed_response.cursor
                _has_next = _parsed_next is not None and _parsed_next != ""
                _get_next = lambda: self.list(
                    type=type,
                    state=state,
                    limit=limit,
                    cursor=_parsed_next,
                    customer_id=customer_id,
                    request_options=request_options,
                )
                _items = _parsed_response.gift_cards
                return SyncPager(has_next=_has_next, items=_items, get_next=_get_next)
            _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 create(
        self,
        *,
        idempotency_key: str,
        location_id: str,
        gift_card: GiftCardParams,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> CreateGiftCardResponse:
        """
        Creates a digital gift card or registers a physical (plastic) gift card. The resulting gift card
        has a `PENDING` state. To activate a gift card so that it can be redeemed for purchases, call
        [CreateGiftCardActivity](api-endpoint:GiftCardActivities-CreateGiftCardActivity) and create an `ACTIVATE`
        activity with the initial balance. Alternatively, you can use [RefundPayment](api-endpoint:Refunds-RefundPayment)
        to refund a payment to the new gift card.

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

        location_id : str
            The ID of the [location](entity:Location) where the gift card should be registered for
            reporting purposes. Gift cards can be redeemed at any of the seller's locations.

        gift_card : GiftCardParams
            The gift card to create. The `type` field is required for this request. The `gan_source`
            and `gan` fields are included as follows:

            To direct Square to generate a 16-digit GAN, omit `gan_source` and `gan`.

            To provide a custom GAN, include `gan_source` and `gan`.
            - For `gan_source`, specify `OTHER`.
            - For `gan`, provide a custom GAN containing 8 to 20 alphanumeric characters. The GAN must be
            unique for the seller and cannot start with the same bank identification number (BIN) as major
            credit cards. Do not use GANs that are easy to guess (such as 12345678) because they greatly
            increase the risk of fraud. It is the responsibility of the developer to ensure the security
            of their custom GANs. For more information, see
            [Custom GANs](https://developer.squareup.com/docs/gift-cards/using-gift-cards-api#custom-gans).

            To register an unused, physical gift card that the seller previously ordered from Square,
            include `gan` and provide the GAN that is printed on the gift card.

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

        Returns
        -------
        CreateGiftCardResponse
            Success

        Examples
        --------
        from square import Square

        client = Square(
            token="YOUR_TOKEN",
        )
        client.gift_cards.create(
            idempotency_key="NC9Tm69EjbjtConu",
            location_id="81FN9BNFZTKS4",
            gift_card={"type": "DIGITAL"},
        )
        """
        response = self._raw_client.create(
            idempotency_key=idempotency_key,
            location_id=location_id,
            gift_card=gift_card,
            request_options=request_options,
        )
        return response.data

    def get_from_gan(
        self, *, gan: str, request_options: typing.Optional[RequestOptions] = None
    ) -> GetGiftCardFromGanResponse:
        """
        Retrieves a gift card using the gift card account number (GAN).

        Parameters
        ----------
        gan : str
            The gift card account number (GAN) of the gift card to retrieve.
            The maximum length of a GAN is 255 digits to account for third-party GANs that have been imported.
            Square-issued gift cards have 16-digit GANs.

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

        Returns
        -------
        GetGiftCardFromGanResponse
            Success

        Examples
        --------
        from square import Square

        client = Square(
            token="YOUR_TOKEN",
        )
        client.gift_cards.get_from_gan(
            gan="7783320001001635",
        )
        """
        response = self._raw_client.get_from_gan(gan=gan, request_options=request_options)
        return response.data

    def get_from_nonce(
        self, *, nonce: str, request_options: typing.Optional[RequestOptions] = None
    ) -> GetGiftCardFromNonceResponse:
        """
        Retrieves a gift card using a secure payment token that represents the gift card.

        Parameters
        ----------
        nonce : str
            The payment token of the gift card to retrieve. Payment tokens are generated by the
            Web Payments SDK or In-App Payments SDK.

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

        Returns
        -------
        GetGiftCardFromNonceResponse
            Success

        Examples
        --------
        from square import Square

        client = Square(
            token="YOUR_TOKEN",
        )
        client.gift_cards.get_from_nonce(
            nonce="cnon:7783322135245171",
        )
        """
        response = self._raw_client.get_from_nonce(nonce=nonce, request_options=request_options)
        return response.data

    def link_customer(
        self, gift_card_id: str, *, customer_id: str, request_options: typing.Optional[RequestOptions] = None
    ) -> LinkCustomerToGiftCardResponse:
        """
        Links a customer to a gift card, which is also referred to as adding a card on file.

        Parameters
        ----------
        gift_card_id : str
            The ID of the gift card to be linked.

        customer_id : str
            The ID of the customer to link to the gift card.

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

        Returns
        -------
        LinkCustomerToGiftCardResponse
            Success

        Examples
        --------
        from square import Square

        client = Square(
            token="YOUR_TOKEN",
        )
        client.gift_cards.link_customer(
            gift_card_id="gift_card_id",
            customer_id="GKY0FZ3V717AH8Q2D821PNT2ZW",
        )
        """
        response = self._raw_client.link_customer(
            gift_card_id, customer_id=customer_id, request_options=request_options
        )
        return response.data

    def unlink_customer(
        self, gift_card_id: str, *, customer_id: str, request_options: typing.Optional[RequestOptions] = None
    ) -> UnlinkCustomerFromGiftCardResponse:
        """
        Unlinks a customer from a gift card, which is also referred to as removing a card on file.

        Parameters
        ----------
        gift_card_id : str
            The ID of the gift card to be unlinked.

        customer_id : str
            The ID of the customer to unlink from the gift card.

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

        Returns
        -------
        UnlinkCustomerFromGiftCardResponse
            Success

        Examples
        --------
        from square import Square

        client = Square(
            token="YOUR_TOKEN",
        )
        client.gift_cards.unlink_customer(
            gift_card_id="gift_card_id",
            customer_id="GKY0FZ3V717AH8Q2D821PNT2ZW",
        )
        """
        response = self._raw_client.unlink_customer(
            gift_card_id, customer_id=customer_id, request_options=request_options
        )
        return response.data

    def get(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> GetGiftCardResponse:
        """
        Retrieves a gift card using the gift card ID.

        Parameters
        ----------
        id : str
            The ID of the gift card to retrieve.

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

        Returns
        -------
        GetGiftCardResponse
            Success

        Examples
        --------
        from square import Square

        client = Square(
            token="YOUR_TOKEN",
        )
        client.gift_cards.get(
            id="id",
        )
        """
        response = self._raw_client.get(id, request_options=request_options)
        return response.data


class AsyncGiftCardsClient:
    def __init__(self, *, client_wrapper: AsyncClientWrapper):
        self._raw_client = AsyncRawGiftCardsClient(client_wrapper=client_wrapper)
        self.activities = AsyncActivitiesClient(client_wrapper=client_wrapper)

    @property
    def with_raw_response(self) -> AsyncRawGiftCardsClient:
        """
        Retrieves a raw implementation of this client that returns raw responses.

        Returns
        -------
        AsyncRawGiftCardsClient
        """
        return self._raw_client

    async def list(
        self,
        *,
        type: typing.Optional[str] = None,
        state: typing.Optional[str] = None,
        limit: typing.Optional[int] = None,
        cursor: typing.Optional[str] = None,
        customer_id: typing.Optional[str] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncPager[GiftCard]:
        """
        Lists all gift cards. You can specify optional filters to retrieve
        a subset of the gift cards. Results are sorted by `created_at` in ascending order.

        Parameters
        ----------
        type : typing.Optional[str]
            If a [type](entity:GiftCardType) is provided, the endpoint returns gift cards of the specified type.
            Otherwise, the endpoint returns gift cards of all types.

        state : typing.Optional[str]
            If a [state](entity:GiftCardStatus) is provided, the endpoint returns the gift cards in the specified state.
            Otherwise, the endpoint returns the gift cards of all states.

        limit : typing.Optional[int]
            If a limit is provided, the endpoint returns only the specified number of results per page.
            The maximum value is 200. The default value is 30.
            For more information, see [Pagination](https://developer.squareup.com/docs/working-with-apis/pagination).

        cursor : typing.Optional[str]
            A pagination cursor returned by a previous call to this endpoint.
            Provide this cursor to retrieve the next set of results for the original query.
            If a cursor is not provided, the endpoint returns the first page of the results.
            For more information, see [Pagination](https://developer.squareup.com/docs/working-with-apis/pagination).

        customer_id : typing.Optional[str]
            If a customer ID is provided, the endpoint returns only the gift cards linked to the specified customer.

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

        Returns
        -------
        AsyncPager[GiftCard]
            Success

        Examples
        --------
        import asyncio

        from square import AsyncSquare

        client = AsyncSquare(
            token="YOUR_TOKEN",
        )


        async def main() -> None:
            response = await client.gift_cards.list()
            async for item in response:
                yield item
            # alternatively, you can paginate page-by-page
            async for page in response.iter_pages():
                yield page


        asyncio.run(main())
        """
        _response = await self._raw_client._client_wrapper.httpx_client.request(
            "v2/gift-cards",
            method="GET",
            params={
                "type": type,
                "state": state,
                "limit": limit,
                "cursor": cursor,
                "customer_id": customer_id,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _parsed_response = typing.cast(
                    ListGiftCardsResponse,
                    construct_type(
                        type_=ListGiftCardsResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                _parsed_next = _parsed_response.cursor
                _has_next = _parsed_next is not None and _parsed_next != ""
                _get_next = lambda: self.list(
                    type=type,
                    state=state,
                    limit=limit,
                    cursor=_parsed_next,
                    customer_id=customer_id,
                    request_options=request_options,
                )
                _items = _parsed_response.gift_cards
                return AsyncPager(has_next=_has_next, items=_items, get_next=_get_next)
            _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 create(
        self,
        *,
        idempotency_key: str,
        location_id: str,
        gift_card: GiftCardParams,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> CreateGiftCardResponse:
        """
        Creates a digital gift card or registers a physical (plastic) gift card. The resulting gift card
        has a `PENDING` state. To activate a gift card so that it can be redeemed for purchases, call
        [CreateGiftCardActivity](api-endpoint:GiftCardActivities-CreateGiftCardActivity) and create an `ACTIVATE`
        activity with the initial balance. Alternatively, you can use [RefundPayment](api-endpoint:Refunds-RefundPayment)
        to refund a payment to the new gift card.

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

        location_id : str
            The ID of the [location](entity:Location) where the gift card should be registered for
            reporting purposes. Gift cards can be redeemed at any of the seller's locations.

        gift_card : GiftCardParams
            The gift card to create. The `type` field is required for this request. The `gan_source`
            and `gan` fields are included as follows:

            To direct Square to generate a 16-digit GAN, omit `gan_source` and `gan`.

            To provide a custom GAN, include `gan_source` and `gan`.
            - For `gan_source`, specify `OTHER`.
            - For `gan`, provide a custom GAN containing 8 to 20 alphanumeric characters. The GAN must be
            unique for the seller and cannot start with the same bank identification number (BIN) as major
            credit cards. Do not use GANs that are easy to guess (such as 12345678) because they greatly
            increase the risk of fraud. It is the responsibility of the developer to ensure the security
            of their custom GANs. For more information, see
            [Custom GANs](https://developer.squareup.com/docs/gift-cards/using-gift-cards-api#custom-gans).

            To register an unused, physical gift card that the seller previously ordered from Square,
            include `gan` and provide the GAN that is printed on the gift card.

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

        Returns
        -------
        CreateGiftCardResponse
            Success

        Examples
        --------
        import asyncio

        from square import AsyncSquare

        client = AsyncSquare(
            token="YOUR_TOKEN",
        )


        async def main() -> None:
            await client.gift_cards.create(
                idempotency_key="NC9Tm69EjbjtConu",
                location_id="81FN9BNFZTKS4",
                gift_card={"type": "DIGITAL"},
            )


        asyncio.run(main())
        """
        response = await self._raw_client.create(
            idempotency_key=idempotency_key,
            location_id=location_id,
            gift_card=gift_card,
            request_options=request_options,
        )
        return response.data

    async def get_from_gan(
        self, *, gan: str, request_options: typing.Optional[RequestOptions] = None
    ) -> GetGiftCardFromGanResponse:
        """
        Retrieves a gift card using the gift card account number (GAN).

        Parameters
        ----------
        gan : str
            The gift card account number (GAN) of the gift card to retrieve.
            The maximum length of a GAN is 255 digits to account for third-party GANs that have been imported.
            Square-issued gift cards have 16-digit GANs.

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

        Returns
        -------
        GetGiftCardFromGanResponse
            Success

        Examples
        --------
        import asyncio

        from square import AsyncSquare

        client = AsyncSquare(
            token="YOUR_TOKEN",
        )


        async def main() -> None:
            await client.gift_cards.get_from_gan(
                gan="7783320001001635",
            )


        asyncio.run(main())
        """
        response = await self._raw_client.get_from_gan(gan=gan, request_options=request_options)
        return response.data

    async def get_from_nonce(
        self, *, nonce: str, request_options: typing.Optional[RequestOptions] = None
    ) -> GetGiftCardFromNonceResponse:
        """
        Retrieves a gift card using a secure payment token that represents the gift card.

        Parameters
        ----------
        nonce : str
            The payment token of the gift card to retrieve. Payment tokens are generated by the
            Web Payments SDK or In-App Payments SDK.

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

        Returns
        -------
        GetGiftCardFromNonceResponse
            Success

        Examples
        --------
        import asyncio

        from square import AsyncSquare

        client = AsyncSquare(
            token="YOUR_TOKEN",
        )


        async def main() -> None:
            await client.gift_cards.get_from_nonce(
                nonce="cnon:7783322135245171",
            )


        asyncio.run(main())
        """
        response = await self._raw_client.get_from_nonce(nonce=nonce, request_options=request_options)
        return response.data

    async def link_customer(
        self, gift_card_id: str, *, customer_id: str, request_options: typing.Optional[RequestOptions] = None
    ) -> LinkCustomerToGiftCardResponse:
        """
        Links a customer to a gift card, which is also referred to as adding a card on file.

        Parameters
        ----------
        gift_card_id : str
            The ID of the gift card to be linked.

        customer_id : str
            The ID of the customer to link to the gift card.

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

        Returns
        -------
        LinkCustomerToGiftCardResponse
            Success

        Examples
        --------
        import asyncio

        from square import AsyncSquare

        client = AsyncSquare(
            token="YOUR_TOKEN",
        )


        async def main() -> None:
            await client.gift_cards.link_customer(
                gift_card_id="gift_card_id",
                customer_id="GKY0FZ3V717AH8Q2D821PNT2ZW",
            )


        asyncio.run(main())
        """
        response = await self._raw_client.link_customer(
            gift_card_id, customer_id=customer_id, request_options=request_options
        )
        return response.data

    async def unlink_customer(
        self, gift_card_id: str, *, customer_id: str, request_options: typing.Optional[RequestOptions] = None
    ) -> UnlinkCustomerFromGiftCardResponse:
        """
        Unlinks a customer from a gift card, which is also referred to as removing a card on file.

        Parameters
        ----------
        gift_card_id : str
            The ID of the gift card to be unlinked.

        customer_id : str
            The ID of the customer to unlink from the gift card.

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

        Returns
        -------
        UnlinkCustomerFromGiftCardResponse
            Success

        Examples
        --------
        import asyncio

        from square import AsyncSquare

        client = AsyncSquare(
            token="YOUR_TOKEN",
        )


        async def main() -> None:
            await client.gift_cards.unlink_customer(
                gift_card_id="gift_card_id",
                customer_id="GKY0FZ3V717AH8Q2D821PNT2ZW",
            )


        asyncio.run(main())
        """
        response = await self._raw_client.unlink_customer(
            gift_card_id, customer_id=customer_id, request_options=request_options
        )
        return response.data

    async def get(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> GetGiftCardResponse:
        """
        Retrieves a gift card using the gift card ID.

        Parameters
        ----------
        id : str
            The ID of the gift card to retrieve.

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

        Returns
        -------
        GetGiftCardResponse
            Success

        Examples
        --------
        import asyncio

        from square import AsyncSquare

        client = AsyncSquare(
            token="YOUR_TOKEN",
        )


        async def main() -> None:
            await client.gift_cards.get(
                id="id",
            )


        asyncio.run(main())
        """
        response = await self._raw_client.get(id, request_options=request_options)
        return response.data
