"""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, Mapping, Optional, Union


class Underwriting(BaseSDK):
    def get(
        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.GetUnderwritingResponse:
        r"""Retrieve underwriting associated with a given Moov account.

        Read our [underwriting guide](https://docs.moov.io/guides/accounts/requirements/underwriting/) 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}/profile.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.GetUnderwritingRequest(
            account_id=account_id,
        )

        req = self._build_request(
            method="GET",
            path="/accounts/{accountID}/underwriting",
            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.GetUnderwritingGlobals(
                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="getUnderwriting",
                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.GetUnderwritingResponse(
                result=unmarshal_json_response(components.Underwriting, 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,
        retries: OptionalNullable[utils.RetryConfig] = UNSET,
        server_url: Optional[str] = None,
        timeout_ms: Optional[int] = None,
        http_headers: Optional[Mapping[str, str]] = None,
    ) -> operations.GetUnderwritingResponse:
        r"""Retrieve underwriting associated with a given Moov account.

        Read our [underwriting guide](https://docs.moov.io/guides/accounts/requirements/underwriting/) 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}/profile.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.GetUnderwritingRequest(
            account_id=account_id,
        )

        req = self._build_request_async(
            method="GET",
            path="/accounts/{accountID}/underwriting",
            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.GetUnderwritingGlobals(
                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="getUnderwriting",
                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.GetUnderwritingResponse(
                result=unmarshal_json_response(components.Underwriting, 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 save(
        self,
        *,
        account_id: str,
        geographic_reach: Optional[components.GeographicReach] = None,
        business_presence: Optional[components.BusinessPresence] = None,
        pending_litigation: Optional[components.PendingLitigation] = None,
        volume_share_by_customer_type: Optional[
            Union[
                components.VolumeShareByCustomerType,
                components.VolumeShareByCustomerTypeTypedDict,
            ]
        ] = None,
        collect_funds: Optional[
            Union[components.CollectFunds, components.CollectFundsTypedDict]
        ] = None,
        money_transfer: Optional[
            Union[components.MoneyTransfer, components.MoneyTransferTypedDict]
        ] = None,
        send_funds: Optional[
            Union[components.SendFunds, components.SendFundsTypedDict]
        ] = None,
        submission_intent: Optional[components.SubmissionIntent] = None,
        retries: OptionalNullable[utils.RetryConfig] = UNSET,
        server_url: Optional[str] = None,
        timeout_ms: Optional[int] = None,
        http_headers: Optional[Mapping[str, str]] = None,
    ) -> operations.SaveUnderwritingResponse:
        r"""Create or update the account's underwriting.

        Read our [underwriting guide](https://docs.moov.io/guides/accounts/requirements/underwriting/) 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}/profile.write` scope.

        :param account_id:
        :param geographic_reach:
        :param business_presence:
        :param pending_litigation:
        :param volume_share_by_customer_type:
        :param collect_funds:
        :param money_transfer:
        :param send_funds:
        :param submission_intent:
        :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.SaveUnderwritingRequest(
            account_id=account_id,
            upsert_underwriting=components.UpsertUnderwriting(
                geographic_reach=geographic_reach,
                business_presence=business_presence,
                pending_litigation=pending_litigation,
                volume_share_by_customer_type=utils.get_pydantic_model(
                    volume_share_by_customer_type,
                    Optional[components.VolumeShareByCustomerType],
                ),
                collect_funds=utils.get_pydantic_model(
                    collect_funds, Optional[components.CollectFunds]
                ),
                money_transfer=utils.get_pydantic_model(
                    money_transfer, Optional[components.MoneyTransfer]
                ),
                send_funds=utils.get_pydantic_model(
                    send_funds, Optional[components.SendFunds]
                ),
                submission_intent=submission_intent,
            ),
        )

        req = self._build_request(
            method="POST",
            path="/accounts/{accountID}/underwriting",
            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.SaveUnderwritingGlobals(
                x_moov_version=self.sdk_configuration.globals.x_moov_version,
            ),
            security=self.sdk_configuration.security,
            get_serialized_body=lambda: utils.serialize_request_body(
                request.upsert_underwriting,
                False,
                False,
                "json",
                components.UpsertUnderwriting,
            ),
            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="saveUnderwriting",
                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.SaveUnderwritingResponse(
                result=unmarshal_json_response(components.Underwriting, 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.UpsertUnderwritingErrorData, http_res
            )
            raise errors.UpsertUnderwritingError(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 save_async(
        self,
        *,
        account_id: str,
        geographic_reach: Optional[components.GeographicReach] = None,
        business_presence: Optional[components.BusinessPresence] = None,
        pending_litigation: Optional[components.PendingLitigation] = None,
        volume_share_by_customer_type: Optional[
            Union[
                components.VolumeShareByCustomerType,
                components.VolumeShareByCustomerTypeTypedDict,
            ]
        ] = None,
        collect_funds: Optional[
            Union[components.CollectFunds, components.CollectFundsTypedDict]
        ] = None,
        money_transfer: Optional[
            Union[components.MoneyTransfer, components.MoneyTransferTypedDict]
        ] = None,
        send_funds: Optional[
            Union[components.SendFunds, components.SendFundsTypedDict]
        ] = None,
        submission_intent: Optional[components.SubmissionIntent] = None,
        retries: OptionalNullable[utils.RetryConfig] = UNSET,
        server_url: Optional[str] = None,
        timeout_ms: Optional[int] = None,
        http_headers: Optional[Mapping[str, str]] = None,
    ) -> operations.SaveUnderwritingResponse:
        r"""Create or update the account's underwriting.

        Read our [underwriting guide](https://docs.moov.io/guides/accounts/requirements/underwriting/) 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}/profile.write` scope.

        :param account_id:
        :param geographic_reach:
        :param business_presence:
        :param pending_litigation:
        :param volume_share_by_customer_type:
        :param collect_funds:
        :param money_transfer:
        :param send_funds:
        :param submission_intent:
        :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.SaveUnderwritingRequest(
            account_id=account_id,
            upsert_underwriting=components.UpsertUnderwriting(
                geographic_reach=geographic_reach,
                business_presence=business_presence,
                pending_litigation=pending_litigation,
                volume_share_by_customer_type=utils.get_pydantic_model(
                    volume_share_by_customer_type,
                    Optional[components.VolumeShareByCustomerType],
                ),
                collect_funds=utils.get_pydantic_model(
                    collect_funds, Optional[components.CollectFunds]
                ),
                money_transfer=utils.get_pydantic_model(
                    money_transfer, Optional[components.MoneyTransfer]
                ),
                send_funds=utils.get_pydantic_model(
                    send_funds, Optional[components.SendFunds]
                ),
                submission_intent=submission_intent,
            ),
        )

        req = self._build_request_async(
            method="POST",
            path="/accounts/{accountID}/underwriting",
            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.SaveUnderwritingGlobals(
                x_moov_version=self.sdk_configuration.globals.x_moov_version,
            ),
            security=self.sdk_configuration.security,
            get_serialized_body=lambda: utils.serialize_request_body(
                request.upsert_underwriting,
                False,
                False,
                "json",
                components.UpsertUnderwriting,
            ),
            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="saveUnderwriting",
                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.SaveUnderwritingResponse(
                result=unmarshal_json_response(components.Underwriting, 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.UpsertUnderwritingErrorData, http_res
            )
            raise errors.UpsertUnderwritingError(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 upsert(
        self,
        *,
        account_id: str,
        average_transaction_size: int,
        max_transaction_size: int,
        average_monthly_transaction_volume: int,
        volume_by_customer_type: Union[
            components.VolumeByCustomerType, components.VolumeByCustomerTypeTypedDict
        ],
        card_volume_distribution: Union[
            components.CardVolumeDistribution,
            components.CardVolumeDistributionTypedDict,
        ],
        fulfillment: Union[
            components.FulfillmentDetails, components.FulfillmentDetailsTypedDict
        ],
        retries: OptionalNullable[utils.RetryConfig] = UNSET,
        server_url: Optional[str] = None,
        timeout_ms: Optional[int] = None,
        http_headers: Optional[Mapping[str, str]] = None,
    ) -> operations.UpsertUnderwritingResponse:
        r"""Create or update the account's underwriting.

        Read our [underwriting guide](https://docs.moov.io/guides/accounts/requirements/underwriting/) 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}/profile.write` scope.

        :param account_id:
        :param average_transaction_size:
        :param max_transaction_size:
        :param average_monthly_transaction_volume:
        :param volume_by_customer_type:
        :param card_volume_distribution:
        :param fulfillment:
        :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.UpsertUnderwritingRequest(
            account_id=account_id,
            update_underwriting=components.UpdateUnderwriting(
                average_transaction_size=average_transaction_size,
                max_transaction_size=max_transaction_size,
                average_monthly_transaction_volume=average_monthly_transaction_volume,
                volume_by_customer_type=utils.get_pydantic_model(
                    volume_by_customer_type, components.VolumeByCustomerType
                ),
                card_volume_distribution=utils.get_pydantic_model(
                    card_volume_distribution, components.CardVolumeDistribution
                ),
                fulfillment=utils.get_pydantic_model(
                    fulfillment, components.FulfillmentDetails
                ),
            ),
        )

        req = self._build_request(
            method="PUT",
            path="/accounts/{accountID}/underwriting",
            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.UpsertUnderwritingGlobals(
                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_underwriting,
                False,
                False,
                "json",
                components.UpdateUnderwriting,
            ),
            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="upsertUnderwriting",
                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.UpsertUnderwritingResponse(
                result=unmarshal_json_response(components.Underwriting, 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.UpdateUnderwritingErrorData, http_res
            )
            raise errors.UpdateUnderwritingError(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 upsert_async(
        self,
        *,
        account_id: str,
        average_transaction_size: int,
        max_transaction_size: int,
        average_monthly_transaction_volume: int,
        volume_by_customer_type: Union[
            components.VolumeByCustomerType, components.VolumeByCustomerTypeTypedDict
        ],
        card_volume_distribution: Union[
            components.CardVolumeDistribution,
            components.CardVolumeDistributionTypedDict,
        ],
        fulfillment: Union[
            components.FulfillmentDetails, components.FulfillmentDetailsTypedDict
        ],
        retries: OptionalNullable[utils.RetryConfig] = UNSET,
        server_url: Optional[str] = None,
        timeout_ms: Optional[int] = None,
        http_headers: Optional[Mapping[str, str]] = None,
    ) -> operations.UpsertUnderwritingResponse:
        r"""Create or update the account's underwriting.

        Read our [underwriting guide](https://docs.moov.io/guides/accounts/requirements/underwriting/) 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}/profile.write` scope.

        :param account_id:
        :param average_transaction_size:
        :param max_transaction_size:
        :param average_monthly_transaction_volume:
        :param volume_by_customer_type:
        :param card_volume_distribution:
        :param fulfillment:
        :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.UpsertUnderwritingRequest(
            account_id=account_id,
            update_underwriting=components.UpdateUnderwriting(
                average_transaction_size=average_transaction_size,
                max_transaction_size=max_transaction_size,
                average_monthly_transaction_volume=average_monthly_transaction_volume,
                volume_by_customer_type=utils.get_pydantic_model(
                    volume_by_customer_type, components.VolumeByCustomerType
                ),
                card_volume_distribution=utils.get_pydantic_model(
                    card_volume_distribution, components.CardVolumeDistribution
                ),
                fulfillment=utils.get_pydantic_model(
                    fulfillment, components.FulfillmentDetails
                ),
            ),
        )

        req = self._build_request_async(
            method="PUT",
            path="/accounts/{accountID}/underwriting",
            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.UpsertUnderwritingGlobals(
                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_underwriting,
                False,
                False,
                "json",
                components.UpdateUnderwriting,
            ),
            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="upsertUnderwriting",
                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.UpsertUnderwritingResponse(
                result=unmarshal_json_response(components.Underwriting, 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.UpdateUnderwritingErrorData, http_res
            )
            raise errors.UpdateUnderwritingError(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)
