# pylint: disable=too-many-lines
# 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 sys
from typing import Any, AsyncIterable, Callable, Dict, IO, Optional, TypeVar, Union, overload
import urllib.parse

from azure.core.async_paging import AsyncItemPaged, AsyncList
from azure.core.exceptions import (
    ClientAuthenticationError,
    HttpResponseError,
    ResourceExistsError,
    ResourceNotFoundError,
    ResourceNotModifiedError,
    map_error,
)
from azure.core.pipeline import PipelineResponse
from azure.core.pipeline.transport import AsyncHttpResponse
from azure.core.rest import 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 ... import models as _models
from ..._vendor import _convert_request
from ...operations._key_vault_client_operations import (
    build_backup_secret_request,
    build_delete_secret_request,
    build_get_deleted_secret_request,
    build_get_deleted_secrets_request,
    build_get_secret_request,
    build_get_secret_versions_request,
    build_get_secrets_request,
    build_purge_deleted_secret_request,
    build_recover_deleted_secret_request,
    build_restore_secret_request,
    build_set_secret_request,
    build_update_secret_request,
)
from .._vendor import KeyVaultClientMixinABC

if sys.version_info >= (3, 8):
    from typing import Literal  # pylint: disable=no-name-in-module, ungrouped-imports
else:
    from typing_extensions import Literal  # type: ignore  # pylint: disable=ungrouped-imports
T = TypeVar("T")
ClsType = Optional[Callable[[PipelineResponse[HttpRequest, AsyncHttpResponse], T, Dict[str, Any]], Any]]


class KeyVaultClientOperationsMixin(KeyVaultClientMixinABC):
    @overload
    async def set_secret(
        self,
        vault_base_url: str,
        secret_name: str,
        parameters: _models.SecretSetParameters,
        *,
        content_type: str = "application/json",
        **kwargs: Any
    ) -> _models.SecretBundle:
        """Sets a secret in a specified key vault.

        The SET operation adds a secret to the Azure Key Vault. If the named secret already exists,
        Azure Key Vault creates a new version of that secret. This operation requires the secrets/set
        permission.

        :param vault_base_url: The vault name, for example https://myvault.vault.azure.net. Required.
        :type vault_base_url: str
        :param secret_name: The name of the secret. Required.
        :type secret_name: str
        :param parameters: The parameters for setting the secret. Required.
        :type parameters: ~azure.keyvault.v7_1.models.SecretSetParameters
        :keyword content_type: Body Parameter content-type. Content type parameter for JSON body.
         Default value is "application/json".
        :paramtype content_type: str
        :keyword callable cls: A custom type or function that will be passed the direct response
        :return: SecretBundle or the result of cls(response)
        :rtype: ~azure.keyvault.v7_1.models.SecretBundle
        :raises ~azure.core.exceptions.HttpResponseError:
        """

    @overload
    async def set_secret(
        self,
        vault_base_url: str,
        secret_name: str,
        parameters: IO,
        *,
        content_type: str = "application/json",
        **kwargs: Any
    ) -> _models.SecretBundle:
        """Sets a secret in a specified key vault.

        The SET operation adds a secret to the Azure Key Vault. If the named secret already exists,
        Azure Key Vault creates a new version of that secret. This operation requires the secrets/set
        permission.

        :param vault_base_url: The vault name, for example https://myvault.vault.azure.net. Required.
        :type vault_base_url: str
        :param secret_name: The name of the secret. Required.
        :type secret_name: str
        :param parameters: The parameters for setting the secret. Required.
        :type parameters: IO
        :keyword content_type: Body Parameter content-type. Content type parameter for binary body.
         Default value is "application/json".
        :paramtype content_type: str
        :keyword callable cls: A custom type or function that will be passed the direct response
        :return: SecretBundle or the result of cls(response)
        :rtype: ~azure.keyvault.v7_1.models.SecretBundle
        :raises ~azure.core.exceptions.HttpResponseError:
        """

    @distributed_trace_async
    async def set_secret(
        self, vault_base_url: str, secret_name: str, parameters: Union[_models.SecretSetParameters, IO], **kwargs: Any
    ) -> _models.SecretBundle:
        """Sets a secret in a specified key vault.

        The SET operation adds a secret to the Azure Key Vault. If the named secret already exists,
        Azure Key Vault creates a new version of that secret. This operation requires the secrets/set
        permission.

        :param vault_base_url: The vault name, for example https://myvault.vault.azure.net. Required.
        :type vault_base_url: str
        :param secret_name: The name of the secret. Required.
        :type secret_name: str
        :param parameters: The parameters for setting the secret. Is either a SecretSetParameters type
         or a IO type. Required.
        :type parameters: ~azure.keyvault.v7_1.models.SecretSetParameters or IO
        :keyword content_type: Body Parameter content-type. Known values are: 'application/json'.
         Default value is None.
        :paramtype content_type: str
        :keyword callable cls: A custom type or function that will be passed the direct response
        :return: SecretBundle or the result of cls(response)
        :rtype: ~azure.keyvault.v7_1.models.SecretBundle
        :raises ~azure.core.exceptions.HttpResponseError:
        """
        error_map = {
            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: Literal["7.1"] = kwargs.pop("api_version", _params.pop("api-version", "7.1"))
        content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None))
        cls: ClsType[_models.SecretBundle] = kwargs.pop("cls", None)

        content_type = content_type or "application/json"
        _json = None
        _content = None
        if isinstance(parameters, (IO, bytes)):
            _content = parameters
        else:
            _json = self._serialize.body(parameters, "SecretSetParameters")

        request = build_set_secret_request(
            secret_name=secret_name,
            api_version=api_version,
            content_type=content_type,
            json=_json,
            content=_content,
            template_url=self.set_secret.metadata["url"],
            headers=_headers,
            params=_params,
        )
        request = _convert_request(request)
        path_format_arguments = {
            "vaultBaseUrl": self._serialize.url("vault_base_url", vault_base_url, "str", skip_quote=True),
        }
        request.url = self._client.format_url(request.url, **path_format_arguments)

        pipeline_response: PipelineResponse = await self._client._pipeline.run(  # type: ignore # pylint: disable=protected-access
            request, stream=False, **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.KeyVaultError, pipeline_response)
            raise HttpResponseError(response=response, model=error)

        deserialized = self._deserialize("SecretBundle", pipeline_response)

        if cls:
            return cls(pipeline_response, deserialized, {})

        return deserialized

    set_secret.metadata = {"url": "/secrets/{secret-name}"}

    @distributed_trace_async
    async def delete_secret(self, vault_base_url: str, secret_name: str, **kwargs: Any) -> _models.DeletedSecretBundle:
        """Deletes a secret from a specified key vault.

        The DELETE operation applies to any secret stored in Azure Key Vault. DELETE cannot be applied
        to an individual version of a secret. This operation requires the secrets/delete permission.

        :param vault_base_url: The vault name, for example https://myvault.vault.azure.net. Required.
        :type vault_base_url: str
        :param secret_name: The name of the secret. Required.
        :type secret_name: str
        :keyword callable cls: A custom type or function that will be passed the direct response
        :return: DeletedSecretBundle or the result of cls(response)
        :rtype: ~azure.keyvault.v7_1.models.DeletedSecretBundle
        :raises ~azure.core.exceptions.HttpResponseError:
        """
        error_map = {
            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: Literal["7.1"] = kwargs.pop("api_version", _params.pop("api-version", "7.1"))
        cls: ClsType[_models.DeletedSecretBundle] = kwargs.pop("cls", None)

        request = build_delete_secret_request(
            secret_name=secret_name,
            api_version=api_version,
            template_url=self.delete_secret.metadata["url"],
            headers=_headers,
            params=_params,
        )
        request = _convert_request(request)
        path_format_arguments = {
            "vaultBaseUrl": self._serialize.url("vault_base_url", vault_base_url, "str", skip_quote=True),
        }
        request.url = self._client.format_url(request.url, **path_format_arguments)

        pipeline_response: PipelineResponse = await self._client._pipeline.run(  # type: ignore # pylint: disable=protected-access
            request, stream=False, **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.KeyVaultError, pipeline_response)
            raise HttpResponseError(response=response, model=error)

        deserialized = self._deserialize("DeletedSecretBundle", pipeline_response)

        if cls:
            return cls(pipeline_response, deserialized, {})

        return deserialized

    delete_secret.metadata = {"url": "/secrets/{secret-name}"}

    @overload
    async def update_secret(
        self,
        vault_base_url: str,
        secret_name: str,
        secret_version: str,
        parameters: _models.SecretUpdateParameters,
        *,
        content_type: str = "application/json",
        **kwargs: Any
    ) -> _models.SecretBundle:
        """Updates the attributes associated with a specified secret in a given key vault.

        The UPDATE operation changes specified attributes of an existing stored secret. Attributes that
        are not specified in the request are left unchanged. The value of a secret itself cannot be
        changed. This operation requires the secrets/set permission.

        :param vault_base_url: The vault name, for example https://myvault.vault.azure.net. Required.
        :type vault_base_url: str
        :param secret_name: The name of the secret. Required.
        :type secret_name: str
        :param secret_version: The version of the secret. Required.
        :type secret_version: str
        :param parameters: The parameters for update secret operation. Required.
        :type parameters: ~azure.keyvault.v7_1.models.SecretUpdateParameters
        :keyword content_type: Body Parameter content-type. Content type parameter for JSON body.
         Default value is "application/json".
        :paramtype content_type: str
        :keyword callable cls: A custom type or function that will be passed the direct response
        :return: SecretBundle or the result of cls(response)
        :rtype: ~azure.keyvault.v7_1.models.SecretBundle
        :raises ~azure.core.exceptions.HttpResponseError:
        """

    @overload
    async def update_secret(
        self,
        vault_base_url: str,
        secret_name: str,
        secret_version: str,
        parameters: IO,
        *,
        content_type: str = "application/json",
        **kwargs: Any
    ) -> _models.SecretBundle:
        """Updates the attributes associated with a specified secret in a given key vault.

        The UPDATE operation changes specified attributes of an existing stored secret. Attributes that
        are not specified in the request are left unchanged. The value of a secret itself cannot be
        changed. This operation requires the secrets/set permission.

        :param vault_base_url: The vault name, for example https://myvault.vault.azure.net. Required.
        :type vault_base_url: str
        :param secret_name: The name of the secret. Required.
        :type secret_name: str
        :param secret_version: The version of the secret. Required.
        :type secret_version: str
        :param parameters: The parameters for update secret operation. Required.
        :type parameters: IO
        :keyword content_type: Body Parameter content-type. Content type parameter for binary body.
         Default value is "application/json".
        :paramtype content_type: str
        :keyword callable cls: A custom type or function that will be passed the direct response
        :return: SecretBundle or the result of cls(response)
        :rtype: ~azure.keyvault.v7_1.models.SecretBundle
        :raises ~azure.core.exceptions.HttpResponseError:
        """

    @distributed_trace_async
    async def update_secret(
        self,
        vault_base_url: str,
        secret_name: str,
        secret_version: str,
        parameters: Union[_models.SecretUpdateParameters, IO],
        **kwargs: Any
    ) -> _models.SecretBundle:
        """Updates the attributes associated with a specified secret in a given key vault.

        The UPDATE operation changes specified attributes of an existing stored secret. Attributes that
        are not specified in the request are left unchanged. The value of a secret itself cannot be
        changed. This operation requires the secrets/set permission.

        :param vault_base_url: The vault name, for example https://myvault.vault.azure.net. Required.
        :type vault_base_url: str
        :param secret_name: The name of the secret. Required.
        :type secret_name: str
        :param secret_version: The version of the secret. Required.
        :type secret_version: str
        :param parameters: The parameters for update secret operation. Is either a
         SecretUpdateParameters type or a IO type. Required.
        :type parameters: ~azure.keyvault.v7_1.models.SecretUpdateParameters or IO
        :keyword content_type: Body Parameter content-type. Known values are: 'application/json'.
         Default value is None.
        :paramtype content_type: str
        :keyword callable cls: A custom type or function that will be passed the direct response
        :return: SecretBundle or the result of cls(response)
        :rtype: ~azure.keyvault.v7_1.models.SecretBundle
        :raises ~azure.core.exceptions.HttpResponseError:
        """
        error_map = {
            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: Literal["7.1"] = kwargs.pop("api_version", _params.pop("api-version", "7.1"))
        content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None))
        cls: ClsType[_models.SecretBundle] = kwargs.pop("cls", None)

        content_type = content_type or "application/json"
        _json = None
        _content = None
        if isinstance(parameters, (IO, bytes)):
            _content = parameters
        else:
            _json = self._serialize.body(parameters, "SecretUpdateParameters")

        request = build_update_secret_request(
            secret_name=secret_name,
            secret_version=secret_version,
            api_version=api_version,
            content_type=content_type,
            json=_json,
            content=_content,
            template_url=self.update_secret.metadata["url"],
            headers=_headers,
            params=_params,
        )
        request = _convert_request(request)
        path_format_arguments = {
            "vaultBaseUrl": self._serialize.url("vault_base_url", vault_base_url, "str", skip_quote=True),
        }
        request.url = self._client.format_url(request.url, **path_format_arguments)

        pipeline_response: PipelineResponse = await self._client._pipeline.run(  # type: ignore # pylint: disable=protected-access
            request, stream=False, **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.KeyVaultError, pipeline_response)
            raise HttpResponseError(response=response, model=error)

        deserialized = self._deserialize("SecretBundle", pipeline_response)

        if cls:
            return cls(pipeline_response, deserialized, {})

        return deserialized

    update_secret.metadata = {"url": "/secrets/{secret-name}/{secret-version}"}

    @distributed_trace_async
    async def get_secret(
        self, vault_base_url: str, secret_name: str, secret_version: str, **kwargs: Any
    ) -> _models.SecretBundle:
        """Get a specified secret from a given key vault.

        The GET operation is applicable to any secret stored in Azure Key Vault. This operation
        requires the secrets/get permission.

        :param vault_base_url: The vault name, for example https://myvault.vault.azure.net. Required.
        :type vault_base_url: str
        :param secret_name: The name of the secret. Required.
        :type secret_name: str
        :param secret_version: The version of the secret. This URI fragment is optional. If not
         specified, the latest version of the secret is returned. Required.
        :type secret_version: str
        :keyword callable cls: A custom type or function that will be passed the direct response
        :return: SecretBundle or the result of cls(response)
        :rtype: ~azure.keyvault.v7_1.models.SecretBundle
        :raises ~azure.core.exceptions.HttpResponseError:
        """
        error_map = {
            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: Literal["7.1"] = kwargs.pop("api_version", _params.pop("api-version", "7.1"))
        cls: ClsType[_models.SecretBundle] = kwargs.pop("cls", None)

        request = build_get_secret_request(
            secret_name=secret_name,
            secret_version=secret_version,
            api_version=api_version,
            template_url=self.get_secret.metadata["url"],
            headers=_headers,
            params=_params,
        )
        request = _convert_request(request)
        path_format_arguments = {
            "vaultBaseUrl": self._serialize.url("vault_base_url", vault_base_url, "str", skip_quote=True),
        }
        request.url = self._client.format_url(request.url, **path_format_arguments)

        pipeline_response: PipelineResponse = await self._client._pipeline.run(  # type: ignore # pylint: disable=protected-access
            request, stream=False, **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.KeyVaultError, pipeline_response)
            raise HttpResponseError(response=response, model=error)

        deserialized = self._deserialize("SecretBundle", pipeline_response)

        if cls:
            return cls(pipeline_response, deserialized, {})

        return deserialized

    get_secret.metadata = {"url": "/secrets/{secret-name}/{secret-version}"}

    @distributed_trace
    def get_secrets(
        self, vault_base_url: str, maxresults: Optional[int] = None, **kwargs: Any
    ) -> AsyncIterable["_models.SecretItem"]:
        """List secrets in a specified key vault.

        The Get Secrets operation is applicable to the entire vault. However, only the base secret
        identifier and its attributes are provided in the response. Individual secret versions are not
        listed in the response. This operation requires the secrets/list permission.

        :param vault_base_url: The vault name, for example https://myvault.vault.azure.net. Required.
        :type vault_base_url: str
        :param maxresults: Specifies the maximum number of results to return in a page. Setting
         maxresults to a value less than 1 or greater than 25 results in error response code 400 (Bad
         Request). If there are additional results to return, then the service returns a nextLink
         containing a skip token for pagination. In certain cases, the service might return fewer
         results than specified by maxresults (even 0 results) and also return a nextLink. Clients
         should not make any assumptions on the minimum number of results per page, and should enumerate
         all pages until the nextLink becomes null. Default value is None.
        :type maxresults: int
        :keyword callable cls: A custom type or function that will be passed the direct response
        :return: An iterator like instance of either SecretItem or the result of cls(response)
        :rtype: ~azure.core.async_paging.AsyncItemPaged[~azure.keyvault.v7_1.models.SecretItem]
        :raises ~azure.core.exceptions.HttpResponseError:
        """
        _headers = kwargs.pop("headers", {}) or {}
        _params = case_insensitive_dict(kwargs.pop("params", {}) or {})

        api_version: Literal["7.1"] = kwargs.pop("api_version", _params.pop("api-version", "7.1"))
        cls: ClsType[_models.SecretListResult] = kwargs.pop("cls", None)

        error_map = {
            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_get_secrets_request(
                    maxresults=maxresults,
                    api_version=api_version,
                    template_url=self.get_secrets.metadata["url"],
                    headers=_headers,
                    params=_params,
                )
                request = _convert_request(request)
                path_format_arguments = {
                    "vaultBaseUrl": self._serialize.url("vault_base_url", vault_base_url, "str", skip_quote=True),
                }
                request.url = self._client.format_url(request.url, **path_format_arguments)

            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 = _convert_request(request)
                path_format_arguments = {
                    "vaultBaseUrl": self._serialize.url("vault_base_url", vault_base_url, "str", skip_quote=True),
                }
                request.url = self._client.format_url(request.url, **path_format_arguments)
                request.method = "GET"
            return request

        async def extract_data(pipeline_response):
            deserialized = self._deserialize("SecretListResult", 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)

            pipeline_response: PipelineResponse = await self._client._pipeline.run(  # type: ignore # pylint: disable=protected-access
                request, stream=False, **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.KeyVaultError, pipeline_response)
                raise HttpResponseError(response=response, model=error)

            return pipeline_response

        return AsyncItemPaged(get_next, extract_data)

    get_secrets.metadata = {"url": "/secrets"}

    @distributed_trace
    def get_secret_versions(
        self, vault_base_url: str, secret_name: str, maxresults: Optional[int] = None, **kwargs: Any
    ) -> AsyncIterable["_models.SecretItem"]:
        """List all versions of the specified secret.

        The full secret identifier and attributes are provided in the response. No values are returned
        for the secrets. This operations requires the secrets/list permission.

        :param vault_base_url: The vault name, for example https://myvault.vault.azure.net. Required.
        :type vault_base_url: str
        :param secret_name: The name of the secret. Required.
        :type secret_name: str
        :param maxresults: Specifies the maximum number of results to return in a page. Setting
         maxresults to a value less than 1 or greater than 25 results in error response code 400 (Bad
         Request). If there are additional results to return, then the service returns a nextLink
         containing a skip token for pagination. In certain cases, the service might return fewer
         results than specified by maxresults (even 0 results) and also return a nextLink. Clients
         should not make any assumptions on the minimum number of results per page, and should enumerate
         all pages until the nextLink becomes null. Default value is None.
        :type maxresults: int
        :keyword callable cls: A custom type or function that will be passed the direct response
        :return: An iterator like instance of either SecretItem or the result of cls(response)
        :rtype: ~azure.core.async_paging.AsyncItemPaged[~azure.keyvault.v7_1.models.SecretItem]
        :raises ~azure.core.exceptions.HttpResponseError:
        """
        _headers = kwargs.pop("headers", {}) or {}
        _params = case_insensitive_dict(kwargs.pop("params", {}) or {})

        api_version: Literal["7.1"] = kwargs.pop("api_version", _params.pop("api-version", "7.1"))
        cls: ClsType[_models.SecretListResult] = kwargs.pop("cls", None)

        error_map = {
            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_get_secret_versions_request(
                    secret_name=secret_name,
                    maxresults=maxresults,
                    api_version=api_version,
                    template_url=self.get_secret_versions.metadata["url"],
                    headers=_headers,
                    params=_params,
                )
                request = _convert_request(request)
                path_format_arguments = {
                    "vaultBaseUrl": self._serialize.url("vault_base_url", vault_base_url, "str", skip_quote=True),
                }
                request.url = self._client.format_url(request.url, **path_format_arguments)

            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 = _convert_request(request)
                path_format_arguments = {
                    "vaultBaseUrl": self._serialize.url("vault_base_url", vault_base_url, "str", skip_quote=True),
                }
                request.url = self._client.format_url(request.url, **path_format_arguments)
                request.method = "GET"
            return request

        async def extract_data(pipeline_response):
            deserialized = self._deserialize("SecretListResult", 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)

            pipeline_response: PipelineResponse = await self._client._pipeline.run(  # type: ignore # pylint: disable=protected-access
                request, stream=False, **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.KeyVaultError, pipeline_response)
                raise HttpResponseError(response=response, model=error)

            return pipeline_response

        return AsyncItemPaged(get_next, extract_data)

    get_secret_versions.metadata = {"url": "/secrets/{secret-name}/versions"}

    @distributed_trace
    def get_deleted_secrets(
        self, vault_base_url: str, maxresults: Optional[int] = None, **kwargs: Any
    ) -> AsyncIterable["_models.DeletedSecretItem"]:
        """Lists deleted secrets for the specified vault.

        The Get Deleted Secrets operation returns the secrets that have been deleted for a vault
        enabled for soft-delete. This operation requires the secrets/list permission.

        :param vault_base_url: The vault name, for example https://myvault.vault.azure.net. Required.
        :type vault_base_url: str
        :param maxresults: Specifies the maximum number of results to return in a page. Setting
         maxresults to a value less than 1 or greater than 25 results in error response code 400 (Bad
         Request). If there are additional results to return, then the service returns a nextLink
         containing a skip token for pagination. In certain cases, the service might return fewer
         results than specified by maxresults (even 0 results) and also return a nextLink. Clients
         should not make any assumptions on the minimum number of results per page, and should enumerate
         all pages until the nextLink becomes null. Default value is None.
        :type maxresults: int
        :keyword callable cls: A custom type or function that will be passed the direct response
        :return: An iterator like instance of either DeletedSecretItem or the result of cls(response)
        :rtype: ~azure.core.async_paging.AsyncItemPaged[~azure.keyvault.v7_1.models.DeletedSecretItem]
        :raises ~azure.core.exceptions.HttpResponseError:
        """
        _headers = kwargs.pop("headers", {}) or {}
        _params = case_insensitive_dict(kwargs.pop("params", {}) or {})

        api_version: Literal["7.1"] = kwargs.pop("api_version", _params.pop("api-version", "7.1"))
        cls: ClsType[_models.DeletedSecretListResult] = kwargs.pop("cls", None)

        error_map = {
            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_get_deleted_secrets_request(
                    maxresults=maxresults,
                    api_version=api_version,
                    template_url=self.get_deleted_secrets.metadata["url"],
                    headers=_headers,
                    params=_params,
                )
                request = _convert_request(request)
                path_format_arguments = {
                    "vaultBaseUrl": self._serialize.url("vault_base_url", vault_base_url, "str", skip_quote=True),
                }
                request.url = self._client.format_url(request.url, **path_format_arguments)

            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 = _convert_request(request)
                path_format_arguments = {
                    "vaultBaseUrl": self._serialize.url("vault_base_url", vault_base_url, "str", skip_quote=True),
                }
                request.url = self._client.format_url(request.url, **path_format_arguments)
                request.method = "GET"
            return request

        async def extract_data(pipeline_response):
            deserialized = self._deserialize("DeletedSecretListResult", 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)

            pipeline_response: PipelineResponse = await self._client._pipeline.run(  # type: ignore # pylint: disable=protected-access
                request, stream=False, **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.KeyVaultError, pipeline_response)
                raise HttpResponseError(response=response, model=error)

            return pipeline_response

        return AsyncItemPaged(get_next, extract_data)

    get_deleted_secrets.metadata = {"url": "/deletedsecrets"}

    @distributed_trace_async
    async def get_deleted_secret(
        self, vault_base_url: str, secret_name: str, **kwargs: Any
    ) -> _models.DeletedSecretBundle:
        """Gets the specified deleted secret.

        The Get Deleted Secret operation returns the specified deleted secret along with its
        attributes. This operation requires the secrets/get permission.

        :param vault_base_url: The vault name, for example https://myvault.vault.azure.net. Required.
        :type vault_base_url: str
        :param secret_name: The name of the secret. Required.
        :type secret_name: str
        :keyword callable cls: A custom type or function that will be passed the direct response
        :return: DeletedSecretBundle or the result of cls(response)
        :rtype: ~azure.keyvault.v7_1.models.DeletedSecretBundle
        :raises ~azure.core.exceptions.HttpResponseError:
        """
        error_map = {
            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: Literal["7.1"] = kwargs.pop("api_version", _params.pop("api-version", "7.1"))
        cls: ClsType[_models.DeletedSecretBundle] = kwargs.pop("cls", None)

        request = build_get_deleted_secret_request(
            secret_name=secret_name,
            api_version=api_version,
            template_url=self.get_deleted_secret.metadata["url"],
            headers=_headers,
            params=_params,
        )
        request = _convert_request(request)
        path_format_arguments = {
            "vaultBaseUrl": self._serialize.url("vault_base_url", vault_base_url, "str", skip_quote=True),
        }
        request.url = self._client.format_url(request.url, **path_format_arguments)

        pipeline_response: PipelineResponse = await self._client._pipeline.run(  # type: ignore # pylint: disable=protected-access
            request, stream=False, **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.KeyVaultError, pipeline_response)
            raise HttpResponseError(response=response, model=error)

        deserialized = self._deserialize("DeletedSecretBundle", pipeline_response)

        if cls:
            return cls(pipeline_response, deserialized, {})

        return deserialized

    get_deleted_secret.metadata = {"url": "/deletedsecrets/{secret-name}"}

    @distributed_trace_async
    async def purge_deleted_secret(  # pylint: disable=inconsistent-return-statements
        self, vault_base_url: str, secret_name: str, **kwargs: Any
    ) -> None:
        """Permanently deletes the specified secret.

        The purge deleted secret operation removes the secret permanently, without the possibility of
        recovery. This operation can only be enabled on a soft-delete enabled vault. This operation
        requires the secrets/purge permission.

        :param vault_base_url: The vault name, for example https://myvault.vault.azure.net. Required.
        :type vault_base_url: str
        :param secret_name: The name of the secret. Required.
        :type secret_name: str
        :keyword callable cls: A custom type or function that will be passed the direct response
        :return: None or the result of cls(response)
        :rtype: None
        :raises ~azure.core.exceptions.HttpResponseError:
        """
        error_map = {
            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: Literal["7.1"] = kwargs.pop("api_version", _params.pop("api-version", "7.1"))
        cls: ClsType[None] = kwargs.pop("cls", None)

        request = build_purge_deleted_secret_request(
            secret_name=secret_name,
            api_version=api_version,
            template_url=self.purge_deleted_secret.metadata["url"],
            headers=_headers,
            params=_params,
        )
        request = _convert_request(request)
        path_format_arguments = {
            "vaultBaseUrl": self._serialize.url("vault_base_url", vault_base_url, "str", skip_quote=True),
        }
        request.url = self._client.format_url(request.url, **path_format_arguments)

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

        response = pipeline_response.http_response

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

        if cls:
            return cls(pipeline_response, None, {})

    purge_deleted_secret.metadata = {"url": "/deletedsecrets/{secret-name}"}

    @distributed_trace_async
    async def recover_deleted_secret(
        self, vault_base_url: str, secret_name: str, **kwargs: Any
    ) -> _models.SecretBundle:
        """Recovers the deleted secret to the latest version.

        Recovers the deleted secret in the specified vault. This operation can only be performed on a
        soft-delete enabled vault. This operation requires the secrets/recover permission.

        :param vault_base_url: The vault name, for example https://myvault.vault.azure.net. Required.
        :type vault_base_url: str
        :param secret_name: The name of the deleted secret. Required.
        :type secret_name: str
        :keyword callable cls: A custom type or function that will be passed the direct response
        :return: SecretBundle or the result of cls(response)
        :rtype: ~azure.keyvault.v7_1.models.SecretBundle
        :raises ~azure.core.exceptions.HttpResponseError:
        """
        error_map = {
            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: Literal["7.1"] = kwargs.pop("api_version", _params.pop("api-version", "7.1"))
        cls: ClsType[_models.SecretBundle] = kwargs.pop("cls", None)

        request = build_recover_deleted_secret_request(
            secret_name=secret_name,
            api_version=api_version,
            template_url=self.recover_deleted_secret.metadata["url"],
            headers=_headers,
            params=_params,
        )
        request = _convert_request(request)
        path_format_arguments = {
            "vaultBaseUrl": self._serialize.url("vault_base_url", vault_base_url, "str", skip_quote=True),
        }
        request.url = self._client.format_url(request.url, **path_format_arguments)

        pipeline_response: PipelineResponse = await self._client._pipeline.run(  # type: ignore # pylint: disable=protected-access
            request, stream=False, **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.KeyVaultError, pipeline_response)
            raise HttpResponseError(response=response, model=error)

        deserialized = self._deserialize("SecretBundle", pipeline_response)

        if cls:
            return cls(pipeline_response, deserialized, {})

        return deserialized

    recover_deleted_secret.metadata = {"url": "/deletedsecrets/{secret-name}/recover"}

    @distributed_trace_async
    async def backup_secret(self, vault_base_url: str, secret_name: str, **kwargs: Any) -> _models.BackupSecretResult:
        """Backs up the specified secret.

        Requests that a backup of the specified secret be downloaded to the client. All versions of the
        secret will be downloaded. This operation requires the secrets/backup permission.

        :param vault_base_url: The vault name, for example https://myvault.vault.azure.net. Required.
        :type vault_base_url: str
        :param secret_name: The name of the secret. Required.
        :type secret_name: str
        :keyword callable cls: A custom type or function that will be passed the direct response
        :return: BackupSecretResult or the result of cls(response)
        :rtype: ~azure.keyvault.v7_1.models.BackupSecretResult
        :raises ~azure.core.exceptions.HttpResponseError:
        """
        error_map = {
            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: Literal["7.1"] = kwargs.pop("api_version", _params.pop("api-version", "7.1"))
        cls: ClsType[_models.BackupSecretResult] = kwargs.pop("cls", None)

        request = build_backup_secret_request(
            secret_name=secret_name,
            api_version=api_version,
            template_url=self.backup_secret.metadata["url"],
            headers=_headers,
            params=_params,
        )
        request = _convert_request(request)
        path_format_arguments = {
            "vaultBaseUrl": self._serialize.url("vault_base_url", vault_base_url, "str", skip_quote=True),
        }
        request.url = self._client.format_url(request.url, **path_format_arguments)

        pipeline_response: PipelineResponse = await self._client._pipeline.run(  # type: ignore # pylint: disable=protected-access
            request, stream=False, **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.KeyVaultError, pipeline_response)
            raise HttpResponseError(response=response, model=error)

        deserialized = self._deserialize("BackupSecretResult", pipeline_response)

        if cls:
            return cls(pipeline_response, deserialized, {})

        return deserialized

    backup_secret.metadata = {"url": "/secrets/{secret-name}/backup"}

    @overload
    async def restore_secret(
        self,
        vault_base_url: str,
        parameters: _models.SecretRestoreParameters,
        *,
        content_type: str = "application/json",
        **kwargs: Any
    ) -> _models.SecretBundle:
        """Restores a backed up secret to a vault.

        Restores a backed up secret, and all its versions, to a vault. This operation requires the
        secrets/restore permission.

        :param vault_base_url: The vault name, for example https://myvault.vault.azure.net. Required.
        :type vault_base_url: str
        :param parameters: The parameters to restore the secret. Required.
        :type parameters: ~azure.keyvault.v7_1.models.SecretRestoreParameters
        :keyword content_type: Body Parameter content-type. Content type parameter for JSON body.
         Default value is "application/json".
        :paramtype content_type: str
        :keyword callable cls: A custom type or function that will be passed the direct response
        :return: SecretBundle or the result of cls(response)
        :rtype: ~azure.keyvault.v7_1.models.SecretBundle
        :raises ~azure.core.exceptions.HttpResponseError:
        """

    @overload
    async def restore_secret(
        self, vault_base_url: str, parameters: IO, *, content_type: str = "application/json", **kwargs: Any
    ) -> _models.SecretBundle:
        """Restores a backed up secret to a vault.

        Restores a backed up secret, and all its versions, to a vault. This operation requires the
        secrets/restore permission.

        :param vault_base_url: The vault name, for example https://myvault.vault.azure.net. Required.
        :type vault_base_url: str
        :param parameters: The parameters to restore the secret. Required.
        :type parameters: IO
        :keyword content_type: Body Parameter content-type. Content type parameter for binary body.
         Default value is "application/json".
        :paramtype content_type: str
        :keyword callable cls: A custom type or function that will be passed the direct response
        :return: SecretBundle or the result of cls(response)
        :rtype: ~azure.keyvault.v7_1.models.SecretBundle
        :raises ~azure.core.exceptions.HttpResponseError:
        """

    @distributed_trace_async
    async def restore_secret(
        self, vault_base_url: str, parameters: Union[_models.SecretRestoreParameters, IO], **kwargs: Any
    ) -> _models.SecretBundle:
        """Restores a backed up secret to a vault.

        Restores a backed up secret, and all its versions, to a vault. This operation requires the
        secrets/restore permission.

        :param vault_base_url: The vault name, for example https://myvault.vault.azure.net. Required.
        :type vault_base_url: str
        :param parameters: The parameters to restore the secret. Is either a SecretRestoreParameters
         type or a IO type. Required.
        :type parameters: ~azure.keyvault.v7_1.models.SecretRestoreParameters or IO
        :keyword content_type: Body Parameter content-type. Known values are: 'application/json'.
         Default value is None.
        :paramtype content_type: str
        :keyword callable cls: A custom type or function that will be passed the direct response
        :return: SecretBundle or the result of cls(response)
        :rtype: ~azure.keyvault.v7_1.models.SecretBundle
        :raises ~azure.core.exceptions.HttpResponseError:
        """
        error_map = {
            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: Literal["7.1"] = kwargs.pop("api_version", _params.pop("api-version", "7.1"))
        content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None))
        cls: ClsType[_models.SecretBundle] = kwargs.pop("cls", None)

        content_type = content_type or "application/json"
        _json = None
        _content = None
        if isinstance(parameters, (IO, bytes)):
            _content = parameters
        else:
            _json = self._serialize.body(parameters, "SecretRestoreParameters")

        request = build_restore_secret_request(
            api_version=api_version,
            content_type=content_type,
            json=_json,
            content=_content,
            template_url=self.restore_secret.metadata["url"],
            headers=_headers,
            params=_params,
        )
        request = _convert_request(request)
        path_format_arguments = {
            "vaultBaseUrl": self._serialize.url("vault_base_url", vault_base_url, "str", skip_quote=True),
        }
        request.url = self._client.format_url(request.url, **path_format_arguments)

        pipeline_response: PipelineResponse = await self._client._pipeline.run(  # type: ignore # pylint: disable=protected-access
            request, stream=False, **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.KeyVaultError, pipeline_response)
            raise HttpResponseError(response=response, model=error)

        deserialized = self._deserialize("SecretBundle", pipeline_response)

        if cls:
            return cls(pipeline_response, deserialized, {})

        return deserialized

    restore_secret.metadata = {"url": "/secrets/restore"}
