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

import typing
from json.decoder import JSONDecodeError

from ...core.api_error import ApiError
from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
from ...core.http_response import AsyncHttpResponse, HttpResponse
from ...core.jsonable_encoder import jsonable_encoder
from ...core.pagination import AsyncPager, SyncPager
from ...core.request_options import RequestOptions
from ...core.serialization import convert_and_respect_annotation_metadata
from ...core.unchecked_base_model import construct_type
from ...requests.batch_upsert_customer_custom_attributes_request_customer_custom_attribute_upsert_request import (
    BatchUpsertCustomerCustomAttributesRequestCustomerCustomAttributeUpsertRequestParams,
)
from ...requests.custom_attribute_definition import CustomAttributeDefinitionParams
from ...types.batch_upsert_customer_custom_attributes_response import BatchUpsertCustomerCustomAttributesResponse
from ...types.create_customer_custom_attribute_definition_response import (
    CreateCustomerCustomAttributeDefinitionResponse,
)
from ...types.custom_attribute_definition import CustomAttributeDefinition
from ...types.delete_customer_custom_attribute_definition_response import (
    DeleteCustomerCustomAttributeDefinitionResponse,
)
from ...types.get_customer_custom_attribute_definition_response import GetCustomerCustomAttributeDefinitionResponse
from ...types.list_customer_custom_attribute_definitions_response import ListCustomerCustomAttributeDefinitionsResponse
from ...types.update_customer_custom_attribute_definition_response import (
    UpdateCustomerCustomAttributeDefinitionResponse,
)

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


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

    def list(
        self,
        *,
        limit: typing.Optional[int] = None,
        cursor: typing.Optional[str] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> SyncPager[CustomAttributeDefinition, ListCustomerCustomAttributeDefinitionsResponse]:
        """
        Lists the customer-related [custom attribute definitions](entity:CustomAttributeDefinition) that belong to a Square seller account.

        When all response pages are retrieved, the results include all custom attribute definitions
        that are visible to the requesting application, including those that are created by other
        applications and set to `VISIBILITY_READ_ONLY` or `VISIBILITY_READ_WRITE_VALUES`. Note that
        seller-defined custom attributes (also known as custom fields) are always set to `VISIBILITY_READ_WRITE_VALUES`.

        Parameters
        ----------
        limit : typing.Optional[int]
            The maximum number of results to return in a single paged response. This limit is advisory.
            The response might contain more or fewer results. The minimum value is 1 and the maximum value is 100.
            The default value is 20. For more information, see [Pagination](https://developer.squareup.com/docs/build-basics/common-api-patterns/pagination).

        cursor : typing.Optional[str]
            The cursor returned in the paged response from the previous call to this endpoint.
            Provide this cursor to retrieve the next page of results for your original request.
            For more information, see [Pagination](https://developer.squareup.com/docs/build-basics/common-api-patterns/pagination).

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

        Returns
        -------
        SyncPager[CustomAttributeDefinition, ListCustomerCustomAttributeDefinitionsResponse]
            Success
        """
        _response = self._client_wrapper.httpx_client.request(
            "v2/customers/custom-attribute-definitions",
            method="GET",
            params={
                "limit": limit,
                "cursor": cursor,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _parsed_response = typing.cast(
                    ListCustomerCustomAttributeDefinitionsResponse,
                    construct_type(
                        type_=ListCustomerCustomAttributeDefinitionsResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                _items = _parsed_response.custom_attribute_definitions
                _parsed_next = _parsed_response.cursor
                _has_next = _parsed_next is not None and _parsed_next != ""
                _get_next = lambda: self.list(
                    limit=limit,
                    cursor=_parsed_next,
                    request_options=request_options,
                )
                return SyncPager(has_next=_has_next, items=_items, get_next=_get_next, response=_parsed_response)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def create(
        self,
        *,
        custom_attribute_definition: CustomAttributeDefinitionParams,
        idempotency_key: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[CreateCustomerCustomAttributeDefinitionResponse]:
        """
        Creates a customer-related [custom attribute definition](entity:CustomAttributeDefinition) for a Square seller account.
        Use this endpoint to define a custom attribute that can be associated with customer profiles.

        A custom attribute definition specifies the `key`, `visibility`, `schema`, and other properties
        for a custom attribute. After the definition is created, you can call
        [UpsertCustomerCustomAttribute](api-endpoint:CustomerCustomAttributes-UpsertCustomerCustomAttribute) or
        [BulkUpsertCustomerCustomAttributes](api-endpoint:CustomerCustomAttributes-BulkUpsertCustomerCustomAttributes)
        to set the custom attribute for customer profiles in the seller's Customer Directory.

        Sellers can view all custom attributes in exported customer data, including those set to
        `VISIBILITY_HIDDEN`.

        Parameters
        ----------
        custom_attribute_definition : CustomAttributeDefinitionParams
            The custom attribute definition to create. Note the following:
            - With the exception of the `Selection` data type, the `schema` is specified as a simple URL to the JSON schema
            definition hosted on the Square CDN. For more information, including supported values and constraints, see
            [Specifying the schema](https://developer.squareup.com/docs/customer-custom-attributes-api/custom-attribute-definitions#specify-schema).
            - If provided, `name` must be unique (case-sensitive) across all visible customer-related custom attribute definitions for the seller.
            - All custom attributes are visible in exported customer data, including those set to `VISIBILITY_HIDDEN`.

        idempotency_key : typing.Optional[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).

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

        Returns
        -------
        HttpResponse[CreateCustomerCustomAttributeDefinitionResponse]
            Success
        """
        _response = self._client_wrapper.httpx_client.request(
            "v2/customers/custom-attribute-definitions",
            method="POST",
            json={
                "custom_attribute_definition": convert_and_respect_annotation_metadata(
                    object_=custom_attribute_definition, annotation=CustomAttributeDefinitionParams, 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(
                    CreateCustomerCustomAttributeDefinitionResponse,
                    construct_type(
                        type_=CreateCustomerCustomAttributeDefinitionResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            _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, key: str, *, version: typing.Optional[int] = None, request_options: typing.Optional[RequestOptions] = None
    ) -> HttpResponse[GetCustomerCustomAttributeDefinitionResponse]:
        """
        Retrieves a customer-related [custom attribute definition](entity:CustomAttributeDefinition) from a Square seller account.

        To retrieve a custom attribute definition created by another application, the `visibility`
        setting must be `VISIBILITY_READ_ONLY` or `VISIBILITY_READ_WRITE_VALUES`. Note that seller-defined custom attributes
        (also known as custom fields) are always set to `VISIBILITY_READ_WRITE_VALUES`.

        Parameters
        ----------
        key : str
            The key of the custom attribute definition to retrieve. If the requesting application
            is not the definition owner, you must use the qualified key.

        version : typing.Optional[int]
            The current version of the custom attribute definition, which is used for strongly consistent
            reads to guarantee that you receive the most up-to-date data. When included in the request,
            Square returns the specified version or a higher version if one exists. If the specified version
            is higher than the current version, Square returns a `BAD_REQUEST` error.

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

        Returns
        -------
        HttpResponse[GetCustomerCustomAttributeDefinitionResponse]
            Success
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v2/customers/custom-attribute-definitions/{jsonable_encoder(key)}",
            method="GET",
            params={
                "version": version,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    GetCustomerCustomAttributeDefinitionResponse,
                    construct_type(
                        type_=GetCustomerCustomAttributeDefinitionResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def update(
        self,
        key: str,
        *,
        custom_attribute_definition: CustomAttributeDefinitionParams,
        idempotency_key: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[UpdateCustomerCustomAttributeDefinitionResponse]:
        """
        Updates a customer-related [custom attribute definition](entity:CustomAttributeDefinition) for a Square seller account.

        Use this endpoint to update the following fields: `name`, `description`, `visibility`, or the
        `schema` for a `Selection` data type.

        Only the definition owner can update a custom attribute definition. Note that sellers can view
        all custom attributes in exported customer data, including those set to `VISIBILITY_HIDDEN`.

        Parameters
        ----------
        key : str
            The key of the custom attribute definition to update.

        custom_attribute_definition : CustomAttributeDefinitionParams
            The custom attribute definition that contains the fields to update. This endpoint
            supports sparse updates, so only new or changed fields need to be included in the request.
            Only the following fields can be updated:

            - `name`
            - `description`
            - `visibility`
            - `schema` for a `Selection` data type. Only changes to the named options or the maximum number of allowed
            selections are supported.

            For more information, see
            [Updatable definition fields](https://developer.squareup.com/docs/customer-custom-attributes-api/custom-attribute-definitions#updatable-definition-fields).

            To enable [optimistic concurrency](https://developer.squareup.com/docs/build-basics/common-api-patterns/optimistic-concurrency)
            control, include the optional `version` field and specify the current version of the custom attribute definition.

        idempotency_key : typing.Optional[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).

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

        Returns
        -------
        HttpResponse[UpdateCustomerCustomAttributeDefinitionResponse]
            Success
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v2/customers/custom-attribute-definitions/{jsonable_encoder(key)}",
            method="PUT",
            json={
                "custom_attribute_definition": convert_and_respect_annotation_metadata(
                    object_=custom_attribute_definition, annotation=CustomAttributeDefinitionParams, 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(
                    UpdateCustomerCustomAttributeDefinitionResponse,
                    construct_type(
                        type_=UpdateCustomerCustomAttributeDefinitionResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            _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 delete(
        self, key: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> HttpResponse[DeleteCustomerCustomAttributeDefinitionResponse]:
        """
        Deletes a customer-related [custom attribute definition](entity:CustomAttributeDefinition) from a Square seller account.

        Deleting a custom attribute definition also deletes the corresponding custom attribute from
        all customer profiles in the seller's Customer Directory.

        Only the definition owner can delete a custom attribute definition.

        Parameters
        ----------
        key : str
            The key of the custom attribute definition to delete.

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

        Returns
        -------
        HttpResponse[DeleteCustomerCustomAttributeDefinitionResponse]
            Success
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v2/customers/custom-attribute-definitions/{jsonable_encoder(key)}",
            method="DELETE",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    DeleteCustomerCustomAttributeDefinitionResponse,
                    construct_type(
                        type_=DeleteCustomerCustomAttributeDefinitionResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            _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 batch_upsert(
        self,
        *,
        values: typing.Dict[str, BatchUpsertCustomerCustomAttributesRequestCustomerCustomAttributeUpsertRequestParams],
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[BatchUpsertCustomerCustomAttributesResponse]:
        """
        Creates or updates [custom attributes](entity:CustomAttribute) for customer profiles as a bulk operation.

        Use this endpoint to set the value of one or more custom attributes for one or more customer profiles.
        A custom attribute is based on a custom attribute definition in a Square seller account, which is
        created using the [CreateCustomerCustomAttributeDefinition](api-endpoint:CustomerCustomAttributes-CreateCustomerCustomAttributeDefinition) endpoint.

        This `BulkUpsertCustomerCustomAttributes` endpoint accepts a map of 1 to 25 individual upsert
        requests and returns a map of individual upsert responses. Each upsert request has a unique ID
        and provides a customer ID and custom attribute. Each upsert response is returned with the ID
        of the corresponding request.

        To create or update a custom attribute owned by another application, the `visibility` setting
        must be `VISIBILITY_READ_WRITE_VALUES`. Note that seller-defined custom attributes
        (also known as custom fields) are always set to `VISIBILITY_READ_WRITE_VALUES`.

        Parameters
        ----------
        values : typing.Dict[str, BatchUpsertCustomerCustomAttributesRequestCustomerCustomAttributeUpsertRequestParams]
            A map containing 1 to 25 individual upsert requests. For each request, provide an
            arbitrary ID that is unique for this `BulkUpsertCustomerCustomAttributes` request and the
            information needed to create or update a custom attribute.

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

        Returns
        -------
        HttpResponse[BatchUpsertCustomerCustomAttributesResponse]
            Success
        """
        _response = self._client_wrapper.httpx_client.request(
            "v2/customers/custom-attributes/bulk-upsert",
            method="POST",
            json={
                "values": convert_and_respect_annotation_metadata(
                    object_=values,
                    annotation=typing.Dict[
                        str, BatchUpsertCustomerCustomAttributesRequestCustomerCustomAttributeUpsertRequestParams
                    ],
                    direction="write",
                ),
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    BatchUpsertCustomerCustomAttributesResponse,
                    construct_type(
                        type_=BatchUpsertCustomerCustomAttributesResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)


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

    async def list(
        self,
        *,
        limit: typing.Optional[int] = None,
        cursor: typing.Optional[str] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncPager[CustomAttributeDefinition, ListCustomerCustomAttributeDefinitionsResponse]:
        """
        Lists the customer-related [custom attribute definitions](entity:CustomAttributeDefinition) that belong to a Square seller account.

        When all response pages are retrieved, the results include all custom attribute definitions
        that are visible to the requesting application, including those that are created by other
        applications and set to `VISIBILITY_READ_ONLY` or `VISIBILITY_READ_WRITE_VALUES`. Note that
        seller-defined custom attributes (also known as custom fields) are always set to `VISIBILITY_READ_WRITE_VALUES`.

        Parameters
        ----------
        limit : typing.Optional[int]
            The maximum number of results to return in a single paged response. This limit is advisory.
            The response might contain more or fewer results. The minimum value is 1 and the maximum value is 100.
            The default value is 20. For more information, see [Pagination](https://developer.squareup.com/docs/build-basics/common-api-patterns/pagination).

        cursor : typing.Optional[str]
            The cursor returned in the paged response from the previous call to this endpoint.
            Provide this cursor to retrieve the next page of results for your original request.
            For more information, see [Pagination](https://developer.squareup.com/docs/build-basics/common-api-patterns/pagination).

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

        Returns
        -------
        AsyncPager[CustomAttributeDefinition, ListCustomerCustomAttributeDefinitionsResponse]
            Success
        """
        _response = await self._client_wrapper.httpx_client.request(
            "v2/customers/custom-attribute-definitions",
            method="GET",
            params={
                "limit": limit,
                "cursor": cursor,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _parsed_response = typing.cast(
                    ListCustomerCustomAttributeDefinitionsResponse,
                    construct_type(
                        type_=ListCustomerCustomAttributeDefinitionsResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                _items = _parsed_response.custom_attribute_definitions
                _parsed_next = _parsed_response.cursor
                _has_next = _parsed_next is not None and _parsed_next != ""

                async def _get_next():
                    return await self.list(
                        limit=limit,
                        cursor=_parsed_next,
                        request_options=request_options,
                    )

                return AsyncPager(has_next=_has_next, items=_items, get_next=_get_next, response=_parsed_response)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def create(
        self,
        *,
        custom_attribute_definition: CustomAttributeDefinitionParams,
        idempotency_key: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[CreateCustomerCustomAttributeDefinitionResponse]:
        """
        Creates a customer-related [custom attribute definition](entity:CustomAttributeDefinition) for a Square seller account.
        Use this endpoint to define a custom attribute that can be associated with customer profiles.

        A custom attribute definition specifies the `key`, `visibility`, `schema`, and other properties
        for a custom attribute. After the definition is created, you can call
        [UpsertCustomerCustomAttribute](api-endpoint:CustomerCustomAttributes-UpsertCustomerCustomAttribute) or
        [BulkUpsertCustomerCustomAttributes](api-endpoint:CustomerCustomAttributes-BulkUpsertCustomerCustomAttributes)
        to set the custom attribute for customer profiles in the seller's Customer Directory.

        Sellers can view all custom attributes in exported customer data, including those set to
        `VISIBILITY_HIDDEN`.

        Parameters
        ----------
        custom_attribute_definition : CustomAttributeDefinitionParams
            The custom attribute definition to create. Note the following:
            - With the exception of the `Selection` data type, the `schema` is specified as a simple URL to the JSON schema
            definition hosted on the Square CDN. For more information, including supported values and constraints, see
            [Specifying the schema](https://developer.squareup.com/docs/customer-custom-attributes-api/custom-attribute-definitions#specify-schema).
            - If provided, `name` must be unique (case-sensitive) across all visible customer-related custom attribute definitions for the seller.
            - All custom attributes are visible in exported customer data, including those set to `VISIBILITY_HIDDEN`.

        idempotency_key : typing.Optional[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).

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

        Returns
        -------
        AsyncHttpResponse[CreateCustomerCustomAttributeDefinitionResponse]
            Success
        """
        _response = await self._client_wrapper.httpx_client.request(
            "v2/customers/custom-attribute-definitions",
            method="POST",
            json={
                "custom_attribute_definition": convert_and_respect_annotation_metadata(
                    object_=custom_attribute_definition, annotation=CustomAttributeDefinitionParams, 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(
                    CreateCustomerCustomAttributeDefinitionResponse,
                    construct_type(
                        type_=CreateCustomerCustomAttributeDefinitionResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            _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, key: str, *, version: typing.Optional[int] = None, request_options: typing.Optional[RequestOptions] = None
    ) -> AsyncHttpResponse[GetCustomerCustomAttributeDefinitionResponse]:
        """
        Retrieves a customer-related [custom attribute definition](entity:CustomAttributeDefinition) from a Square seller account.

        To retrieve a custom attribute definition created by another application, the `visibility`
        setting must be `VISIBILITY_READ_ONLY` or `VISIBILITY_READ_WRITE_VALUES`. Note that seller-defined custom attributes
        (also known as custom fields) are always set to `VISIBILITY_READ_WRITE_VALUES`.

        Parameters
        ----------
        key : str
            The key of the custom attribute definition to retrieve. If the requesting application
            is not the definition owner, you must use the qualified key.

        version : typing.Optional[int]
            The current version of the custom attribute definition, which is used for strongly consistent
            reads to guarantee that you receive the most up-to-date data. When included in the request,
            Square returns the specified version or a higher version if one exists. If the specified version
            is higher than the current version, Square returns a `BAD_REQUEST` error.

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

        Returns
        -------
        AsyncHttpResponse[GetCustomerCustomAttributeDefinitionResponse]
            Success
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v2/customers/custom-attribute-definitions/{jsonable_encoder(key)}",
            method="GET",
            params={
                "version": version,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    GetCustomerCustomAttributeDefinitionResponse,
                    construct_type(
                        type_=GetCustomerCustomAttributeDefinitionResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def update(
        self,
        key: str,
        *,
        custom_attribute_definition: CustomAttributeDefinitionParams,
        idempotency_key: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[UpdateCustomerCustomAttributeDefinitionResponse]:
        """
        Updates a customer-related [custom attribute definition](entity:CustomAttributeDefinition) for a Square seller account.

        Use this endpoint to update the following fields: `name`, `description`, `visibility`, or the
        `schema` for a `Selection` data type.

        Only the definition owner can update a custom attribute definition. Note that sellers can view
        all custom attributes in exported customer data, including those set to `VISIBILITY_HIDDEN`.

        Parameters
        ----------
        key : str
            The key of the custom attribute definition to update.

        custom_attribute_definition : CustomAttributeDefinitionParams
            The custom attribute definition that contains the fields to update. This endpoint
            supports sparse updates, so only new or changed fields need to be included in the request.
            Only the following fields can be updated:

            - `name`
            - `description`
            - `visibility`
            - `schema` for a `Selection` data type. Only changes to the named options or the maximum number of allowed
            selections are supported.

            For more information, see
            [Updatable definition fields](https://developer.squareup.com/docs/customer-custom-attributes-api/custom-attribute-definitions#updatable-definition-fields).

            To enable [optimistic concurrency](https://developer.squareup.com/docs/build-basics/common-api-patterns/optimistic-concurrency)
            control, include the optional `version` field and specify the current version of the custom attribute definition.

        idempotency_key : typing.Optional[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).

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

        Returns
        -------
        AsyncHttpResponse[UpdateCustomerCustomAttributeDefinitionResponse]
            Success
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v2/customers/custom-attribute-definitions/{jsonable_encoder(key)}",
            method="PUT",
            json={
                "custom_attribute_definition": convert_and_respect_annotation_metadata(
                    object_=custom_attribute_definition, annotation=CustomAttributeDefinitionParams, 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(
                    UpdateCustomerCustomAttributeDefinitionResponse,
                    construct_type(
                        type_=UpdateCustomerCustomAttributeDefinitionResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            _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 delete(
        self, key: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> AsyncHttpResponse[DeleteCustomerCustomAttributeDefinitionResponse]:
        """
        Deletes a customer-related [custom attribute definition](entity:CustomAttributeDefinition) from a Square seller account.

        Deleting a custom attribute definition also deletes the corresponding custom attribute from
        all customer profiles in the seller's Customer Directory.

        Only the definition owner can delete a custom attribute definition.

        Parameters
        ----------
        key : str
            The key of the custom attribute definition to delete.

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

        Returns
        -------
        AsyncHttpResponse[DeleteCustomerCustomAttributeDefinitionResponse]
            Success
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v2/customers/custom-attribute-definitions/{jsonable_encoder(key)}",
            method="DELETE",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    DeleteCustomerCustomAttributeDefinitionResponse,
                    construct_type(
                        type_=DeleteCustomerCustomAttributeDefinitionResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            _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 batch_upsert(
        self,
        *,
        values: typing.Dict[str, BatchUpsertCustomerCustomAttributesRequestCustomerCustomAttributeUpsertRequestParams],
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[BatchUpsertCustomerCustomAttributesResponse]:
        """
        Creates or updates [custom attributes](entity:CustomAttribute) for customer profiles as a bulk operation.

        Use this endpoint to set the value of one or more custom attributes for one or more customer profiles.
        A custom attribute is based on a custom attribute definition in a Square seller account, which is
        created using the [CreateCustomerCustomAttributeDefinition](api-endpoint:CustomerCustomAttributes-CreateCustomerCustomAttributeDefinition) endpoint.

        This `BulkUpsertCustomerCustomAttributes` endpoint accepts a map of 1 to 25 individual upsert
        requests and returns a map of individual upsert responses. Each upsert request has a unique ID
        and provides a customer ID and custom attribute. Each upsert response is returned with the ID
        of the corresponding request.

        To create or update a custom attribute owned by another application, the `visibility` setting
        must be `VISIBILITY_READ_WRITE_VALUES`. Note that seller-defined custom attributes
        (also known as custom fields) are always set to `VISIBILITY_READ_WRITE_VALUES`.

        Parameters
        ----------
        values : typing.Dict[str, BatchUpsertCustomerCustomAttributesRequestCustomerCustomAttributeUpsertRequestParams]
            A map containing 1 to 25 individual upsert requests. For each request, provide an
            arbitrary ID that is unique for this `BulkUpsertCustomerCustomAttributes` request and the
            information needed to create or update a custom attribute.

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

        Returns
        -------
        AsyncHttpResponse[BatchUpsertCustomerCustomAttributesResponse]
            Success
        """
        _response = await self._client_wrapper.httpx_client.request(
            "v2/customers/custom-attributes/bulk-upsert",
            method="POST",
            json={
                "values": convert_and_respect_annotation_metadata(
                    object_=values,
                    annotation=typing.Dict[
                        str, BatchUpsertCustomerCustomAttributesRequestCustomerCustomAttributeUpsertRequestParams
                    ],
                    direction="write",
                ),
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    BatchUpsertCustomerCustomAttributesResponse,
                    construct_type(
                        type_=BatchUpsertCustomerCustomAttributesResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            _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)
