"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""

from .basesdk import BaseSDK
from moovio_sdk import utils
from moovio_sdk._hooks import HookContext
from moovio_sdk.models import components, errors, operations
from moovio_sdk.types import OptionalNullable, UNSET
from moovio_sdk.utils import get_security_from_env
from moovio_sdk.utils.unmarshal_json_response import unmarshal_json_response
from typing import Any, List, Mapping, Optional, Union


class Cards(BaseSDK):
    def link(
        self,
        *,
        account_id: str,
        card_number: str,
        card_cvv: str,
        expiration: Union[
            components.CardExpiration, components.CardExpirationTypedDict
        ],
        billing_address: Union[components.CardAddress, components.CardAddressTypedDict],
        x_wait_for: Optional[components.LinkCardWaitFor] = None,
        e2ee: Optional[
            Union[components.E2EEToken, components.E2EETokenTypedDict]
        ] = None,
        holder_name: Optional[str] = None,
        card_on_file: Optional[bool] = None,
        merchant_account_id: Optional[str] = None,
        verify_name: Optional[bool] = None,
        retries: OptionalNullable[utils.RetryConfig] = UNSET,
        server_url: Optional[str] = None,
        timeout_ms: Optional[int] = None,
        http_headers: Optional[Mapping[str, str]] = None,
    ) -> operations.LinkCardResponse:
        r"""Link a card to an existing Moov account.

        Read our [accept card payments guide](https://docs.moov.io/guides/sources/cards/accept-card-payments/#link-a-card) to learn more.

        Only use this endpoint if you have provided Moov with a copy of your PCI attestation of compliance.

        During card linking, the provided data will be verified by submitting a $0 authorization (account verification) request.
        If `merchantAccountID` is provided, the authorization request will contain that account's statement descriptor and address.
        Otherwise, the platform account's profile will be used. If no statement descriptor has been set, the authorization will
        use the account's name instead.

        It is strongly recommended that callers include the `X-Wait-For` header, set to `payment-method`, if the newly linked
        card is intended to be used right away. If this header is not included, the caller will need to poll the [List Payment
        Methods](https://docs.moov.io/api/sources/payment-methods/list/)
        endpoint to wait for the new payment methods to be available for use.

        To access this endpoint using an [access token](https://docs.moov.io/api/authentication/access-tokens/)
        you'll need to specify the `/accounts/{accountID}/cards.write` scope.

        :param account_id:
        :param card_number:
        :param card_cvv:
        :param expiration: The expiration date of the card or token.
        :param billing_address:
        :param x_wait_for: Optional header to wait for certain events, such as the creation of a payment method, to occur before returning a response.

            When this header is set to `payment-method`, the response will include any payment methods that were created for the newly
            linked card in the `paymentMethods` field. Otherwise, the `paymentMethods` field will be omitted from the response.
        :param e2ee: Wraps a compact-serialized JSON Web Encryption (JWE) token used for secure transmission of sensitive data (e.g., PCI information) through intermediaries.
            This token is encrypted using the public key from /end-to-end-keys and wraps an AES key. For details and examples, refer to our
            [GitHub repository](https://github.com/moovfinancial/moov-go/blob/main/examples/e2ee/e2ee_test.go).
        :param holder_name:
        :param card_on_file:
        :param merchant_account_id:
        :param verify_name:
        :param retries: Override the default retry configuration for this method
        :param server_url: Override the default server URL for this method
        :param timeout_ms: Override the default request timeout configuration for this method in milliseconds
        :param http_headers: Additional headers to set or replace on requests.
        """
        base_url = None
        url_variables = None
        if timeout_ms is None:
            timeout_ms = self.sdk_configuration.timeout_ms

        if server_url is not None:
            base_url = server_url
        else:
            base_url = self._get_url(base_url, url_variables)

        request = operations.LinkCardRequest(
            x_wait_for=x_wait_for,
            account_id=account_id,
            link_card=components.LinkCard(
                e2ee=utils.get_pydantic_model(e2ee, Optional[components.E2EEToken]),
                card_number=card_number,
                card_cvv=card_cvv,
                expiration=utils.get_pydantic_model(
                    expiration, components.CardExpiration
                ),
                holder_name=holder_name,
                billing_address=utils.get_pydantic_model(
                    billing_address, components.CardAddress
                ),
                card_on_file=card_on_file,
                merchant_account_id=merchant_account_id,
                verify_name=verify_name,
            ),
        )

        req = self._build_request(
            method="POST",
            path="/accounts/{accountID}/cards",
            base_url=base_url,
            url_variables=url_variables,
            request=request,
            request_body_required=True,
            request_has_path_params=True,
            request_has_query_params=True,
            user_agent_header="user-agent",
            accept_header_value="application/json",
            http_headers=http_headers,
            _globals=operations.LinkCardGlobals(
                x_moov_version=self.sdk_configuration.globals.x_moov_version,
            ),
            security=self.sdk_configuration.security,
            get_serialized_body=lambda: utils.serialize_request_body(
                request.link_card, False, False, "json", components.LinkCard
            ),
            allow_empty_value=None,
            timeout_ms=timeout_ms,
        )

        if retries == UNSET:
            if self.sdk_configuration.retry_config is not UNSET:
                retries = self.sdk_configuration.retry_config

        retry_config = None
        if isinstance(retries, utils.RetryConfig):
            retry_config = (retries, ["429", "500", "502", "503", "504"])

        http_res = self.do_request(
            hook_ctx=HookContext(
                config=self.sdk_configuration,
                base_url=base_url or "",
                operation_id="linkCard",
                oauth2_scopes=None,
                security_source=get_security_from_env(
                    self.sdk_configuration.security, components.Security
                ),
            ),
            request=req,
            error_status_codes=[
                "400",
                "401",
                "403",
                "404",
                "409",
                "422",
                "429",
                "4XX",
                "500",
                "504",
                "5XX",
            ],
            retry_config=retry_config,
        )

        response_data: Any = None
        if utils.match_response(http_res, "200", "application/json"):
            return operations.LinkCardResponse(
                result=unmarshal_json_response(components.Card, http_res),
                headers=utils.get_response_headers(http_res.headers),
            )
        if utils.match_response(http_res, "400", "application/json"):
            response_data = unmarshal_json_response(errors.GenericErrorData, http_res)
            raise errors.GenericError(response_data, http_res)
        if utils.match_response(http_res, "409", "application/json"):
            response_data = unmarshal_json_response(
                errors.DuplicateCardErrorData, http_res
            )
            raise errors.DuplicateCardError(response_data, http_res)
        if utils.match_response(http_res, "422", "application/json"):
            response_data = unmarshal_json_response(errors.LinkCardErrorData, http_res)
            raise errors.LinkCardError(response_data, http_res)
        if utils.match_response(http_res, ["401", "403", "404", "429"], "*"):
            http_res_text = utils.stream_to_text(http_res)
            raise errors.APIError("API error occurred", http_res, http_res_text)
        if utils.match_response(http_res, ["500", "504"], "*"):
            http_res_text = utils.stream_to_text(http_res)
            raise errors.APIError("API error occurred", http_res, http_res_text)
        if utils.match_response(http_res, "4XX", "*"):
            http_res_text = utils.stream_to_text(http_res)
            raise errors.APIError("API error occurred", http_res, http_res_text)
        if utils.match_response(http_res, "5XX", "*"):
            http_res_text = utils.stream_to_text(http_res)
            raise errors.APIError("API error occurred", http_res, http_res_text)

        raise errors.APIError("Unexpected response received", http_res)

    async def link_async(
        self,
        *,
        account_id: str,
        card_number: str,
        card_cvv: str,
        expiration: Union[
            components.CardExpiration, components.CardExpirationTypedDict
        ],
        billing_address: Union[components.CardAddress, components.CardAddressTypedDict],
        x_wait_for: Optional[components.LinkCardWaitFor] = None,
        e2ee: Optional[
            Union[components.E2EEToken, components.E2EETokenTypedDict]
        ] = None,
        holder_name: Optional[str] = None,
        card_on_file: Optional[bool] = None,
        merchant_account_id: Optional[str] = None,
        verify_name: Optional[bool] = None,
        retries: OptionalNullable[utils.RetryConfig] = UNSET,
        server_url: Optional[str] = None,
        timeout_ms: Optional[int] = None,
        http_headers: Optional[Mapping[str, str]] = None,
    ) -> operations.LinkCardResponse:
        r"""Link a card to an existing Moov account.

        Read our [accept card payments guide](https://docs.moov.io/guides/sources/cards/accept-card-payments/#link-a-card) to learn more.

        Only use this endpoint if you have provided Moov with a copy of your PCI attestation of compliance.

        During card linking, the provided data will be verified by submitting a $0 authorization (account verification) request.
        If `merchantAccountID` is provided, the authorization request will contain that account's statement descriptor and address.
        Otherwise, the platform account's profile will be used. If no statement descriptor has been set, the authorization will
        use the account's name instead.

        It is strongly recommended that callers include the `X-Wait-For` header, set to `payment-method`, if the newly linked
        card is intended to be used right away. If this header is not included, the caller will need to poll the [List Payment
        Methods](https://docs.moov.io/api/sources/payment-methods/list/)
        endpoint to wait for the new payment methods to be available for use.

        To access this endpoint using an [access token](https://docs.moov.io/api/authentication/access-tokens/)
        you'll need to specify the `/accounts/{accountID}/cards.write` scope.

        :param account_id:
        :param card_number:
        :param card_cvv:
        :param expiration: The expiration date of the card or token.
        :param billing_address:
        :param x_wait_for: Optional header to wait for certain events, such as the creation of a payment method, to occur before returning a response.

            When this header is set to `payment-method`, the response will include any payment methods that were created for the newly
            linked card in the `paymentMethods` field. Otherwise, the `paymentMethods` field will be omitted from the response.
        :param e2ee: Wraps a compact-serialized JSON Web Encryption (JWE) token used for secure transmission of sensitive data (e.g., PCI information) through intermediaries.
            This token is encrypted using the public key from /end-to-end-keys and wraps an AES key. For details and examples, refer to our
            [GitHub repository](https://github.com/moovfinancial/moov-go/blob/main/examples/e2ee/e2ee_test.go).
        :param holder_name:
        :param card_on_file:
        :param merchant_account_id:
        :param verify_name:
        :param retries: Override the default retry configuration for this method
        :param server_url: Override the default server URL for this method
        :param timeout_ms: Override the default request timeout configuration for this method in milliseconds
        :param http_headers: Additional headers to set or replace on requests.
        """
        base_url = None
        url_variables = None
        if timeout_ms is None:
            timeout_ms = self.sdk_configuration.timeout_ms

        if server_url is not None:
            base_url = server_url
        else:
            base_url = self._get_url(base_url, url_variables)

        request = operations.LinkCardRequest(
            x_wait_for=x_wait_for,
            account_id=account_id,
            link_card=components.LinkCard(
                e2ee=utils.get_pydantic_model(e2ee, Optional[components.E2EEToken]),
                card_number=card_number,
                card_cvv=card_cvv,
                expiration=utils.get_pydantic_model(
                    expiration, components.CardExpiration
                ),
                holder_name=holder_name,
                billing_address=utils.get_pydantic_model(
                    billing_address, components.CardAddress
                ),
                card_on_file=card_on_file,
                merchant_account_id=merchant_account_id,
                verify_name=verify_name,
            ),
        )

        req = self._build_request_async(
            method="POST",
            path="/accounts/{accountID}/cards",
            base_url=base_url,
            url_variables=url_variables,
            request=request,
            request_body_required=True,
            request_has_path_params=True,
            request_has_query_params=True,
            user_agent_header="user-agent",
            accept_header_value="application/json",
            http_headers=http_headers,
            _globals=operations.LinkCardGlobals(
                x_moov_version=self.sdk_configuration.globals.x_moov_version,
            ),
            security=self.sdk_configuration.security,
            get_serialized_body=lambda: utils.serialize_request_body(
                request.link_card, False, False, "json", components.LinkCard
            ),
            allow_empty_value=None,
            timeout_ms=timeout_ms,
        )

        if retries == UNSET:
            if self.sdk_configuration.retry_config is not UNSET:
                retries = self.sdk_configuration.retry_config

        retry_config = None
        if isinstance(retries, utils.RetryConfig):
            retry_config = (retries, ["429", "500", "502", "503", "504"])

        http_res = await self.do_request_async(
            hook_ctx=HookContext(
                config=self.sdk_configuration,
                base_url=base_url or "",
                operation_id="linkCard",
                oauth2_scopes=None,
                security_source=get_security_from_env(
                    self.sdk_configuration.security, components.Security
                ),
            ),
            request=req,
            error_status_codes=[
                "400",
                "401",
                "403",
                "404",
                "409",
                "422",
                "429",
                "4XX",
                "500",
                "504",
                "5XX",
            ],
            retry_config=retry_config,
        )

        response_data: Any = None
        if utils.match_response(http_res, "200", "application/json"):
            return operations.LinkCardResponse(
                result=unmarshal_json_response(components.Card, http_res),
                headers=utils.get_response_headers(http_res.headers),
            )
        if utils.match_response(http_res, "400", "application/json"):
            response_data = unmarshal_json_response(errors.GenericErrorData, http_res)
            raise errors.GenericError(response_data, http_res)
        if utils.match_response(http_res, "409", "application/json"):
            response_data = unmarshal_json_response(
                errors.DuplicateCardErrorData, http_res
            )
            raise errors.DuplicateCardError(response_data, http_res)
        if utils.match_response(http_res, "422", "application/json"):
            response_data = unmarshal_json_response(errors.LinkCardErrorData, http_res)
            raise errors.LinkCardError(response_data, http_res)
        if utils.match_response(http_res, ["401", "403", "404", "429"], "*"):
            http_res_text = await utils.stream_to_text_async(http_res)
            raise errors.APIError("API error occurred", http_res, http_res_text)
        if utils.match_response(http_res, ["500", "504"], "*"):
            http_res_text = await utils.stream_to_text_async(http_res)
            raise errors.APIError("API error occurred", http_res, http_res_text)
        if utils.match_response(http_res, "4XX", "*"):
            http_res_text = await utils.stream_to_text_async(http_res)
            raise errors.APIError("API error occurred", http_res, http_res_text)
        if utils.match_response(http_res, "5XX", "*"):
            http_res_text = await utils.stream_to_text_async(http_res)
            raise errors.APIError("API error occurred", http_res, http_res_text)

        raise errors.APIError("Unexpected response received", http_res)

    def list(
        self,
        *,
        account_id: str,
        retries: OptionalNullable[utils.RetryConfig] = UNSET,
        server_url: Optional[str] = None,
        timeout_ms: Optional[int] = None,
        http_headers: Optional[Mapping[str, str]] = None,
    ) -> operations.ListCardsResponse:
        r"""List all the active cards associated with a Moov account.

        Read our [accept card payments guide](https://docs.moov.io/guides/sources/cards/accept-card-payments/) to learn more.

        To access this endpoint using an [access token](https://docs.moov.io/api/authentication/access-tokens/)
        you'll need to specify the `/accounts/{accountID}/cards.read` scope.

        :param account_id:
        :param retries: Override the default retry configuration for this method
        :param server_url: Override the default server URL for this method
        :param timeout_ms: Override the default request timeout configuration for this method in milliseconds
        :param http_headers: Additional headers to set or replace on requests.
        """
        base_url = None
        url_variables = None
        if timeout_ms is None:
            timeout_ms = self.sdk_configuration.timeout_ms

        if server_url is not None:
            base_url = server_url
        else:
            base_url = self._get_url(base_url, url_variables)

        request = operations.ListCardsRequest(
            account_id=account_id,
        )

        req = self._build_request(
            method="GET",
            path="/accounts/{accountID}/cards",
            base_url=base_url,
            url_variables=url_variables,
            request=request,
            request_body_required=False,
            request_has_path_params=True,
            request_has_query_params=True,
            user_agent_header="user-agent",
            accept_header_value="application/json",
            http_headers=http_headers,
            _globals=operations.ListCardsGlobals(
                x_moov_version=self.sdk_configuration.globals.x_moov_version,
            ),
            security=self.sdk_configuration.security,
            allow_empty_value=None,
            timeout_ms=timeout_ms,
        )

        if retries == UNSET:
            if self.sdk_configuration.retry_config is not UNSET:
                retries = self.sdk_configuration.retry_config

        retry_config = None
        if isinstance(retries, utils.RetryConfig):
            retry_config = (retries, ["429", "500", "502", "503", "504"])

        http_res = self.do_request(
            hook_ctx=HookContext(
                config=self.sdk_configuration,
                base_url=base_url or "",
                operation_id="listCards",
                oauth2_scopes=None,
                security_source=get_security_from_env(
                    self.sdk_configuration.security, components.Security
                ),
            ),
            request=req,
            error_status_codes=["401", "403", "429", "4XX", "500", "504", "5XX"],
            retry_config=retry_config,
        )

        if utils.match_response(http_res, "200", "application/json"):
            return operations.ListCardsResponse(
                result=unmarshal_json_response(List[components.Card], http_res),
                headers=utils.get_response_headers(http_res.headers),
            )
        if utils.match_response(http_res, ["401", "403", "429"], "*"):
            http_res_text = utils.stream_to_text(http_res)
            raise errors.APIError("API error occurred", http_res, http_res_text)
        if utils.match_response(http_res, ["500", "504"], "*"):
            http_res_text = utils.stream_to_text(http_res)
            raise errors.APIError("API error occurred", http_res, http_res_text)
        if utils.match_response(http_res, "4XX", "*"):
            http_res_text = utils.stream_to_text(http_res)
            raise errors.APIError("API error occurred", http_res, http_res_text)
        if utils.match_response(http_res, "5XX", "*"):
            http_res_text = utils.stream_to_text(http_res)
            raise errors.APIError("API error occurred", http_res, http_res_text)

        raise errors.APIError("Unexpected response received", http_res)

    async def list_async(
        self,
        *,
        account_id: str,
        retries: OptionalNullable[utils.RetryConfig] = UNSET,
        server_url: Optional[str] = None,
        timeout_ms: Optional[int] = None,
        http_headers: Optional[Mapping[str, str]] = None,
    ) -> operations.ListCardsResponse:
        r"""List all the active cards associated with a Moov account.

        Read our [accept card payments guide](https://docs.moov.io/guides/sources/cards/accept-card-payments/) to learn more.

        To access this endpoint using an [access token](https://docs.moov.io/api/authentication/access-tokens/)
        you'll need to specify the `/accounts/{accountID}/cards.read` scope.

        :param account_id:
        :param retries: Override the default retry configuration for this method
        :param server_url: Override the default server URL for this method
        :param timeout_ms: Override the default request timeout configuration for this method in milliseconds
        :param http_headers: Additional headers to set or replace on requests.
        """
        base_url = None
        url_variables = None
        if timeout_ms is None:
            timeout_ms = self.sdk_configuration.timeout_ms

        if server_url is not None:
            base_url = server_url
        else:
            base_url = self._get_url(base_url, url_variables)

        request = operations.ListCardsRequest(
            account_id=account_id,
        )

        req = self._build_request_async(
            method="GET",
            path="/accounts/{accountID}/cards",
            base_url=base_url,
            url_variables=url_variables,
            request=request,
            request_body_required=False,
            request_has_path_params=True,
            request_has_query_params=True,
            user_agent_header="user-agent",
            accept_header_value="application/json",
            http_headers=http_headers,
            _globals=operations.ListCardsGlobals(
                x_moov_version=self.sdk_configuration.globals.x_moov_version,
            ),
            security=self.sdk_configuration.security,
            allow_empty_value=None,
            timeout_ms=timeout_ms,
        )

        if retries == UNSET:
            if self.sdk_configuration.retry_config is not UNSET:
                retries = self.sdk_configuration.retry_config

        retry_config = None
        if isinstance(retries, utils.RetryConfig):
            retry_config = (retries, ["429", "500", "502", "503", "504"])

        http_res = await self.do_request_async(
            hook_ctx=HookContext(
                config=self.sdk_configuration,
                base_url=base_url or "",
                operation_id="listCards",
                oauth2_scopes=None,
                security_source=get_security_from_env(
                    self.sdk_configuration.security, components.Security
                ),
            ),
            request=req,
            error_status_codes=["401", "403", "429", "4XX", "500", "504", "5XX"],
            retry_config=retry_config,
        )

        if utils.match_response(http_res, "200", "application/json"):
            return operations.ListCardsResponse(
                result=unmarshal_json_response(List[components.Card], http_res),
                headers=utils.get_response_headers(http_res.headers),
            )
        if utils.match_response(http_res, ["401", "403", "429"], "*"):
            http_res_text = await utils.stream_to_text_async(http_res)
            raise errors.APIError("API error occurred", http_res, http_res_text)
        if utils.match_response(http_res, ["500", "504"], "*"):
            http_res_text = await utils.stream_to_text_async(http_res)
            raise errors.APIError("API error occurred", http_res, http_res_text)
        if utils.match_response(http_res, "4XX", "*"):
            http_res_text = await utils.stream_to_text_async(http_res)
            raise errors.APIError("API error occurred", http_res, http_res_text)
        if utils.match_response(http_res, "5XX", "*"):
            http_res_text = await utils.stream_to_text_async(http_res)
            raise errors.APIError("API error occurred", http_res, http_res_text)

        raise errors.APIError("Unexpected response received", http_res)

    def get(
        self,
        *,
        account_id: str,
        card_id: str,
        retries: OptionalNullable[utils.RetryConfig] = UNSET,
        server_url: Optional[str] = None,
        timeout_ms: Optional[int] = None,
        http_headers: Optional[Mapping[str, str]] = None,
    ) -> operations.GetCardResponse:
        r"""Fetch a specific card associated with a Moov account.

        Read our [accept card payments guide](https://docs.moov.io/guides/sources/cards/accept-card-payments/) to learn more.

        To access this endpoint using an [access token](https://docs.moov.io/api/authentication/access-tokens/)
        you'll need to specify the `/accounts/{accountID}/cards.read` scope.

        :param account_id:
        :param card_id:
        :param retries: Override the default retry configuration for this method
        :param server_url: Override the default server URL for this method
        :param timeout_ms: Override the default request timeout configuration for this method in milliseconds
        :param http_headers: Additional headers to set or replace on requests.
        """
        base_url = None
        url_variables = None
        if timeout_ms is None:
            timeout_ms = self.sdk_configuration.timeout_ms

        if server_url is not None:
            base_url = server_url
        else:
            base_url = self._get_url(base_url, url_variables)

        request = operations.GetCardRequest(
            account_id=account_id,
            card_id=card_id,
        )

        req = self._build_request(
            method="GET",
            path="/accounts/{accountID}/cards/{cardID}",
            base_url=base_url,
            url_variables=url_variables,
            request=request,
            request_body_required=False,
            request_has_path_params=True,
            request_has_query_params=True,
            user_agent_header="user-agent",
            accept_header_value="application/json",
            http_headers=http_headers,
            _globals=operations.GetCardGlobals(
                x_moov_version=self.sdk_configuration.globals.x_moov_version,
            ),
            security=self.sdk_configuration.security,
            allow_empty_value=None,
            timeout_ms=timeout_ms,
        )

        if retries == UNSET:
            if self.sdk_configuration.retry_config is not UNSET:
                retries = self.sdk_configuration.retry_config

        retry_config = None
        if isinstance(retries, utils.RetryConfig):
            retry_config = (retries, ["429", "500", "502", "503", "504"])

        http_res = self.do_request(
            hook_ctx=HookContext(
                config=self.sdk_configuration,
                base_url=base_url or "",
                operation_id="getCard",
                oauth2_scopes=None,
                security_source=get_security_from_env(
                    self.sdk_configuration.security, components.Security
                ),
            ),
            request=req,
            error_status_codes=["401", "403", "404", "429", "4XX", "500", "504", "5XX"],
            retry_config=retry_config,
        )

        if utils.match_response(http_res, "200", "application/json"):
            return operations.GetCardResponse(
                result=unmarshal_json_response(components.Card, http_res),
                headers=utils.get_response_headers(http_res.headers),
            )
        if utils.match_response(http_res, ["401", "403", "404", "429"], "*"):
            http_res_text = utils.stream_to_text(http_res)
            raise errors.APIError("API error occurred", http_res, http_res_text)
        if utils.match_response(http_res, ["500", "504"], "*"):
            http_res_text = utils.stream_to_text(http_res)
            raise errors.APIError("API error occurred", http_res, http_res_text)
        if utils.match_response(http_res, "4XX", "*"):
            http_res_text = utils.stream_to_text(http_res)
            raise errors.APIError("API error occurred", http_res, http_res_text)
        if utils.match_response(http_res, "5XX", "*"):
            http_res_text = utils.stream_to_text(http_res)
            raise errors.APIError("API error occurred", http_res, http_res_text)

        raise errors.APIError("Unexpected response received", http_res)

    async def get_async(
        self,
        *,
        account_id: str,
        card_id: str,
        retries: OptionalNullable[utils.RetryConfig] = UNSET,
        server_url: Optional[str] = None,
        timeout_ms: Optional[int] = None,
        http_headers: Optional[Mapping[str, str]] = None,
    ) -> operations.GetCardResponse:
        r"""Fetch a specific card associated with a Moov account.

        Read our [accept card payments guide](https://docs.moov.io/guides/sources/cards/accept-card-payments/) to learn more.

        To access this endpoint using an [access token](https://docs.moov.io/api/authentication/access-tokens/)
        you'll need to specify the `/accounts/{accountID}/cards.read` scope.

        :param account_id:
        :param card_id:
        :param retries: Override the default retry configuration for this method
        :param server_url: Override the default server URL for this method
        :param timeout_ms: Override the default request timeout configuration for this method in milliseconds
        :param http_headers: Additional headers to set or replace on requests.
        """
        base_url = None
        url_variables = None
        if timeout_ms is None:
            timeout_ms = self.sdk_configuration.timeout_ms

        if server_url is not None:
            base_url = server_url
        else:
            base_url = self._get_url(base_url, url_variables)

        request = operations.GetCardRequest(
            account_id=account_id,
            card_id=card_id,
        )

        req = self._build_request_async(
            method="GET",
            path="/accounts/{accountID}/cards/{cardID}",
            base_url=base_url,
            url_variables=url_variables,
            request=request,
            request_body_required=False,
            request_has_path_params=True,
            request_has_query_params=True,
            user_agent_header="user-agent",
            accept_header_value="application/json",
            http_headers=http_headers,
            _globals=operations.GetCardGlobals(
                x_moov_version=self.sdk_configuration.globals.x_moov_version,
            ),
            security=self.sdk_configuration.security,
            allow_empty_value=None,
            timeout_ms=timeout_ms,
        )

        if retries == UNSET:
            if self.sdk_configuration.retry_config is not UNSET:
                retries = self.sdk_configuration.retry_config

        retry_config = None
        if isinstance(retries, utils.RetryConfig):
            retry_config = (retries, ["429", "500", "502", "503", "504"])

        http_res = await self.do_request_async(
            hook_ctx=HookContext(
                config=self.sdk_configuration,
                base_url=base_url or "",
                operation_id="getCard",
                oauth2_scopes=None,
                security_source=get_security_from_env(
                    self.sdk_configuration.security, components.Security
                ),
            ),
            request=req,
            error_status_codes=["401", "403", "404", "429", "4XX", "500", "504", "5XX"],
            retry_config=retry_config,
        )

        if utils.match_response(http_res, "200", "application/json"):
            return operations.GetCardResponse(
                result=unmarshal_json_response(components.Card, http_res),
                headers=utils.get_response_headers(http_res.headers),
            )
        if utils.match_response(http_res, ["401", "403", "404", "429"], "*"):
            http_res_text = await utils.stream_to_text_async(http_res)
            raise errors.APIError("API error occurred", http_res, http_res_text)
        if utils.match_response(http_res, ["500", "504"], "*"):
            http_res_text = await utils.stream_to_text_async(http_res)
            raise errors.APIError("API error occurred", http_res, http_res_text)
        if utils.match_response(http_res, "4XX", "*"):
            http_res_text = await utils.stream_to_text_async(http_res)
            raise errors.APIError("API error occurred", http_res, http_res_text)
        if utils.match_response(http_res, "5XX", "*"):
            http_res_text = await utils.stream_to_text_async(http_res)
            raise errors.APIError("API error occurred", http_res, http_res_text)

        raise errors.APIError("Unexpected response received", http_res)

    def update(
        self,
        *,
        account_id: str,
        card_id: str,
        e2ee: Optional[
            Union[components.E2EETokenUpdate, components.E2EETokenUpdateTypedDict]
        ] = None,
        billing_address: Optional[
            Union[components.UpdateCardAddress, components.UpdateCardAddressTypedDict]
        ] = None,
        expiration: Optional[
            Union[
                components.UpdateCardExpiration,
                components.UpdateCardExpirationTypedDict,
            ]
        ] = None,
        card_cvv: Optional[str] = None,
        card_on_file: Optional[bool] = None,
        merchant_account_id: Optional[str] = None,
        verify_name: Optional[bool] = None,
        holder_name: Optional[str] = None,
        retries: OptionalNullable[utils.RetryConfig] = UNSET,
        server_url: Optional[str] = None,
        timeout_ms: Optional[int] = None,
        http_headers: Optional[Mapping[str, str]] = None,
    ) -> operations.UpdateCardResponse:
        r"""Update a linked card and/or resubmit it for verification.

        If a value is provided for CVV, a new verification ($0 authorization) will be submitted for the card. Updating the expiration
        date or
        address will update the information stored on file for the card but will not be verified.

        Read our [accept card payments guide](https://docs.moov.io/guides/sources/cards/accept-card-payments/#reverify-a-card) to learn
        more.

        Only use this endpoint if you have provided Moov with a copy of your PCI attestation of compliance.

        To access this endpoint using an [access token](https://docs.moov.io/api/authentication/access-tokens/)
        you'll need to specify the `/accounts/{accountID}/cards.write` scope.

        :param account_id:
        :param card_id:
        :param e2ee: Wraps a compact-serialized JSON Web Encryption (JWE) token used for secure transmission of sensitive data (e.g., PCI information) through intermediaries.
            This token is encrypted using the public key from /end-to-end-keys and wraps an AES key. For details and examples, refer to our
            [GitHub repository](https://github.com/moovfinancial/moov-go/blob/main/examples/e2ee/e2ee_test.go).
        :param billing_address:
        :param expiration:
        :param card_cvv:
        :param card_on_file:
        :param merchant_account_id:
        :param verify_name:
        :param holder_name:
        :param retries: Override the default retry configuration for this method
        :param server_url: Override the default server URL for this method
        :param timeout_ms: Override the default request timeout configuration for this method in milliseconds
        :param http_headers: Additional headers to set or replace on requests.
        """
        base_url = None
        url_variables = None
        if timeout_ms is None:
            timeout_ms = self.sdk_configuration.timeout_ms

        if server_url is not None:
            base_url = server_url
        else:
            base_url = self._get_url(base_url, url_variables)

        request = operations.UpdateCardRequest(
            account_id=account_id,
            card_id=card_id,
            update_card=components.UpdateCard(
                e2ee=utils.get_pydantic_model(
                    e2ee, Optional[components.E2EETokenUpdate]
                ),
                billing_address=utils.get_pydantic_model(
                    billing_address, Optional[components.UpdateCardAddress]
                ),
                expiration=utils.get_pydantic_model(
                    expiration, Optional[components.UpdateCardExpiration]
                ),
                card_cvv=card_cvv,
                card_on_file=card_on_file,
                merchant_account_id=merchant_account_id,
                verify_name=verify_name,
                holder_name=holder_name,
            ),
        )

        req = self._build_request(
            method="PATCH",
            path="/accounts/{accountID}/cards/{cardID}",
            base_url=base_url,
            url_variables=url_variables,
            request=request,
            request_body_required=True,
            request_has_path_params=True,
            request_has_query_params=True,
            user_agent_header="user-agent",
            accept_header_value="application/json",
            http_headers=http_headers,
            _globals=operations.UpdateCardGlobals(
                x_moov_version=self.sdk_configuration.globals.x_moov_version,
            ),
            security=self.sdk_configuration.security,
            get_serialized_body=lambda: utils.serialize_request_body(
                request.update_card, False, False, "json", components.UpdateCard
            ),
            allow_empty_value=None,
            timeout_ms=timeout_ms,
        )

        if retries == UNSET:
            if self.sdk_configuration.retry_config is not UNSET:
                retries = self.sdk_configuration.retry_config

        retry_config = None
        if isinstance(retries, utils.RetryConfig):
            retry_config = (retries, ["429", "500", "502", "503", "504"])

        http_res = self.do_request(
            hook_ctx=HookContext(
                config=self.sdk_configuration,
                base_url=base_url or "",
                operation_id="updateCard",
                oauth2_scopes=None,
                security_source=get_security_from_env(
                    self.sdk_configuration.security, components.Security
                ),
            ),
            request=req,
            error_status_codes=[
                "400",
                "401",
                "403",
                "404",
                "409",
                "422",
                "429",
                "4XX",
                "500",
                "504",
                "5XX",
            ],
            retry_config=retry_config,
        )

        response_data: Any = None
        if utils.match_response(http_res, "200", "application/json"):
            return operations.UpdateCardResponse(
                result=unmarshal_json_response(components.Card, http_res),
                headers=utils.get_response_headers(http_res.headers),
            )
        if utils.match_response(http_res, ["400", "409"], "application/json"):
            response_data = unmarshal_json_response(errors.GenericErrorData, http_res)
            raise errors.GenericError(response_data, http_res)
        if utils.match_response(http_res, "422", "application/json"):
            response_data = unmarshal_json_response(
                errors.UpdateCardErrorData, http_res
            )
            raise errors.UpdateCardError(response_data, http_res)
        if utils.match_response(http_res, ["401", "403", "404", "429"], "*"):
            http_res_text = utils.stream_to_text(http_res)
            raise errors.APIError("API error occurred", http_res, http_res_text)
        if utils.match_response(http_res, ["500", "504"], "*"):
            http_res_text = utils.stream_to_text(http_res)
            raise errors.APIError("API error occurred", http_res, http_res_text)
        if utils.match_response(http_res, "4XX", "*"):
            http_res_text = utils.stream_to_text(http_res)
            raise errors.APIError("API error occurred", http_res, http_res_text)
        if utils.match_response(http_res, "5XX", "*"):
            http_res_text = utils.stream_to_text(http_res)
            raise errors.APIError("API error occurred", http_res, http_res_text)

        raise errors.APIError("Unexpected response received", http_res)

    async def update_async(
        self,
        *,
        account_id: str,
        card_id: str,
        e2ee: Optional[
            Union[components.E2EETokenUpdate, components.E2EETokenUpdateTypedDict]
        ] = None,
        billing_address: Optional[
            Union[components.UpdateCardAddress, components.UpdateCardAddressTypedDict]
        ] = None,
        expiration: Optional[
            Union[
                components.UpdateCardExpiration,
                components.UpdateCardExpirationTypedDict,
            ]
        ] = None,
        card_cvv: Optional[str] = None,
        card_on_file: Optional[bool] = None,
        merchant_account_id: Optional[str] = None,
        verify_name: Optional[bool] = None,
        holder_name: Optional[str] = None,
        retries: OptionalNullable[utils.RetryConfig] = UNSET,
        server_url: Optional[str] = None,
        timeout_ms: Optional[int] = None,
        http_headers: Optional[Mapping[str, str]] = None,
    ) -> operations.UpdateCardResponse:
        r"""Update a linked card and/or resubmit it for verification.

        If a value is provided for CVV, a new verification ($0 authorization) will be submitted for the card. Updating the expiration
        date or
        address will update the information stored on file for the card but will not be verified.

        Read our [accept card payments guide](https://docs.moov.io/guides/sources/cards/accept-card-payments/#reverify-a-card) to learn
        more.

        Only use this endpoint if you have provided Moov with a copy of your PCI attestation of compliance.

        To access this endpoint using an [access token](https://docs.moov.io/api/authentication/access-tokens/)
        you'll need to specify the `/accounts/{accountID}/cards.write` scope.

        :param account_id:
        :param card_id:
        :param e2ee: Wraps a compact-serialized JSON Web Encryption (JWE) token used for secure transmission of sensitive data (e.g., PCI information) through intermediaries.
            This token is encrypted using the public key from /end-to-end-keys and wraps an AES key. For details and examples, refer to our
            [GitHub repository](https://github.com/moovfinancial/moov-go/blob/main/examples/e2ee/e2ee_test.go).
        :param billing_address:
        :param expiration:
        :param card_cvv:
        :param card_on_file:
        :param merchant_account_id:
        :param verify_name:
        :param holder_name:
        :param retries: Override the default retry configuration for this method
        :param server_url: Override the default server URL for this method
        :param timeout_ms: Override the default request timeout configuration for this method in milliseconds
        :param http_headers: Additional headers to set or replace on requests.
        """
        base_url = None
        url_variables = None
        if timeout_ms is None:
            timeout_ms = self.sdk_configuration.timeout_ms

        if server_url is not None:
            base_url = server_url
        else:
            base_url = self._get_url(base_url, url_variables)

        request = operations.UpdateCardRequest(
            account_id=account_id,
            card_id=card_id,
            update_card=components.UpdateCard(
                e2ee=utils.get_pydantic_model(
                    e2ee, Optional[components.E2EETokenUpdate]
                ),
                billing_address=utils.get_pydantic_model(
                    billing_address, Optional[components.UpdateCardAddress]
                ),
                expiration=utils.get_pydantic_model(
                    expiration, Optional[components.UpdateCardExpiration]
                ),
                card_cvv=card_cvv,
                card_on_file=card_on_file,
                merchant_account_id=merchant_account_id,
                verify_name=verify_name,
                holder_name=holder_name,
            ),
        )

        req = self._build_request_async(
            method="PATCH",
            path="/accounts/{accountID}/cards/{cardID}",
            base_url=base_url,
            url_variables=url_variables,
            request=request,
            request_body_required=True,
            request_has_path_params=True,
            request_has_query_params=True,
            user_agent_header="user-agent",
            accept_header_value="application/json",
            http_headers=http_headers,
            _globals=operations.UpdateCardGlobals(
                x_moov_version=self.sdk_configuration.globals.x_moov_version,
            ),
            security=self.sdk_configuration.security,
            get_serialized_body=lambda: utils.serialize_request_body(
                request.update_card, False, False, "json", components.UpdateCard
            ),
            allow_empty_value=None,
            timeout_ms=timeout_ms,
        )

        if retries == UNSET:
            if self.sdk_configuration.retry_config is not UNSET:
                retries = self.sdk_configuration.retry_config

        retry_config = None
        if isinstance(retries, utils.RetryConfig):
            retry_config = (retries, ["429", "500", "502", "503", "504"])

        http_res = await self.do_request_async(
            hook_ctx=HookContext(
                config=self.sdk_configuration,
                base_url=base_url or "",
                operation_id="updateCard",
                oauth2_scopes=None,
                security_source=get_security_from_env(
                    self.sdk_configuration.security, components.Security
                ),
            ),
            request=req,
            error_status_codes=[
                "400",
                "401",
                "403",
                "404",
                "409",
                "422",
                "429",
                "4XX",
                "500",
                "504",
                "5XX",
            ],
            retry_config=retry_config,
        )

        response_data: Any = None
        if utils.match_response(http_res, "200", "application/json"):
            return operations.UpdateCardResponse(
                result=unmarshal_json_response(components.Card, http_res),
                headers=utils.get_response_headers(http_res.headers),
            )
        if utils.match_response(http_res, ["400", "409"], "application/json"):
            response_data = unmarshal_json_response(errors.GenericErrorData, http_res)
            raise errors.GenericError(response_data, http_res)
        if utils.match_response(http_res, "422", "application/json"):
            response_data = unmarshal_json_response(
                errors.UpdateCardErrorData, http_res
            )
            raise errors.UpdateCardError(response_data, http_res)
        if utils.match_response(http_res, ["401", "403", "404", "429"], "*"):
            http_res_text = await utils.stream_to_text_async(http_res)
            raise errors.APIError("API error occurred", http_res, http_res_text)
        if utils.match_response(http_res, ["500", "504"], "*"):
            http_res_text = await utils.stream_to_text_async(http_res)
            raise errors.APIError("API error occurred", http_res, http_res_text)
        if utils.match_response(http_res, "4XX", "*"):
            http_res_text = await utils.stream_to_text_async(http_res)
            raise errors.APIError("API error occurred", http_res, http_res_text)
        if utils.match_response(http_res, "5XX", "*"):
            http_res_text = await utils.stream_to_text_async(http_res)
            raise errors.APIError("API error occurred", http_res, http_res_text)

        raise errors.APIError("Unexpected response received", http_res)

    def disable(
        self,
        *,
        account_id: str,
        card_id: str,
        retries: OptionalNullable[utils.RetryConfig] = UNSET,
        server_url: Optional[str] = None,
        timeout_ms: Optional[int] = None,
        http_headers: Optional[Mapping[str, str]] = None,
    ) -> operations.DisableCardResponse:
        r"""Disables a card associated with a Moov account.

        To access this endpoint using an [access token](https://docs.moov.io/api/authentication/access-tokens/)
        you'll need to specify the `/accounts/{accountID}/cards.write` scope.

        :param account_id:
        :param card_id:
        :param retries: Override the default retry configuration for this method
        :param server_url: Override the default server URL for this method
        :param timeout_ms: Override the default request timeout configuration for this method in milliseconds
        :param http_headers: Additional headers to set or replace on requests.
        """
        base_url = None
        url_variables = None
        if timeout_ms is None:
            timeout_ms = self.sdk_configuration.timeout_ms

        if server_url is not None:
            base_url = server_url
        else:
            base_url = self._get_url(base_url, url_variables)

        request = operations.DisableCardRequest(
            account_id=account_id,
            card_id=card_id,
        )

        req = self._build_request(
            method="DELETE",
            path="/accounts/{accountID}/cards/{cardID}",
            base_url=base_url,
            url_variables=url_variables,
            request=request,
            request_body_required=False,
            request_has_path_params=True,
            request_has_query_params=True,
            user_agent_header="user-agent",
            accept_header_value="application/json",
            http_headers=http_headers,
            _globals=operations.DisableCardGlobals(
                x_moov_version=self.sdk_configuration.globals.x_moov_version,
            ),
            security=self.sdk_configuration.security,
            allow_empty_value=None,
            timeout_ms=timeout_ms,
        )

        if retries == UNSET:
            if self.sdk_configuration.retry_config is not UNSET:
                retries = self.sdk_configuration.retry_config

        retry_config = None
        if isinstance(retries, utils.RetryConfig):
            retry_config = (retries, ["429", "500", "502", "503", "504"])

        http_res = self.do_request(
            hook_ctx=HookContext(
                config=self.sdk_configuration,
                base_url=base_url or "",
                operation_id="disableCard",
                oauth2_scopes=None,
                security_source=get_security_from_env(
                    self.sdk_configuration.security, components.Security
                ),
            ),
            request=req,
            error_status_codes=[
                "400",
                "401",
                "403",
                "404",
                "409",
                "429",
                "4XX",
                "500",
                "504",
                "5XX",
            ],
            retry_config=retry_config,
        )

        response_data: Any = None
        if utils.match_response(http_res, "204", "*"):
            return operations.DisableCardResponse(
                headers=utils.get_response_headers(http_res.headers)
            )
        if utils.match_response(http_res, ["400", "409"], "application/json"):
            response_data = unmarshal_json_response(errors.GenericErrorData, http_res)
            raise errors.GenericError(response_data, http_res)
        if utils.match_response(http_res, ["401", "403", "404", "429"], "*"):
            http_res_text = utils.stream_to_text(http_res)
            raise errors.APIError("API error occurred", http_res, http_res_text)
        if utils.match_response(http_res, ["500", "504"], "*"):
            http_res_text = utils.stream_to_text(http_res)
            raise errors.APIError("API error occurred", http_res, http_res_text)
        if utils.match_response(http_res, "4XX", "*"):
            http_res_text = utils.stream_to_text(http_res)
            raise errors.APIError("API error occurred", http_res, http_res_text)
        if utils.match_response(http_res, "5XX", "*"):
            http_res_text = utils.stream_to_text(http_res)
            raise errors.APIError("API error occurred", http_res, http_res_text)

        raise errors.APIError("Unexpected response received", http_res)

    async def disable_async(
        self,
        *,
        account_id: str,
        card_id: str,
        retries: OptionalNullable[utils.RetryConfig] = UNSET,
        server_url: Optional[str] = None,
        timeout_ms: Optional[int] = None,
        http_headers: Optional[Mapping[str, str]] = None,
    ) -> operations.DisableCardResponse:
        r"""Disables a card associated with a Moov account.

        To access this endpoint using an [access token](https://docs.moov.io/api/authentication/access-tokens/)
        you'll need to specify the `/accounts/{accountID}/cards.write` scope.

        :param account_id:
        :param card_id:
        :param retries: Override the default retry configuration for this method
        :param server_url: Override the default server URL for this method
        :param timeout_ms: Override the default request timeout configuration for this method in milliseconds
        :param http_headers: Additional headers to set or replace on requests.
        """
        base_url = None
        url_variables = None
        if timeout_ms is None:
            timeout_ms = self.sdk_configuration.timeout_ms

        if server_url is not None:
            base_url = server_url
        else:
            base_url = self._get_url(base_url, url_variables)

        request = operations.DisableCardRequest(
            account_id=account_id,
            card_id=card_id,
        )

        req = self._build_request_async(
            method="DELETE",
            path="/accounts/{accountID}/cards/{cardID}",
            base_url=base_url,
            url_variables=url_variables,
            request=request,
            request_body_required=False,
            request_has_path_params=True,
            request_has_query_params=True,
            user_agent_header="user-agent",
            accept_header_value="application/json",
            http_headers=http_headers,
            _globals=operations.DisableCardGlobals(
                x_moov_version=self.sdk_configuration.globals.x_moov_version,
            ),
            security=self.sdk_configuration.security,
            allow_empty_value=None,
            timeout_ms=timeout_ms,
        )

        if retries == UNSET:
            if self.sdk_configuration.retry_config is not UNSET:
                retries = self.sdk_configuration.retry_config

        retry_config = None
        if isinstance(retries, utils.RetryConfig):
            retry_config = (retries, ["429", "500", "502", "503", "504"])

        http_res = await self.do_request_async(
            hook_ctx=HookContext(
                config=self.sdk_configuration,
                base_url=base_url or "",
                operation_id="disableCard",
                oauth2_scopes=None,
                security_source=get_security_from_env(
                    self.sdk_configuration.security, components.Security
                ),
            ),
            request=req,
            error_status_codes=[
                "400",
                "401",
                "403",
                "404",
                "409",
                "429",
                "4XX",
                "500",
                "504",
                "5XX",
            ],
            retry_config=retry_config,
        )

        response_data: Any = None
        if utils.match_response(http_res, "204", "*"):
            return operations.DisableCardResponse(
                headers=utils.get_response_headers(http_res.headers)
            )
        if utils.match_response(http_res, ["400", "409"], "application/json"):
            response_data = unmarshal_json_response(errors.GenericErrorData, http_res)
            raise errors.GenericError(response_data, http_res)
        if utils.match_response(http_res, ["401", "403", "404", "429"], "*"):
            http_res_text = await utils.stream_to_text_async(http_res)
            raise errors.APIError("API error occurred", http_res, http_res_text)
        if utils.match_response(http_res, ["500", "504"], "*"):
            http_res_text = await utils.stream_to_text_async(http_res)
            raise errors.APIError("API error occurred", http_res, http_res_text)
        if utils.match_response(http_res, "4XX", "*"):
            http_res_text = await utils.stream_to_text_async(http_res)
            raise errors.APIError("API error occurred", http_res, http_res_text)
        if utils.match_response(http_res, "5XX", "*"):
            http_res_text = await utils.stream_to_text_async(http_res)
            raise errors.APIError("API error occurred", http_res, http_res_text)

        raise errors.APIError("Unexpected response received", http_res)
