# pylint: disable=too-many-lines,too-many-statements
# coding=utf-8
# --------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
# Code generated by Microsoft (R) AutoRest Code Generator.
# Changes may cause incorrect behavior and will be lost if the code is regenerated.
# --------------------------------------------------------------------------
import datetime
from io import IOBase
import sys
from typing import (
    Any,
    AsyncIterable,
    AsyncIterator,
    Callable,
    Dict,
    IO,
    List,
    Optional,
    Type,
    TypeVar,
    Union,
    cast,
    overload,
)
import urllib.parse

from azure.core.async_paging import AsyncItemPaged, AsyncList
from azure.core.exceptions import (
    ClientAuthenticationError,
    HttpResponseError,
    ResourceExistsError,
    ResourceNotFoundError,
    ResourceNotModifiedError,
    StreamClosedError,
    StreamConsumedError,
    map_error,
)
from azure.core.pipeline import PipelineResponse
from azure.core.polling import AsyncLROPoller, AsyncNoPolling, AsyncPollingMethod
from azure.core.rest import AsyncHttpResponse, HttpRequest
from azure.core.tracing.decorator import distributed_trace
from azure.core.tracing.decorator_async import distributed_trace_async
from azure.core.utils import case_insensitive_dict
from azure.mgmt.core.exceptions import ARMErrorFormat
from azure.mgmt.core.polling.async_arm_polling import AsyncARMPolling

from ... import models as _models
from ...operations._invoices_operations import (
    build_amend_request,
    build_download_by_billing_account_request,
    build_download_by_billing_subscription_request,
    build_download_documents_by_billing_account_request,
    build_download_documents_by_billing_subscription_request,
    build_download_summary_by_billing_account_request,
    build_get_by_billing_account_request,
    build_get_by_billing_subscription_request,
    build_get_request,
    build_list_by_billing_account_request,
    build_list_by_billing_profile_request,
    build_list_by_billing_subscription_request,
)

if sys.version_info >= (3, 9):
    from collections.abc import MutableMapping
else:
    from typing import MutableMapping  # type: ignore  # pylint: disable=ungrouped-imports
T = TypeVar("T")
ClsType = Optional[Callable[[PipelineResponse[HttpRequest, AsyncHttpResponse], T, Dict[str, Any]], Any]]


class InvoicesOperations:
    """
    .. warning::
        **DO NOT** instantiate this class directly.

        Instead, you should access the following operations through
        :class:`~azure.mgmt.billing.aio.BillingManagementClient`'s
        :attr:`invoices` attribute.
    """

    models = _models

    def __init__(self, *args, **kwargs) -> None:
        input_args = list(args)
        self._client = input_args.pop(0) if input_args else kwargs.pop("client")
        self._config = input_args.pop(0) if input_args else kwargs.pop("config")
        self._serialize = input_args.pop(0) if input_args else kwargs.pop("serializer")
        self._deserialize = input_args.pop(0) if input_args else kwargs.pop("deserializer")

    @distributed_trace
    def list_by_billing_profile(
        self,
        billing_account_name: str,
        billing_profile_name: str,
        period_start_date: Optional[datetime.date] = None,
        period_end_date: Optional[datetime.date] = None,
        filter: Optional[str] = None,
        order_by: Optional[str] = None,
        top: Optional[int] = None,
        skip: Optional[int] = None,
        count: Optional[bool] = None,
        search: Optional[str] = None,
        **kwargs: Any
    ) -> AsyncIterable["_models.Invoice"]:
        """Lists the invoices for a billing profile for a given start date and end date. The operation is
        supported for billing accounts with agreement type Microsoft Partner Agreement or Microsoft
        Customer Agreement.

        .. seealso::
           - https://docs.microsoft.com/en-us/rest/api/billing/

        :param billing_account_name: The ID that uniquely identifies a billing account. Required.
        :type billing_account_name: str
        :param billing_profile_name: The ID that uniquely identifies a billing profile. Required.
        :type billing_profile_name: str
        :param period_start_date: The start date of the billing period for which the invoice is
         generated. The date is in MM-DD-YYYY format. Default value is None.
        :type period_start_date: ~datetime.date
        :param period_end_date: The end date of the billing period for which the invoice is generated.
         The date is in MM-DD-YYYY format. Default value is None.
        :type period_end_date: ~datetime.date
        :param filter: The filter query option allows clients to filter a collection of resources that
         are addressed by a request URL. Default value is None.
        :type filter: str
        :param order_by: The orderby query option allows clients to request resources in a particular
         order. Default value is None.
        :type order_by: str
        :param top: The top query option requests the number of items in the queried collection to be
         included in the result. The maximum supported value for top is 50. Default value is None.
        :type top: int
        :param skip: The skip query option requests the number of items in the queried collection that
         are to be skipped and not included in the result. Default value is None.
        :type skip: int
        :param count: The count query option allows clients to request a count of the matching
         resources included with the resources in the response. Default value is None.
        :type count: bool
        :param search: The search query option allows clients to request items within a collection
         matching a free-text search expression. search is only supported for string fields. Default
         value is None.
        :type search: str
        :return: An iterator like instance of either Invoice or the result of cls(response)
        :rtype: ~azure.core.async_paging.AsyncItemPaged[~azure.mgmt.billing.models.Invoice]
        :raises ~azure.core.exceptions.HttpResponseError:
        """
        _headers = kwargs.pop("headers", {}) or {}
        _params = case_insensitive_dict(kwargs.pop("params", {}) or {})

        api_version: str = kwargs.pop("api_version", _params.pop("api-version", self._config.api_version))
        cls: ClsType[_models.InvoiceListResult] = kwargs.pop("cls", None)

        error_map: MutableMapping[int, Type[HttpResponseError]] = {
            401: ClientAuthenticationError,
            404: ResourceNotFoundError,
            409: ResourceExistsError,
            304: ResourceNotModifiedError,
        }
        error_map.update(kwargs.pop("error_map", {}) or {})

        def prepare_request(next_link=None):
            if not next_link:

                _request = build_list_by_billing_profile_request(
                    billing_account_name=billing_account_name,
                    billing_profile_name=billing_profile_name,
                    period_start_date=period_start_date,
                    period_end_date=period_end_date,
                    filter=filter,
                    order_by=order_by,
                    top=top,
                    skip=skip,
                    count=count,
                    search=search,
                    api_version=api_version,
                    headers=_headers,
                    params=_params,
                )
                _request.url = self._client.format_url(_request.url)

            else:
                # make call to next link with the client's api-version
                _parsed_next_link = urllib.parse.urlparse(next_link)
                _next_request_params = case_insensitive_dict(
                    {
                        key: [urllib.parse.quote(v) for v in value]
                        for key, value in urllib.parse.parse_qs(_parsed_next_link.query).items()
                    }
                )
                _next_request_params["api-version"] = self._config.api_version
                _request = HttpRequest(
                    "GET", urllib.parse.urljoin(next_link, _parsed_next_link.path), params=_next_request_params
                )
                _request.url = self._client.format_url(_request.url)
                _request.method = "GET"
            return _request

        async def extract_data(pipeline_response):
            deserialized = self._deserialize("InvoiceListResult", pipeline_response)
            list_of_elem = deserialized.value
            if cls:
                list_of_elem = cls(list_of_elem)  # type: ignore
            return deserialized.next_link or None, AsyncList(list_of_elem)

        async def get_next(next_link=None):
            _request = prepare_request(next_link)

            _stream = False
            pipeline_response: PipelineResponse = await self._client._pipeline.run(  # pylint: disable=protected-access
                _request, stream=_stream, **kwargs
            )
            response = pipeline_response.http_response

            if response.status_code not in [200]:
                map_error(status_code=response.status_code, response=response, error_map=error_map)
                error = self._deserialize.failsafe_deserialize(_models.ErrorResponse, pipeline_response)
                raise HttpResponseError(response=response, model=error, error_format=ARMErrorFormat)

            return pipeline_response

        return AsyncItemPaged(get_next, extract_data)

    async def _download_documents_by_billing_account_initial(  # pylint: disable=name-too-long
        self,
        billing_account_name: str,
        parameters: Union[List[_models.DocumentDownloadRequest], IO[bytes]],
        **kwargs: Any
    ) -> AsyncIterator[bytes]:
        error_map: MutableMapping[int, Type[HttpResponseError]] = {
            401: ClientAuthenticationError,
            404: ResourceNotFoundError,
            409: ResourceExistsError,
            304: ResourceNotModifiedError,
        }
        error_map.update(kwargs.pop("error_map", {}) or {})

        _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {})
        _params = case_insensitive_dict(kwargs.pop("params", {}) or {})

        api_version: str = kwargs.pop("api_version", _params.pop("api-version", self._config.api_version))
        content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None))
        cls: ClsType[AsyncIterator[bytes]] = kwargs.pop("cls", None)

        content_type = content_type or "application/json"
        _json = None
        _content = None
        if isinstance(parameters, (IOBase, bytes)):
            _content = parameters
        else:
            _json = self._serialize.body(parameters, "[DocumentDownloadRequest]")

        _request = build_download_documents_by_billing_account_request(
            billing_account_name=billing_account_name,
            api_version=api_version,
            content_type=content_type,
            json=_json,
            content=_content,
            headers=_headers,
            params=_params,
        )
        _request.url = self._client.format_url(_request.url)

        _decompress = kwargs.pop("decompress", True)
        _stream = True
        pipeline_response: PipelineResponse = await self._client._pipeline.run(  # pylint: disable=protected-access
            _request, stream=_stream, **kwargs
        )

        response = pipeline_response.http_response

        if response.status_code not in [200, 202]:
            try:
                await response.read()  # Load the body in memory and close the socket
            except (StreamConsumedError, StreamClosedError):
                pass
            map_error(status_code=response.status_code, response=response, error_map=error_map)
            error = self._deserialize.failsafe_deserialize(_models.ErrorResponse, pipeline_response)
            raise HttpResponseError(response=response, model=error, error_format=ARMErrorFormat)

        response_headers = {}
        if response.status_code == 202:
            response_headers["Location"] = self._deserialize("str", response.headers.get("Location"))
            response_headers["Retry-After"] = self._deserialize("int", response.headers.get("Retry-After"))

        deserialized = response.stream_download(self._client._pipeline, decompress=_decompress)

        if cls:
            return cls(pipeline_response, deserialized, response_headers)  # type: ignore

        return deserialized  # type: ignore

    @overload
    async def begin_download_documents_by_billing_account(  # pylint: disable=name-too-long
        self,
        billing_account_name: str,
        parameters: List[_models.DocumentDownloadRequest],
        *,
        content_type: str = "application/json",
        **kwargs: Any
    ) -> AsyncLROPoller[_models.DocumentDownloadResult]:
        """Gets a URL to download multiple invoice documents (invoice pdf, tax receipts, credit notes) as
        a zip file. The operation is supported for billing accounts with agreement type Microsoft
        Partner Agreement or Microsoft Customer Agreement.

        .. seealso::
           - https://docs.microsoft.com/en-us/rest/api/billing/

        :param billing_account_name: The ID that uniquely identifies a billing account. Required.
        :type billing_account_name: str
        :param parameters: A list of download details for individual documents. Required.
        :type parameters: list[~azure.mgmt.billing.models.DocumentDownloadRequest]
        :keyword content_type: Body Parameter content-type. Content type parameter for JSON body.
         Default value is "application/json".
        :paramtype content_type: str
        :return: An instance of AsyncLROPoller that returns either DocumentDownloadResult or the result
         of cls(response)
        :rtype: ~azure.core.polling.AsyncLROPoller[~azure.mgmt.billing.models.DocumentDownloadResult]
        :raises ~azure.core.exceptions.HttpResponseError:
        """

    @overload
    async def begin_download_documents_by_billing_account(  # pylint: disable=name-too-long
        self, billing_account_name: str, parameters: IO[bytes], *, content_type: str = "application/json", **kwargs: Any
    ) -> AsyncLROPoller[_models.DocumentDownloadResult]:
        """Gets a URL to download multiple invoice documents (invoice pdf, tax receipts, credit notes) as
        a zip file. The operation is supported for billing accounts with agreement type Microsoft
        Partner Agreement or Microsoft Customer Agreement.

        .. seealso::
           - https://docs.microsoft.com/en-us/rest/api/billing/

        :param billing_account_name: The ID that uniquely identifies a billing account. Required.
        :type billing_account_name: str
        :param parameters: A list of download details for individual documents. Required.
        :type parameters: IO[bytes]
        :keyword content_type: Body Parameter content-type. Content type parameter for binary body.
         Default value is "application/json".
        :paramtype content_type: str
        :return: An instance of AsyncLROPoller that returns either DocumentDownloadResult or the result
         of cls(response)
        :rtype: ~azure.core.polling.AsyncLROPoller[~azure.mgmt.billing.models.DocumentDownloadResult]
        :raises ~azure.core.exceptions.HttpResponseError:
        """

    @distributed_trace_async
    async def begin_download_documents_by_billing_account(  # pylint: disable=name-too-long
        self,
        billing_account_name: str,
        parameters: Union[List[_models.DocumentDownloadRequest], IO[bytes]],
        **kwargs: Any
    ) -> AsyncLROPoller[_models.DocumentDownloadResult]:
        """Gets a URL to download multiple invoice documents (invoice pdf, tax receipts, credit notes) as
        a zip file. The operation is supported for billing accounts with agreement type Microsoft
        Partner Agreement or Microsoft Customer Agreement.

        .. seealso::
           - https://docs.microsoft.com/en-us/rest/api/billing/

        :param billing_account_name: The ID that uniquely identifies a billing account. Required.
        :type billing_account_name: str
        :param parameters: A list of download details for individual documents. Is either a
         [DocumentDownloadRequest] type or a IO[bytes] type. Required.
        :type parameters: list[~azure.mgmt.billing.models.DocumentDownloadRequest] or IO[bytes]
        :return: An instance of AsyncLROPoller that returns either DocumentDownloadResult or the result
         of cls(response)
        :rtype: ~azure.core.polling.AsyncLROPoller[~azure.mgmt.billing.models.DocumentDownloadResult]
        :raises ~azure.core.exceptions.HttpResponseError:
        """
        _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {})
        _params = case_insensitive_dict(kwargs.pop("params", {}) or {})

        api_version: str = kwargs.pop("api_version", _params.pop("api-version", self._config.api_version))
        content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None))
        cls: ClsType[_models.DocumentDownloadResult] = kwargs.pop("cls", None)
        polling: Union[bool, AsyncPollingMethod] = kwargs.pop("polling", True)
        lro_delay = kwargs.pop("polling_interval", self._config.polling_interval)
        cont_token: Optional[str] = kwargs.pop("continuation_token", None)
        if cont_token is None:
            raw_result = await self._download_documents_by_billing_account_initial(
                billing_account_name=billing_account_name,
                parameters=parameters,
                api_version=api_version,
                content_type=content_type,
                cls=lambda x, y, z: x,
                headers=_headers,
                params=_params,
                **kwargs
            )
            await raw_result.http_response.read()  # type: ignore
        kwargs.pop("error_map", None)

        def get_long_running_output(pipeline_response):
            deserialized = self._deserialize("DocumentDownloadResult", pipeline_response.http_response)
            if cls:
                return cls(pipeline_response, deserialized, {})  # type: ignore
            return deserialized

        if polling is True:
            polling_method: AsyncPollingMethod = cast(
                AsyncPollingMethod, AsyncARMPolling(lro_delay, lro_options={"final-state-via": "location"}, **kwargs)
            )
        elif polling is False:
            polling_method = cast(AsyncPollingMethod, AsyncNoPolling())
        else:
            polling_method = polling
        if cont_token:
            return AsyncLROPoller[_models.DocumentDownloadResult].from_continuation_token(
                polling_method=polling_method,
                continuation_token=cont_token,
                client=self._client,
                deserialization_callback=get_long_running_output,
            )
        return AsyncLROPoller[_models.DocumentDownloadResult](
            self._client, raw_result, get_long_running_output, polling_method  # type: ignore
        )

    async def _amend_initial(self, billing_account_name: str, invoice_name: str, **kwargs: Any) -> AsyncIterator[bytes]:
        error_map: MutableMapping[int, Type[HttpResponseError]] = {
            401: ClientAuthenticationError,
            404: ResourceNotFoundError,
            409: ResourceExistsError,
            304: ResourceNotModifiedError,
        }
        error_map.update(kwargs.pop("error_map", {}) or {})

        _headers = kwargs.pop("headers", {}) or {}
        _params = case_insensitive_dict(kwargs.pop("params", {}) or {})

        api_version: str = kwargs.pop("api_version", _params.pop("api-version", self._config.api_version))
        cls: ClsType[AsyncIterator[bytes]] = kwargs.pop("cls", None)

        _request = build_amend_request(
            billing_account_name=billing_account_name,
            invoice_name=invoice_name,
            api_version=api_version,
            headers=_headers,
            params=_params,
        )
        _request.url = self._client.format_url(_request.url)

        _decompress = kwargs.pop("decompress", True)
        _stream = True
        pipeline_response: PipelineResponse = await self._client._pipeline.run(  # pylint: disable=protected-access
            _request, stream=_stream, **kwargs
        )

        response = pipeline_response.http_response

        if response.status_code not in [202]:
            try:
                await response.read()  # Load the body in memory and close the socket
            except (StreamConsumedError, StreamClosedError):
                pass
            map_error(status_code=response.status_code, response=response, error_map=error_map)
            error = self._deserialize.failsafe_deserialize(_models.ErrorResponse, pipeline_response)
            raise HttpResponseError(response=response, model=error, error_format=ARMErrorFormat)

        response_headers = {}
        response_headers["Location"] = self._deserialize("str", response.headers.get("Location"))
        response_headers["Retry-After"] = self._deserialize("int", response.headers.get("Retry-After"))

        deserialized = response.stream_download(self._client._pipeline, decompress=_decompress)

        if cls:
            return cls(pipeline_response, deserialized, response_headers)  # type: ignore

        return deserialized  # type: ignore

    @distributed_trace_async
    async def begin_amend(self, billing_account_name: str, invoice_name: str, **kwargs: Any) -> AsyncLROPoller[None]:
        """Regenerate an invoice by billing account name and invoice name. The operation is supported for
        billing accounts with agreement type Microsoft Customer Agreement.

        .. seealso::
           - https://docs.microsoft.com/en-us/rest/api/billing/

        :param billing_account_name: The ID that uniquely identifies a billing account. Required.
        :type billing_account_name: str
        :param invoice_name: The ID that uniquely identifies an invoice. Required.
        :type invoice_name: str
        :return: An instance of AsyncLROPoller that returns either None or the result of cls(response)
        :rtype: ~azure.core.polling.AsyncLROPoller[None]
        :raises ~azure.core.exceptions.HttpResponseError:
        """
        _headers = kwargs.pop("headers", {}) or {}
        _params = case_insensitive_dict(kwargs.pop("params", {}) or {})

        api_version: str = kwargs.pop("api_version", _params.pop("api-version", self._config.api_version))
        cls: ClsType[None] = kwargs.pop("cls", None)
        polling: Union[bool, AsyncPollingMethod] = kwargs.pop("polling", True)
        lro_delay = kwargs.pop("polling_interval", self._config.polling_interval)
        cont_token: Optional[str] = kwargs.pop("continuation_token", None)
        if cont_token is None:
            raw_result = await self._amend_initial(
                billing_account_name=billing_account_name,
                invoice_name=invoice_name,
                api_version=api_version,
                cls=lambda x, y, z: x,
                headers=_headers,
                params=_params,
                **kwargs
            )
            await raw_result.http_response.read()  # type: ignore
        kwargs.pop("error_map", None)

        def get_long_running_output(pipeline_response):  # pylint: disable=inconsistent-return-statements
            if cls:
                return cls(pipeline_response, None, {})  # type: ignore

        if polling is True:
            polling_method: AsyncPollingMethod = cast(
                AsyncPollingMethod, AsyncARMPolling(lro_delay, lro_options={"final-state-via": "location"}, **kwargs)
            )
        elif polling is False:
            polling_method = cast(AsyncPollingMethod, AsyncNoPolling())
        else:
            polling_method = polling
        if cont_token:
            return AsyncLROPoller[None].from_continuation_token(
                polling_method=polling_method,
                continuation_token=cont_token,
                client=self._client,
                deserialization_callback=get_long_running_output,
            )
        return AsyncLROPoller[None](self._client, raw_result, get_long_running_output, polling_method)  # type: ignore

    async def _download_by_billing_account_initial(
        self, billing_account_name: str, invoice_name: str, document_name: Optional[str] = None, **kwargs: Any
    ) -> AsyncIterator[bytes]:
        error_map: MutableMapping[int, Type[HttpResponseError]] = {
            401: ClientAuthenticationError,
            404: ResourceNotFoundError,
            409: ResourceExistsError,
            304: ResourceNotModifiedError,
        }
        error_map.update(kwargs.pop("error_map", {}) or {})

        _headers = kwargs.pop("headers", {}) or {}
        _params = case_insensitive_dict(kwargs.pop("params", {}) or {})

        api_version: str = kwargs.pop("api_version", _params.pop("api-version", self._config.api_version))
        cls: ClsType[AsyncIterator[bytes]] = kwargs.pop("cls", None)

        _request = build_download_by_billing_account_request(
            billing_account_name=billing_account_name,
            invoice_name=invoice_name,
            document_name=document_name,
            api_version=api_version,
            headers=_headers,
            params=_params,
        )
        _request.url = self._client.format_url(_request.url)

        _decompress = kwargs.pop("decompress", True)
        _stream = True
        pipeline_response: PipelineResponse = await self._client._pipeline.run(  # pylint: disable=protected-access
            _request, stream=_stream, **kwargs
        )

        response = pipeline_response.http_response

        if response.status_code not in [200, 202]:
            try:
                await response.read()  # Load the body in memory and close the socket
            except (StreamConsumedError, StreamClosedError):
                pass
            map_error(status_code=response.status_code, response=response, error_map=error_map)
            error = self._deserialize.failsafe_deserialize(_models.ErrorResponse, pipeline_response)
            raise HttpResponseError(response=response, model=error, error_format=ARMErrorFormat)

        response_headers = {}
        if response.status_code == 202:
            response_headers["Location"] = self._deserialize("str", response.headers.get("Location"))
            response_headers["Retry-After"] = self._deserialize("int", response.headers.get("Retry-After"))

        deserialized = response.stream_download(self._client._pipeline, decompress=_decompress)

        if cls:
            return cls(pipeline_response, deserialized, response_headers)  # type: ignore

        return deserialized  # type: ignore

    @distributed_trace_async
    async def begin_download_by_billing_account(
        self, billing_account_name: str, invoice_name: str, document_name: Optional[str] = None, **kwargs: Any
    ) -> AsyncLROPoller[_models.DocumentDownloadResult]:
        """Gets a URL to download an invoice document. The operation is supported for billing accounts
        with agreement type Microsoft Partner Agreement, Microsoft Customer Agreement or Enterprise
        Agreement.

        .. seealso::
           - https://docs.microsoft.com/en-us/rest/api/billing/

        :param billing_account_name: The ID that uniquely identifies a billing account. Required.
        :type billing_account_name: str
        :param invoice_name: The ID that uniquely identifies an invoice. Required.
        :type invoice_name: str
        :param document_name: The ID that uniquely identifies an invoice document. This ID may be an
         identifier for an invoice PDF, a credit note, or a tax receipt. Default value is None.
        :type document_name: str
        :return: An instance of AsyncLROPoller that returns either DocumentDownloadResult or the result
         of cls(response)
        :rtype: ~azure.core.polling.AsyncLROPoller[~azure.mgmt.billing.models.DocumentDownloadResult]
        :raises ~azure.core.exceptions.HttpResponseError:
        """
        _headers = kwargs.pop("headers", {}) or {}
        _params = case_insensitive_dict(kwargs.pop("params", {}) or {})

        api_version: str = kwargs.pop("api_version", _params.pop("api-version", self._config.api_version))
        cls: ClsType[_models.DocumentDownloadResult] = kwargs.pop("cls", None)
        polling: Union[bool, AsyncPollingMethod] = kwargs.pop("polling", True)
        lro_delay = kwargs.pop("polling_interval", self._config.polling_interval)
        cont_token: Optional[str] = kwargs.pop("continuation_token", None)
        if cont_token is None:
            raw_result = await self._download_by_billing_account_initial(
                billing_account_name=billing_account_name,
                invoice_name=invoice_name,
                document_name=document_name,
                api_version=api_version,
                cls=lambda x, y, z: x,
                headers=_headers,
                params=_params,
                **kwargs
            )
            await raw_result.http_response.read()  # type: ignore
        kwargs.pop("error_map", None)

        def get_long_running_output(pipeline_response):
            deserialized = self._deserialize("DocumentDownloadResult", pipeline_response.http_response)
            if cls:
                return cls(pipeline_response, deserialized, {})  # type: ignore
            return deserialized

        if polling is True:
            polling_method: AsyncPollingMethod = cast(
                AsyncPollingMethod, AsyncARMPolling(lro_delay, lro_options={"final-state-via": "location"}, **kwargs)
            )
        elif polling is False:
            polling_method = cast(AsyncPollingMethod, AsyncNoPolling())
        else:
            polling_method = polling
        if cont_token:
            return AsyncLROPoller[_models.DocumentDownloadResult].from_continuation_token(
                polling_method=polling_method,
                continuation_token=cont_token,
                client=self._client,
                deserialization_callback=get_long_running_output,
            )
        return AsyncLROPoller[_models.DocumentDownloadResult](
            self._client, raw_result, get_long_running_output, polling_method  # type: ignore
        )

    async def _download_summary_by_billing_account_initial(  # pylint: disable=name-too-long
        self, billing_account_name: str, invoice_name: str, **kwargs: Any
    ) -> AsyncIterator[bytes]:
        error_map: MutableMapping[int, Type[HttpResponseError]] = {
            401: ClientAuthenticationError,
            404: ResourceNotFoundError,
            409: ResourceExistsError,
            304: ResourceNotModifiedError,
        }
        error_map.update(kwargs.pop("error_map", {}) or {})

        _headers = kwargs.pop("headers", {}) or {}
        _params = case_insensitive_dict(kwargs.pop("params", {}) or {})

        api_version: str = kwargs.pop("api_version", _params.pop("api-version", self._config.api_version))
        cls: ClsType[AsyncIterator[bytes]] = kwargs.pop("cls", None)

        _request = build_download_summary_by_billing_account_request(
            billing_account_name=billing_account_name,
            invoice_name=invoice_name,
            api_version=api_version,
            headers=_headers,
            params=_params,
        )
        _request.url = self._client.format_url(_request.url)

        _decompress = kwargs.pop("decompress", True)
        _stream = True
        pipeline_response: PipelineResponse = await self._client._pipeline.run(  # pylint: disable=protected-access
            _request, stream=_stream, **kwargs
        )

        response = pipeline_response.http_response

        if response.status_code not in [200, 202]:
            try:
                await response.read()  # Load the body in memory and close the socket
            except (StreamConsumedError, StreamClosedError):
                pass
            map_error(status_code=response.status_code, response=response, error_map=error_map)
            error = self._deserialize.failsafe_deserialize(_models.ErrorResponse, pipeline_response)
            raise HttpResponseError(response=response, model=error, error_format=ARMErrorFormat)

        response_headers = {}
        if response.status_code == 202:
            response_headers["Location"] = self._deserialize("str", response.headers.get("Location"))
            response_headers["Retry-After"] = self._deserialize("int", response.headers.get("Retry-After"))

        deserialized = response.stream_download(self._client._pipeline, decompress=_decompress)

        if cls:
            return cls(pipeline_response, deserialized, response_headers)  # type: ignore

        return deserialized  # type: ignore

    @distributed_trace_async
    async def begin_download_summary_by_billing_account(  # pylint: disable=name-too-long
        self, billing_account_name: str, invoice_name: str, **kwargs: Any
    ) -> AsyncLROPoller[_models.DocumentDownloadResult]:
        """Gets a URL to download the summary document for an invoice. The operation is supported for
        billing accounts with agreement type Enterprise Agreement.

        .. seealso::
           - https://docs.microsoft.com/en-us/rest/api/billing/

        :param billing_account_name: The ID that uniquely identifies a billing account. Required.
        :type billing_account_name: str
        :param invoice_name: The ID that uniquely identifies an invoice. Required.
        :type invoice_name: str
        :return: An instance of AsyncLROPoller that returns either DocumentDownloadResult or the result
         of cls(response)
        :rtype: ~azure.core.polling.AsyncLROPoller[~azure.mgmt.billing.models.DocumentDownloadResult]
        :raises ~azure.core.exceptions.HttpResponseError:
        """
        _headers = kwargs.pop("headers", {}) or {}
        _params = case_insensitive_dict(kwargs.pop("params", {}) or {})

        api_version: str = kwargs.pop("api_version", _params.pop("api-version", self._config.api_version))
        cls: ClsType[_models.DocumentDownloadResult] = kwargs.pop("cls", None)
        polling: Union[bool, AsyncPollingMethod] = kwargs.pop("polling", True)
        lro_delay = kwargs.pop("polling_interval", self._config.polling_interval)
        cont_token: Optional[str] = kwargs.pop("continuation_token", None)
        if cont_token is None:
            raw_result = await self._download_summary_by_billing_account_initial(
                billing_account_name=billing_account_name,
                invoice_name=invoice_name,
                api_version=api_version,
                cls=lambda x, y, z: x,
                headers=_headers,
                params=_params,
                **kwargs
            )
            await raw_result.http_response.read()  # type: ignore
        kwargs.pop("error_map", None)

        def get_long_running_output(pipeline_response):
            deserialized = self._deserialize("DocumentDownloadResult", pipeline_response.http_response)
            if cls:
                return cls(pipeline_response, deserialized, {})  # type: ignore
            return deserialized

        if polling is True:
            polling_method: AsyncPollingMethod = cast(
                AsyncPollingMethod, AsyncARMPolling(lro_delay, lro_options={"final-state-via": "location"}, **kwargs)
            )
        elif polling is False:
            polling_method = cast(AsyncPollingMethod, AsyncNoPolling())
        else:
            polling_method = polling
        if cont_token:
            return AsyncLROPoller[_models.DocumentDownloadResult].from_continuation_token(
                polling_method=polling_method,
                continuation_token=cont_token,
                client=self._client,
                deserialization_callback=get_long_running_output,
            )
        return AsyncLROPoller[_models.DocumentDownloadResult](
            self._client, raw_result, get_long_running_output, polling_method  # type: ignore
        )

    @distributed_trace_async
    async def get_by_billing_account(
        self, billing_account_name: str, invoice_name: str, **kwargs: Any
    ) -> _models.Invoice:
        """Gets an invoice by billing account name and ID. The operation is supported for all billing
        account types.

        .. seealso::
           - https://docs.microsoft.com/en-us/rest/api/billing/

        :param billing_account_name: The ID that uniquely identifies a billing account. Required.
        :type billing_account_name: str
        :param invoice_name: The ID that uniquely identifies an invoice. Required.
        :type invoice_name: str
        :return: Invoice or the result of cls(response)
        :rtype: ~azure.mgmt.billing.models.Invoice
        :raises ~azure.core.exceptions.HttpResponseError:
        """
        error_map: MutableMapping[int, Type[HttpResponseError]] = {
            401: ClientAuthenticationError,
            404: ResourceNotFoundError,
            409: ResourceExistsError,
            304: ResourceNotModifiedError,
        }
        error_map.update(kwargs.pop("error_map", {}) or {})

        _headers = kwargs.pop("headers", {}) or {}
        _params = case_insensitive_dict(kwargs.pop("params", {}) or {})

        api_version: str = kwargs.pop("api_version", _params.pop("api-version", self._config.api_version))
        cls: ClsType[_models.Invoice] = kwargs.pop("cls", None)

        _request = build_get_by_billing_account_request(
            billing_account_name=billing_account_name,
            invoice_name=invoice_name,
            api_version=api_version,
            headers=_headers,
            params=_params,
        )
        _request.url = self._client.format_url(_request.url)

        _stream = False
        pipeline_response: PipelineResponse = await self._client._pipeline.run(  # pylint: disable=protected-access
            _request, stream=_stream, **kwargs
        )

        response = pipeline_response.http_response

        if response.status_code not in [200]:
            map_error(status_code=response.status_code, response=response, error_map=error_map)
            error = self._deserialize.failsafe_deserialize(_models.ErrorResponse, pipeline_response)
            raise HttpResponseError(response=response, model=error, error_format=ARMErrorFormat)

        deserialized = self._deserialize("Invoice", pipeline_response.http_response)

        if cls:
            return cls(pipeline_response, deserialized, {})  # type: ignore

        return deserialized  # type: ignore

    @distributed_trace
    def list_by_billing_account(
        self,
        billing_account_name: str,
        period_start_date: Optional[datetime.date] = None,
        period_end_date: Optional[datetime.date] = None,
        filter: Optional[str] = None,
        order_by: Optional[str] = None,
        top: Optional[int] = None,
        skip: Optional[int] = None,
        count: Optional[bool] = None,
        search: Optional[str] = None,
        **kwargs: Any
    ) -> AsyncIterable["_models.Invoice"]:
        """Lists the invoices for a billing account for a given start date and end date. The operation is
        supported for all billing account types.

        .. seealso::
           - https://docs.microsoft.com/en-us/rest/api/billing/

        :param billing_account_name: The ID that uniquely identifies a billing account. Required.
        :type billing_account_name: str
        :param period_start_date: The start date of the billing period for which the invoice is
         generated. The date is in MM-DD-YYYY format. Default value is None.
        :type period_start_date: ~datetime.date
        :param period_end_date: The end date of the billing period for which the invoice is generated.
         The date is in MM-DD-YYYY format. Default value is None.
        :type period_end_date: ~datetime.date
        :param filter: The filter query option allows clients to filter a collection of resources that
         are addressed by a request URL. Default value is None.
        :type filter: str
        :param order_by: The orderby query option allows clients to request resources in a particular
         order. Default value is None.
        :type order_by: str
        :param top: The top query option requests the number of items in the queried collection to be
         included in the result. The maximum supported value for top is 50. Default value is None.
        :type top: int
        :param skip: The skip query option requests the number of items in the queried collection that
         are to be skipped and not included in the result. Default value is None.
        :type skip: int
        :param count: The count query option allows clients to request a count of the matching
         resources included with the resources in the response. Default value is None.
        :type count: bool
        :param search: The search query option allows clients to request items within a collection
         matching a free-text search expression. search is only supported for string fields. Default
         value is None.
        :type search: str
        :return: An iterator like instance of either Invoice or the result of cls(response)
        :rtype: ~azure.core.async_paging.AsyncItemPaged[~azure.mgmt.billing.models.Invoice]
        :raises ~azure.core.exceptions.HttpResponseError:
        """
        _headers = kwargs.pop("headers", {}) or {}
        _params = case_insensitive_dict(kwargs.pop("params", {}) or {})

        api_version: str = kwargs.pop("api_version", _params.pop("api-version", self._config.api_version))
        cls: ClsType[_models.InvoiceListResult] = kwargs.pop("cls", None)

        error_map: MutableMapping[int, Type[HttpResponseError]] = {
            401: ClientAuthenticationError,
            404: ResourceNotFoundError,
            409: ResourceExistsError,
            304: ResourceNotModifiedError,
        }
        error_map.update(kwargs.pop("error_map", {}) or {})

        def prepare_request(next_link=None):
            if not next_link:

                _request = build_list_by_billing_account_request(
                    billing_account_name=billing_account_name,
                    period_start_date=period_start_date,
                    period_end_date=period_end_date,
                    filter=filter,
                    order_by=order_by,
                    top=top,
                    skip=skip,
                    count=count,
                    search=search,
                    api_version=api_version,
                    headers=_headers,
                    params=_params,
                )
                _request.url = self._client.format_url(_request.url)

            else:
                # make call to next link with the client's api-version
                _parsed_next_link = urllib.parse.urlparse(next_link)
                _next_request_params = case_insensitive_dict(
                    {
                        key: [urllib.parse.quote(v) for v in value]
                        for key, value in urllib.parse.parse_qs(_parsed_next_link.query).items()
                    }
                )
                _next_request_params["api-version"] = self._config.api_version
                _request = HttpRequest(
                    "GET", urllib.parse.urljoin(next_link, _parsed_next_link.path), params=_next_request_params
                )
                _request.url = self._client.format_url(_request.url)
                _request.method = "GET"
            return _request

        async def extract_data(pipeline_response):
            deserialized = self._deserialize("InvoiceListResult", pipeline_response)
            list_of_elem = deserialized.value
            if cls:
                list_of_elem = cls(list_of_elem)  # type: ignore
            return deserialized.next_link or None, AsyncList(list_of_elem)

        async def get_next(next_link=None):
            _request = prepare_request(next_link)

            _stream = False
            pipeline_response: PipelineResponse = await self._client._pipeline.run(  # pylint: disable=protected-access
                _request, stream=_stream, **kwargs
            )
            response = pipeline_response.http_response

            if response.status_code not in [200]:
                map_error(status_code=response.status_code, response=response, error_map=error_map)
                error = self._deserialize.failsafe_deserialize(_models.ErrorResponse, pipeline_response)
                raise HttpResponseError(response=response, model=error, error_format=ARMErrorFormat)

            return pipeline_response

        return AsyncItemPaged(get_next, extract_data)

    async def _download_documents_by_billing_subscription_initial(  # pylint: disable=name-too-long
        self, parameters: Union[List[_models.DocumentDownloadRequest], IO[bytes]], **kwargs: Any
    ) -> AsyncIterator[bytes]:
        error_map: MutableMapping[int, Type[HttpResponseError]] = {
            401: ClientAuthenticationError,
            404: ResourceNotFoundError,
            409: ResourceExistsError,
            304: ResourceNotModifiedError,
        }
        error_map.update(kwargs.pop("error_map", {}) or {})

        _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {})
        _params = case_insensitive_dict(kwargs.pop("params", {}) or {})

        api_version: str = kwargs.pop("api_version", _params.pop("api-version", self._config.api_version))
        content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None))
        cls: ClsType[AsyncIterator[bytes]] = kwargs.pop("cls", None)

        content_type = content_type or "application/json"
        _json = None
        _content = None
        if isinstance(parameters, (IOBase, bytes)):
            _content = parameters
        else:
            _json = self._serialize.body(parameters, "[DocumentDownloadRequest]")

        _request = build_download_documents_by_billing_subscription_request(
            subscription_id=self._config.subscription_id,
            api_version=api_version,
            content_type=content_type,
            json=_json,
            content=_content,
            headers=_headers,
            params=_params,
        )
        _request.url = self._client.format_url(_request.url)

        _decompress = kwargs.pop("decompress", True)
        _stream = True
        pipeline_response: PipelineResponse = await self._client._pipeline.run(  # pylint: disable=protected-access
            _request, stream=_stream, **kwargs
        )

        response = pipeline_response.http_response

        if response.status_code not in [200, 202]:
            try:
                await response.read()  # Load the body in memory and close the socket
            except (StreamConsumedError, StreamClosedError):
                pass
            map_error(status_code=response.status_code, response=response, error_map=error_map)
            error = self._deserialize.failsafe_deserialize(_models.ErrorResponse, pipeline_response)
            raise HttpResponseError(response=response, model=error, error_format=ARMErrorFormat)

        response_headers = {}
        if response.status_code == 202:
            response_headers["Location"] = self._deserialize("str", response.headers.get("Location"))
            response_headers["Retry-After"] = self._deserialize("int", response.headers.get("Retry-After"))

        deserialized = response.stream_download(self._client._pipeline, decompress=_decompress)

        if cls:
            return cls(pipeline_response, deserialized, response_headers)  # type: ignore

        return deserialized  # type: ignore

    @overload
    async def begin_download_documents_by_billing_subscription(  # pylint: disable=name-too-long
        self,
        parameters: List[_models.DocumentDownloadRequest],
        *,
        content_type: str = "application/json",
        **kwargs: Any
    ) -> AsyncLROPoller[_models.DocumentDownloadResult]:
        """Gets a URL to download multiple invoice documents (invoice pdf, tax receipts, credit notes) as
        a zip file. The operation is supported for billing accounts with agreement type Microsoft
        Partner Agreement or Microsoft Customer Agreement.

        .. seealso::
           - https://docs.microsoft.com/en-us/rest/api/billing/

        :param parameters: A list of download details for individual documents. Required.
        :type parameters: list[~azure.mgmt.billing.models.DocumentDownloadRequest]
        :keyword content_type: Body Parameter content-type. Content type parameter for JSON body.
         Default value is "application/json".
        :paramtype content_type: str
        :return: An instance of AsyncLROPoller that returns either DocumentDownloadResult or the result
         of cls(response)
        :rtype: ~azure.core.polling.AsyncLROPoller[~azure.mgmt.billing.models.DocumentDownloadResult]
        :raises ~azure.core.exceptions.HttpResponseError:
        """

    @overload
    async def begin_download_documents_by_billing_subscription(  # pylint: disable=name-too-long
        self, parameters: IO[bytes], *, content_type: str = "application/json", **kwargs: Any
    ) -> AsyncLROPoller[_models.DocumentDownloadResult]:
        """Gets a URL to download multiple invoice documents (invoice pdf, tax receipts, credit notes) as
        a zip file. The operation is supported for billing accounts with agreement type Microsoft
        Partner Agreement or Microsoft Customer Agreement.

        .. seealso::
           - https://docs.microsoft.com/en-us/rest/api/billing/

        :param parameters: A list of download details for individual documents. Required.
        :type parameters: IO[bytes]
        :keyword content_type: Body Parameter content-type. Content type parameter for binary body.
         Default value is "application/json".
        :paramtype content_type: str
        :return: An instance of AsyncLROPoller that returns either DocumentDownloadResult or the result
         of cls(response)
        :rtype: ~azure.core.polling.AsyncLROPoller[~azure.mgmt.billing.models.DocumentDownloadResult]
        :raises ~azure.core.exceptions.HttpResponseError:
        """

    @distributed_trace_async
    async def begin_download_documents_by_billing_subscription(  # pylint: disable=name-too-long
        self, parameters: Union[List[_models.DocumentDownloadRequest], IO[bytes]], **kwargs: Any
    ) -> AsyncLROPoller[_models.DocumentDownloadResult]:
        """Gets a URL to download multiple invoice documents (invoice pdf, tax receipts, credit notes) as
        a zip file. The operation is supported for billing accounts with agreement type Microsoft
        Partner Agreement or Microsoft Customer Agreement.

        .. seealso::
           - https://docs.microsoft.com/en-us/rest/api/billing/

        :param parameters: A list of download details for individual documents. Is either a
         [DocumentDownloadRequest] type or a IO[bytes] type. Required.
        :type parameters: list[~azure.mgmt.billing.models.DocumentDownloadRequest] or IO[bytes]
        :return: An instance of AsyncLROPoller that returns either DocumentDownloadResult or the result
         of cls(response)
        :rtype: ~azure.core.polling.AsyncLROPoller[~azure.mgmt.billing.models.DocumentDownloadResult]
        :raises ~azure.core.exceptions.HttpResponseError:
        """
        _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {})
        _params = case_insensitive_dict(kwargs.pop("params", {}) or {})

        api_version: str = kwargs.pop("api_version", _params.pop("api-version", self._config.api_version))
        content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None))
        cls: ClsType[_models.DocumentDownloadResult] = kwargs.pop("cls", None)
        polling: Union[bool, AsyncPollingMethod] = kwargs.pop("polling", True)
        lro_delay = kwargs.pop("polling_interval", self._config.polling_interval)
        cont_token: Optional[str] = kwargs.pop("continuation_token", None)
        if cont_token is None:
            raw_result = await self._download_documents_by_billing_subscription_initial(
                parameters=parameters,
                api_version=api_version,
                content_type=content_type,
                cls=lambda x, y, z: x,
                headers=_headers,
                params=_params,
                **kwargs
            )
            await raw_result.http_response.read()  # type: ignore
        kwargs.pop("error_map", None)

        def get_long_running_output(pipeline_response):
            deserialized = self._deserialize("DocumentDownloadResult", pipeline_response.http_response)
            if cls:
                return cls(pipeline_response, deserialized, {})  # type: ignore
            return deserialized

        if polling is True:
            polling_method: AsyncPollingMethod = cast(
                AsyncPollingMethod, AsyncARMPolling(lro_delay, lro_options={"final-state-via": "location"}, **kwargs)
            )
        elif polling is False:
            polling_method = cast(AsyncPollingMethod, AsyncNoPolling())
        else:
            polling_method = polling
        if cont_token:
            return AsyncLROPoller[_models.DocumentDownloadResult].from_continuation_token(
                polling_method=polling_method,
                continuation_token=cont_token,
                client=self._client,
                deserialization_callback=get_long_running_output,
            )
        return AsyncLROPoller[_models.DocumentDownloadResult](
            self._client, raw_result, get_long_running_output, polling_method  # type: ignore
        )

    async def _download_by_billing_subscription_initial(  # pylint: disable=name-too-long
        self, invoice_name: str, document_name: Optional[str] = None, **kwargs: Any
    ) -> AsyncIterator[bytes]:
        error_map: MutableMapping[int, Type[HttpResponseError]] = {
            401: ClientAuthenticationError,
            404: ResourceNotFoundError,
            409: ResourceExistsError,
            304: ResourceNotModifiedError,
        }
        error_map.update(kwargs.pop("error_map", {}) or {})

        _headers = kwargs.pop("headers", {}) or {}
        _params = case_insensitive_dict(kwargs.pop("params", {}) or {})

        api_version: str = kwargs.pop("api_version", _params.pop("api-version", self._config.api_version))
        cls: ClsType[AsyncIterator[bytes]] = kwargs.pop("cls", None)

        _request = build_download_by_billing_subscription_request(
            invoice_name=invoice_name,
            subscription_id=self._config.subscription_id,
            document_name=document_name,
            api_version=api_version,
            headers=_headers,
            params=_params,
        )
        _request.url = self._client.format_url(_request.url)

        _decompress = kwargs.pop("decompress", True)
        _stream = True
        pipeline_response: PipelineResponse = await self._client._pipeline.run(  # pylint: disable=protected-access
            _request, stream=_stream, **kwargs
        )

        response = pipeline_response.http_response

        if response.status_code not in [200, 202]:
            try:
                await response.read()  # Load the body in memory and close the socket
            except (StreamConsumedError, StreamClosedError):
                pass
            map_error(status_code=response.status_code, response=response, error_map=error_map)
            error = self._deserialize.failsafe_deserialize(_models.ErrorResponse, pipeline_response)
            raise HttpResponseError(response=response, model=error, error_format=ARMErrorFormat)

        response_headers = {}
        if response.status_code == 202:
            response_headers["Location"] = self._deserialize("str", response.headers.get("Location"))
            response_headers["Retry-After"] = self._deserialize("int", response.headers.get("Retry-After"))

        deserialized = response.stream_download(self._client._pipeline, decompress=_decompress)

        if cls:
            return cls(pipeline_response, deserialized, response_headers)  # type: ignore

        return deserialized  # type: ignore

    @distributed_trace_async
    async def begin_download_by_billing_subscription(
        self, invoice_name: str, document_name: Optional[str] = None, **kwargs: Any
    ) -> AsyncLROPoller[_models.DocumentDownloadResult]:
        """Gets a URL to download an invoice by billing subscription. The operation is supported for
        billing accounts with agreement type Microsoft Partner Agreement or Microsoft Customer
        Agreement.

        .. seealso::
           - https://docs.microsoft.com/en-us/rest/api/billing/

        :param invoice_name: The ID that uniquely identifies an invoice. Required.
        :type invoice_name: str
        :param document_name: The ID that uniquely identifies an invoice document. This ID may be an
         identifier for an invoice PDF, a credit note, or a tax receipt. Default value is None.
        :type document_name: str
        :return: An instance of AsyncLROPoller that returns either DocumentDownloadResult or the result
         of cls(response)
        :rtype: ~azure.core.polling.AsyncLROPoller[~azure.mgmt.billing.models.DocumentDownloadResult]
        :raises ~azure.core.exceptions.HttpResponseError:
        """
        _headers = kwargs.pop("headers", {}) or {}
        _params = case_insensitive_dict(kwargs.pop("params", {}) or {})

        api_version: str = kwargs.pop("api_version", _params.pop("api-version", self._config.api_version))
        cls: ClsType[_models.DocumentDownloadResult] = kwargs.pop("cls", None)
        polling: Union[bool, AsyncPollingMethod] = kwargs.pop("polling", True)
        lro_delay = kwargs.pop("polling_interval", self._config.polling_interval)
        cont_token: Optional[str] = kwargs.pop("continuation_token", None)
        if cont_token is None:
            raw_result = await self._download_by_billing_subscription_initial(
                invoice_name=invoice_name,
                document_name=document_name,
                api_version=api_version,
                cls=lambda x, y, z: x,
                headers=_headers,
                params=_params,
                **kwargs
            )
            await raw_result.http_response.read()  # type: ignore
        kwargs.pop("error_map", None)

        def get_long_running_output(pipeline_response):
            deserialized = self._deserialize("DocumentDownloadResult", pipeline_response.http_response)
            if cls:
                return cls(pipeline_response, deserialized, {})  # type: ignore
            return deserialized

        if polling is True:
            polling_method: AsyncPollingMethod = cast(
                AsyncPollingMethod, AsyncARMPolling(lro_delay, lro_options={"final-state-via": "location"}, **kwargs)
            )
        elif polling is False:
            polling_method = cast(AsyncPollingMethod, AsyncNoPolling())
        else:
            polling_method = polling
        if cont_token:
            return AsyncLROPoller[_models.DocumentDownloadResult].from_continuation_token(
                polling_method=polling_method,
                continuation_token=cont_token,
                client=self._client,
                deserialization_callback=get_long_running_output,
            )
        return AsyncLROPoller[_models.DocumentDownloadResult](
            self._client, raw_result, get_long_running_output, polling_method  # type: ignore
        )

    @distributed_trace_async
    async def get_by_billing_subscription(self, invoice_name: str, **kwargs: Any) -> _models.Invoice:
        """Gets an invoice by subscription ID and invoice ID. The operation is supported for billing
        accounts with agreement type Microsoft Partner Agreement or Microsoft Customer Agreement.

        .. seealso::
           - https://docs.microsoft.com/en-us/rest/api/billing/

        :param invoice_name: The ID that uniquely identifies an invoice. Required.
        :type invoice_name: str
        :return: Invoice or the result of cls(response)
        :rtype: ~azure.mgmt.billing.models.Invoice
        :raises ~azure.core.exceptions.HttpResponseError:
        """
        error_map: MutableMapping[int, Type[HttpResponseError]] = {
            401: ClientAuthenticationError,
            404: ResourceNotFoundError,
            409: ResourceExistsError,
            304: ResourceNotModifiedError,
        }
        error_map.update(kwargs.pop("error_map", {}) or {})

        _headers = kwargs.pop("headers", {}) or {}
        _params = case_insensitive_dict(kwargs.pop("params", {}) or {})

        api_version: str = kwargs.pop("api_version", _params.pop("api-version", self._config.api_version))
        cls: ClsType[_models.Invoice] = kwargs.pop("cls", None)

        _request = build_get_by_billing_subscription_request(
            invoice_name=invoice_name,
            subscription_id=self._config.subscription_id,
            api_version=api_version,
            headers=_headers,
            params=_params,
        )
        _request.url = self._client.format_url(_request.url)

        _stream = False
        pipeline_response: PipelineResponse = await self._client._pipeline.run(  # pylint: disable=protected-access
            _request, stream=_stream, **kwargs
        )

        response = pipeline_response.http_response

        if response.status_code not in [200]:
            map_error(status_code=response.status_code, response=response, error_map=error_map)
            error = self._deserialize.failsafe_deserialize(_models.ErrorResponse, pipeline_response)
            raise HttpResponseError(response=response, model=error, error_format=ARMErrorFormat)

        deserialized = self._deserialize("Invoice", pipeline_response.http_response)

        if cls:
            return cls(pipeline_response, deserialized, {})  # type: ignore

        return deserialized  # type: ignore

    @distributed_trace
    def list_by_billing_subscription(
        self,
        period_start_date: Optional[datetime.date] = None,
        period_end_date: Optional[datetime.date] = None,
        filter: Optional[str] = None,
        order_by: Optional[str] = None,
        top: Optional[int] = None,
        skip: Optional[int] = None,
        count: Optional[bool] = None,
        search: Optional[str] = None,
        **kwargs: Any
    ) -> AsyncIterable["_models.Invoice"]:
        """Lists the invoices for a subscription. The operation is supported for billing accounts with
        agreement type Microsoft Partner Agreement or Microsoft Customer Agreement.

        .. seealso::
           - https://docs.microsoft.com/en-us/rest/api/billing/

        :param period_start_date: The start date of the billing period for which the invoice is
         generated. The date is in MM-DD-YYYY format. Default value is None.
        :type period_start_date: ~datetime.date
        :param period_end_date: The end date of the billing period for which the invoice is generated.
         The date is in MM-DD-YYYY format. Default value is None.
        :type period_end_date: ~datetime.date
        :param filter: The filter query option allows clients to filter a collection of resources that
         are addressed by a request URL. Default value is None.
        :type filter: str
        :param order_by: The orderby query option allows clients to request resources in a particular
         order. Default value is None.
        :type order_by: str
        :param top: The top query option requests the number of items in the queried collection to be
         included in the result. The maximum supported value for top is 50. Default value is None.
        :type top: int
        :param skip: The skip query option requests the number of items in the queried collection that
         are to be skipped and not included in the result. Default value is None.
        :type skip: int
        :param count: The count query option allows clients to request a count of the matching
         resources included with the resources in the response. Default value is None.
        :type count: bool
        :param search: The search query option allows clients to request items within a collection
         matching a free-text search expression. search is only supported for string fields. Default
         value is None.
        :type search: str
        :return: An iterator like instance of either Invoice or the result of cls(response)
        :rtype: ~azure.core.async_paging.AsyncItemPaged[~azure.mgmt.billing.models.Invoice]
        :raises ~azure.core.exceptions.HttpResponseError:
        """
        _headers = kwargs.pop("headers", {}) or {}
        _params = case_insensitive_dict(kwargs.pop("params", {}) or {})

        api_version: str = kwargs.pop("api_version", _params.pop("api-version", self._config.api_version))
        cls: ClsType[_models.InvoiceListResult] = kwargs.pop("cls", None)

        error_map: MutableMapping[int, Type[HttpResponseError]] = {
            401: ClientAuthenticationError,
            404: ResourceNotFoundError,
            409: ResourceExistsError,
            304: ResourceNotModifiedError,
        }
        error_map.update(kwargs.pop("error_map", {}) or {})

        def prepare_request(next_link=None):
            if not next_link:

                _request = build_list_by_billing_subscription_request(
                    subscription_id=self._config.subscription_id,
                    period_start_date=period_start_date,
                    period_end_date=period_end_date,
                    filter=filter,
                    order_by=order_by,
                    top=top,
                    skip=skip,
                    count=count,
                    search=search,
                    api_version=api_version,
                    headers=_headers,
                    params=_params,
                )
                _request.url = self._client.format_url(_request.url)

            else:
                # make call to next link with the client's api-version
                _parsed_next_link = urllib.parse.urlparse(next_link)
                _next_request_params = case_insensitive_dict(
                    {
                        key: [urllib.parse.quote(v) for v in value]
                        for key, value in urllib.parse.parse_qs(_parsed_next_link.query).items()
                    }
                )
                _next_request_params["api-version"] = self._config.api_version
                _request = HttpRequest(
                    "GET", urllib.parse.urljoin(next_link, _parsed_next_link.path), params=_next_request_params
                )
                _request.url = self._client.format_url(_request.url)
                _request.method = "GET"
            return _request

        async def extract_data(pipeline_response):
            deserialized = self._deserialize("InvoiceListResult", pipeline_response)
            list_of_elem = deserialized.value
            if cls:
                list_of_elem = cls(list_of_elem)  # type: ignore
            return deserialized.next_link or None, AsyncList(list_of_elem)

        async def get_next(next_link=None):
            _request = prepare_request(next_link)

            _stream = False
            pipeline_response: PipelineResponse = await self._client._pipeline.run(  # pylint: disable=protected-access
                _request, stream=_stream, **kwargs
            )
            response = pipeline_response.http_response

            if response.status_code not in [200]:
                map_error(status_code=response.status_code, response=response, error_map=error_map)
                error = self._deserialize.failsafe_deserialize(_models.ErrorResponse, pipeline_response)
                raise HttpResponseError(response=response, model=error, error_format=ARMErrorFormat)

            return pipeline_response

        return AsyncItemPaged(get_next, extract_data)

    @distributed_trace_async
    async def get(self, invoice_name: str, **kwargs: Any) -> _models.Invoice:
        """Gets an invoice by ID. The operation is supported for billing accounts with agreement type
        Microsoft Partner Agreement or Microsoft Customer Agreement.

        .. seealso::
           - https://docs.microsoft.com/en-us/rest/api/billing/

        :param invoice_name: The ID that uniquely identifies an invoice. Required.
        :type invoice_name: str
        :return: Invoice or the result of cls(response)
        :rtype: ~azure.mgmt.billing.models.Invoice
        :raises ~azure.core.exceptions.HttpResponseError:
        """
        error_map: MutableMapping[int, Type[HttpResponseError]] = {
            401: ClientAuthenticationError,
            404: ResourceNotFoundError,
            409: ResourceExistsError,
            304: ResourceNotModifiedError,
        }
        error_map.update(kwargs.pop("error_map", {}) or {})

        _headers = kwargs.pop("headers", {}) or {}
        _params = case_insensitive_dict(kwargs.pop("params", {}) or {})

        api_version: str = kwargs.pop("api_version", _params.pop("api-version", self._config.api_version))
        cls: ClsType[_models.Invoice] = kwargs.pop("cls", None)

        _request = build_get_request(
            invoice_name=invoice_name,
            api_version=api_version,
            headers=_headers,
            params=_params,
        )
        _request.url = self._client.format_url(_request.url)

        _stream = False
        pipeline_response: PipelineResponse = await self._client._pipeline.run(  # pylint: disable=protected-access
            _request, stream=_stream, **kwargs
        )

        response = pipeline_response.http_response

        if response.status_code not in [200]:
            map_error(status_code=response.status_code, response=response, error_map=error_map)
            error = self._deserialize.failsafe_deserialize(_models.ErrorResponse, pipeline_response)
            raise HttpResponseError(response=response, model=error, error_format=ARMErrorFormat)

        deserialized = self._deserialize("Invoice", pipeline_response.http_response)

        if cls:
            return cls(pipeline_response, deserialized, {})  # type: ignore

        return deserialized  # type: ignore
