# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.

from __future__ import annotations

from typing import Type, Optional, cast

import httpx

from ..._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, omit, not_given
from ..._utils import path_template, maybe_transform, async_maybe_transform
from ..._compat import cached_property
from ..._resource import SyncAPIResource, AsyncAPIResource
from ..._response import (
    to_raw_response_wrapper,
    to_streamed_response_wrapper,
    async_to_raw_response_wrapper,
    async_to_streamed_response_wrapper,
)
from ..._wrappers import ResultWrapper
from .reverse_dns import (
    ReverseDNSResource,
    AsyncReverseDNSResource,
    ReverseDNSResourceWithRawResponse,
    AsyncReverseDNSResourceWithRawResponse,
    ReverseDNSResourceWithStreamingResponse,
    AsyncReverseDNSResourceWithStreamingResponse,
)
from ...pagination import SyncV4PagePaginationArray, AsyncV4PagePaginationArray
from ..._base_client import AsyncPaginator, make_request_options
from .analytics.analytics import (
    AnalyticsResource,
    AsyncAnalyticsResource,
    AnalyticsResourceWithRawResponse,
    AsyncAnalyticsResourceWithRawResponse,
    AnalyticsResourceWithStreamingResponse,
    AsyncAnalyticsResourceWithStreamingResponse,
)
from ...types.dns_firewall import (
    dns_firewall_edit_params,
    dns_firewall_list_params,
    dns_firewall_create_params,
)
from ...types.dns_firewall.upstream_ips import UpstreamIPs
from ...types.dns_firewall.attack_mitigation_param import AttackMitigationParam
from ...types.dns_firewall.dns_firewall_get_response import DNSFirewallGetResponse
from ...types.dns_firewall.dns_firewall_edit_response import DNSFirewallEditResponse
from ...types.dns_firewall.dns_firewall_list_response import DNSFirewallListResponse
from ...types.dns_firewall.dns_firewall_create_response import DNSFirewallCreateResponse
from ...types.dns_firewall.dns_firewall_delete_response import DNSFirewallDeleteResponse

__all__ = ["DNSFirewallResource", "AsyncDNSFirewallResource"]


class DNSFirewallResource(SyncAPIResource):
    @cached_property
    def analytics(self) -> AnalyticsResource:
        return AnalyticsResource(self._client)

    @cached_property
    def reverse_dns(self) -> ReverseDNSResource:
        return ReverseDNSResource(self._client)

    @cached_property
    def with_raw_response(self) -> DNSFirewallResourceWithRawResponse:
        """
        This property can be used as a prefix for any HTTP method call to return
        the raw response object instead of the parsed content.

        For more information, see https://www.github.com/cloudflare/cloudflare-python#accessing-raw-response-data-eg-headers
        """
        return DNSFirewallResourceWithRawResponse(self)

    @cached_property
    def with_streaming_response(self) -> DNSFirewallResourceWithStreamingResponse:
        """
        An alternative to `.with_raw_response` that doesn't eagerly read the response body.

        For more information, see https://www.github.com/cloudflare/cloudflare-python#with_streaming_response
        """
        return DNSFirewallResourceWithStreamingResponse(self)

    def create(
        self,
        *,
        account_id: str,
        name: str,
        upstream_ips: SequenceNotStr[UpstreamIPs],
        attack_mitigation: Optional[AttackMitigationParam] | Omit = omit,
        deprecate_any_requests: bool | Omit = omit,
        dns_firewall_ip_count: int | Omit = omit,
        ecs_fallback: bool | Omit = omit,
        maximum_cache_ttl: float | Omit = omit,
        minimum_cache_ttl: float | Omit = omit,
        negative_cache_ttl: Optional[float] | Omit = omit,
        ratelimit: Optional[float] | Omit = omit,
        retries: float | Omit = omit,
        # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
        # The extra values given here take precedence over values defined on the client or passed to this method.
        extra_headers: Headers | None = None,
        extra_query: Query | None = None,
        extra_body: Body | None = None,
        timeout: float | httpx.Timeout | None | NotGiven = not_given,
    ) -> Optional[DNSFirewallCreateResponse]:
        """
        Create a DNS Firewall cluster

        Args:
          account_id: Identifier.

          name: DNS Firewall cluster name

          attack_mitigation: Attack mitigation settings

          deprecate_any_requests: Whether to refuse to answer queries for the ANY type

          dns_firewall_ip_count: Number of IPv4 addresses to assign to the DNS Firewall cluster. Only used during
              cluster creation and cannot be changed later.

          ecs_fallback: Whether to forward client IP (resolver) subnet if no EDNS Client Subnet is sent

          maximum_cache_ttl: By default, Cloudflare attempts to cache responses for as long as indicated by
              the TTL received from upstream nameservers. This setting sets an upper bound on
              this duration. For caching purposes, higher TTLs will be decreased to the
              maximum value defined by this setting.

              This setting does not affect the TTL value in the DNS response Cloudflare
              returns to clients. Cloudflare will always forward the TTL value received from
              upstream nameservers.

          minimum_cache_ttl: By default, Cloudflare attempts to cache responses for as long as indicated by
              the TTL received from upstream nameservers. This setting sets a lower bound on
              this duration. For caching purposes, lower TTLs will be increased to the minimum
              value defined by this setting.

              This setting does not affect the TTL value in the DNS response Cloudflare
              returns to clients. Cloudflare will always forward the TTL value received from
              upstream nameservers.

              Note that, even with this setting, there is no guarantee that a response will be
              cached for at least the specified duration. Cached responses may be removed
              earlier for capacity or other operational reasons.

          negative_cache_ttl: This setting controls how long DNS Firewall should cache negative responses
              (e.g., NXDOMAIN) from the upstream servers.

              This setting does not affect the TTL value in the DNS response Cloudflare
              returns to clients. Cloudflare will always forward the TTL value received from
              upstream nameservers.

          ratelimit: Maximum number of DNS queries per second that will be forwarded to your upstream
              nameservers. The limit is enforced per server, where each server receives a
              fraction of the configured value. The actual aggregate rate for a data center
              may vary depending on how many servers are present. Responses served from cache
              do not count toward this limit. Set to null to disable rate limiting.

          retries: Number of retries for fetching DNS responses from upstream nameservers (not
              counting the initial attempt)

          extra_headers: Send extra headers

          extra_query: Add additional query parameters to the request

          extra_body: Add additional JSON properties to the request

          timeout: Override the client-level default timeout for this request, in seconds
        """
        if not account_id:
            raise ValueError(f"Expected a non-empty value for `account_id` but received {account_id!r}")
        return self._post(
            path_template("/accounts/{account_id}/dns_firewall", account_id=account_id),
            body=maybe_transform(
                {
                    "name": name,
                    "upstream_ips": upstream_ips,
                    "attack_mitigation": attack_mitigation,
                    "deprecate_any_requests": deprecate_any_requests,
                    "dns_firewall_ip_count": dns_firewall_ip_count,
                    "ecs_fallback": ecs_fallback,
                    "maximum_cache_ttl": maximum_cache_ttl,
                    "minimum_cache_ttl": minimum_cache_ttl,
                    "negative_cache_ttl": negative_cache_ttl,
                    "ratelimit": ratelimit,
                    "retries": retries,
                },
                dns_firewall_create_params.DNSFirewallCreateParams,
            ),
            options=make_request_options(
                extra_headers=extra_headers,
                extra_query=extra_query,
                extra_body=extra_body,
                timeout=timeout,
                post_parser=ResultWrapper[Optional[DNSFirewallCreateResponse]]._unwrapper,
            ),
            cast_to=cast(Type[Optional[DNSFirewallCreateResponse]], ResultWrapper[DNSFirewallCreateResponse]),
        )

    def list(
        self,
        *,
        account_id: str,
        page: float | Omit = omit,
        per_page: float | Omit = omit,
        # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
        # The extra values given here take precedence over values defined on the client or passed to this method.
        extra_headers: Headers | None = None,
        extra_query: Query | None = None,
        extra_body: Body | None = None,
        timeout: float | httpx.Timeout | None | NotGiven = not_given,
    ) -> SyncV4PagePaginationArray[DNSFirewallListResponse]:
        """
        List DNS Firewall clusters for an account

        Args:
          account_id: Identifier.

          page: Page number of paginated results

          per_page: Number of clusters per page

          extra_headers: Send extra headers

          extra_query: Add additional query parameters to the request

          extra_body: Add additional JSON properties to the request

          timeout: Override the client-level default timeout for this request, in seconds
        """
        if not account_id:
            raise ValueError(f"Expected a non-empty value for `account_id` but received {account_id!r}")
        return self._get_api_list(
            path_template("/accounts/{account_id}/dns_firewall", account_id=account_id),
            page=SyncV4PagePaginationArray[DNSFirewallListResponse],
            options=make_request_options(
                extra_headers=extra_headers,
                extra_query=extra_query,
                extra_body=extra_body,
                timeout=timeout,
                query=maybe_transform(
                    {
                        "page": page,
                        "per_page": per_page,
                    },
                    dns_firewall_list_params.DNSFirewallListParams,
                ),
            ),
            model=DNSFirewallListResponse,
        )

    def delete(
        self,
        dns_firewall_id: str,
        *,
        account_id: str,
        # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
        # The extra values given here take precedence over values defined on the client or passed to this method.
        extra_headers: Headers | None = None,
        extra_query: Query | None = None,
        extra_body: Body | None = None,
        timeout: float | httpx.Timeout | None | NotGiven = not_given,
    ) -> Optional[DNSFirewallDeleteResponse]:
        """
        Delete a DNS Firewall cluster

        Args:
          account_id: Identifier.

          dns_firewall_id: Identifier.

          extra_headers: Send extra headers

          extra_query: Add additional query parameters to the request

          extra_body: Add additional JSON properties to the request

          timeout: Override the client-level default timeout for this request, in seconds
        """
        if not account_id:
            raise ValueError(f"Expected a non-empty value for `account_id` but received {account_id!r}")
        if not dns_firewall_id:
            raise ValueError(f"Expected a non-empty value for `dns_firewall_id` but received {dns_firewall_id!r}")
        return self._delete(
            path_template(
                "/accounts/{account_id}/dns_firewall/{dns_firewall_id}",
                account_id=account_id,
                dns_firewall_id=dns_firewall_id,
            ),
            options=make_request_options(
                extra_headers=extra_headers,
                extra_query=extra_query,
                extra_body=extra_body,
                timeout=timeout,
                post_parser=ResultWrapper[Optional[DNSFirewallDeleteResponse]]._unwrapper,
            ),
            cast_to=cast(Type[Optional[DNSFirewallDeleteResponse]], ResultWrapper[DNSFirewallDeleteResponse]),
        )

    def edit(
        self,
        dns_firewall_id: str,
        *,
        account_id: str,
        attack_mitigation: Optional[AttackMitigationParam] | Omit = omit,
        deprecate_any_requests: bool | Omit = omit,
        ecs_fallback: bool | Omit = omit,
        maximum_cache_ttl: float | Omit = omit,
        minimum_cache_ttl: float | Omit = omit,
        name: str | Omit = omit,
        negative_cache_ttl: Optional[float] | Omit = omit,
        ratelimit: Optional[float] | Omit = omit,
        retries: float | Omit = omit,
        upstream_ips: SequenceNotStr[UpstreamIPs] | Omit = omit,
        # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
        # The extra values given here take precedence over values defined on the client or passed to this method.
        extra_headers: Headers | None = None,
        extra_query: Query | None = None,
        extra_body: Body | None = None,
        timeout: float | httpx.Timeout | None | NotGiven = not_given,
    ) -> Optional[DNSFirewallEditResponse]:
        """
        Modify the configuration of a DNS Firewall cluster

        Args:
          account_id: Identifier.

          dns_firewall_id: Identifier.

          attack_mitigation: Attack mitigation settings

          deprecate_any_requests: Whether to refuse to answer queries for the ANY type

          ecs_fallback: Whether to forward client IP (resolver) subnet if no EDNS Client Subnet is sent

          maximum_cache_ttl: By default, Cloudflare attempts to cache responses for as long as indicated by
              the TTL received from upstream nameservers. This setting sets an upper bound on
              this duration. For caching purposes, higher TTLs will be decreased to the
              maximum value defined by this setting.

              This setting does not affect the TTL value in the DNS response Cloudflare
              returns to clients. Cloudflare will always forward the TTL value received from
              upstream nameservers.

          minimum_cache_ttl: By default, Cloudflare attempts to cache responses for as long as indicated by
              the TTL received from upstream nameservers. This setting sets a lower bound on
              this duration. For caching purposes, lower TTLs will be increased to the minimum
              value defined by this setting.

              This setting does not affect the TTL value in the DNS response Cloudflare
              returns to clients. Cloudflare will always forward the TTL value received from
              upstream nameservers.

              Note that, even with this setting, there is no guarantee that a response will be
              cached for at least the specified duration. Cached responses may be removed
              earlier for capacity or other operational reasons.

          name: DNS Firewall cluster name

          negative_cache_ttl: This setting controls how long DNS Firewall should cache negative responses
              (e.g., NXDOMAIN) from the upstream servers.

              This setting does not affect the TTL value in the DNS response Cloudflare
              returns to clients. Cloudflare will always forward the TTL value received from
              upstream nameservers.

          ratelimit: Maximum number of DNS queries per second that will be forwarded to your upstream
              nameservers. The limit is enforced per server, where each server receives a
              fraction of the configured value. The actual aggregate rate for a data center
              may vary depending on how many servers are present. Responses served from cache
              do not count toward this limit. Set to null to disable rate limiting.

          retries: Number of retries for fetching DNS responses from upstream nameservers (not
              counting the initial attempt)

          extra_headers: Send extra headers

          extra_query: Add additional query parameters to the request

          extra_body: Add additional JSON properties to the request

          timeout: Override the client-level default timeout for this request, in seconds
        """
        if not account_id:
            raise ValueError(f"Expected a non-empty value for `account_id` but received {account_id!r}")
        if not dns_firewall_id:
            raise ValueError(f"Expected a non-empty value for `dns_firewall_id` but received {dns_firewall_id!r}")
        return self._patch(
            path_template(
                "/accounts/{account_id}/dns_firewall/{dns_firewall_id}",
                account_id=account_id,
                dns_firewall_id=dns_firewall_id,
            ),
            body=maybe_transform(
                {
                    "attack_mitigation": attack_mitigation,
                    "deprecate_any_requests": deprecate_any_requests,
                    "ecs_fallback": ecs_fallback,
                    "maximum_cache_ttl": maximum_cache_ttl,
                    "minimum_cache_ttl": minimum_cache_ttl,
                    "name": name,
                    "negative_cache_ttl": negative_cache_ttl,
                    "ratelimit": ratelimit,
                    "retries": retries,
                    "upstream_ips": upstream_ips,
                },
                dns_firewall_edit_params.DNSFirewallEditParams,
            ),
            options=make_request_options(
                extra_headers=extra_headers,
                extra_query=extra_query,
                extra_body=extra_body,
                timeout=timeout,
                post_parser=ResultWrapper[Optional[DNSFirewallEditResponse]]._unwrapper,
            ),
            cast_to=cast(Type[Optional[DNSFirewallEditResponse]], ResultWrapper[DNSFirewallEditResponse]),
        )

    def get(
        self,
        dns_firewall_id: str,
        *,
        account_id: str,
        # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
        # The extra values given here take precedence over values defined on the client or passed to this method.
        extra_headers: Headers | None = None,
        extra_query: Query | None = None,
        extra_body: Body | None = None,
        timeout: float | httpx.Timeout | None | NotGiven = not_given,
    ) -> Optional[DNSFirewallGetResponse]:
        """
        Show a single DNS Firewall cluster for an account

        Args:
          account_id: Identifier.

          dns_firewall_id: Identifier.

          extra_headers: Send extra headers

          extra_query: Add additional query parameters to the request

          extra_body: Add additional JSON properties to the request

          timeout: Override the client-level default timeout for this request, in seconds
        """
        if not account_id:
            raise ValueError(f"Expected a non-empty value for `account_id` but received {account_id!r}")
        if not dns_firewall_id:
            raise ValueError(f"Expected a non-empty value for `dns_firewall_id` but received {dns_firewall_id!r}")
        return self._get(
            path_template(
                "/accounts/{account_id}/dns_firewall/{dns_firewall_id}",
                account_id=account_id,
                dns_firewall_id=dns_firewall_id,
            ),
            options=make_request_options(
                extra_headers=extra_headers,
                extra_query=extra_query,
                extra_body=extra_body,
                timeout=timeout,
                post_parser=ResultWrapper[Optional[DNSFirewallGetResponse]]._unwrapper,
            ),
            cast_to=cast(Type[Optional[DNSFirewallGetResponse]], ResultWrapper[DNSFirewallGetResponse]),
        )


class AsyncDNSFirewallResource(AsyncAPIResource):
    @cached_property
    def analytics(self) -> AsyncAnalyticsResource:
        return AsyncAnalyticsResource(self._client)

    @cached_property
    def reverse_dns(self) -> AsyncReverseDNSResource:
        return AsyncReverseDNSResource(self._client)

    @cached_property
    def with_raw_response(self) -> AsyncDNSFirewallResourceWithRawResponse:
        """
        This property can be used as a prefix for any HTTP method call to return
        the raw response object instead of the parsed content.

        For more information, see https://www.github.com/cloudflare/cloudflare-python#accessing-raw-response-data-eg-headers
        """
        return AsyncDNSFirewallResourceWithRawResponse(self)

    @cached_property
    def with_streaming_response(self) -> AsyncDNSFirewallResourceWithStreamingResponse:
        """
        An alternative to `.with_raw_response` that doesn't eagerly read the response body.

        For more information, see https://www.github.com/cloudflare/cloudflare-python#with_streaming_response
        """
        return AsyncDNSFirewallResourceWithStreamingResponse(self)

    async def create(
        self,
        *,
        account_id: str,
        name: str,
        upstream_ips: SequenceNotStr[UpstreamIPs],
        attack_mitigation: Optional[AttackMitigationParam] | Omit = omit,
        deprecate_any_requests: bool | Omit = omit,
        dns_firewall_ip_count: int | Omit = omit,
        ecs_fallback: bool | Omit = omit,
        maximum_cache_ttl: float | Omit = omit,
        minimum_cache_ttl: float | Omit = omit,
        negative_cache_ttl: Optional[float] | Omit = omit,
        ratelimit: Optional[float] | Omit = omit,
        retries: float | Omit = omit,
        # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
        # The extra values given here take precedence over values defined on the client or passed to this method.
        extra_headers: Headers | None = None,
        extra_query: Query | None = None,
        extra_body: Body | None = None,
        timeout: float | httpx.Timeout | None | NotGiven = not_given,
    ) -> Optional[DNSFirewallCreateResponse]:
        """
        Create a DNS Firewall cluster

        Args:
          account_id: Identifier.

          name: DNS Firewall cluster name

          attack_mitigation: Attack mitigation settings

          deprecate_any_requests: Whether to refuse to answer queries for the ANY type

          dns_firewall_ip_count: Number of IPv4 addresses to assign to the DNS Firewall cluster. Only used during
              cluster creation and cannot be changed later.

          ecs_fallback: Whether to forward client IP (resolver) subnet if no EDNS Client Subnet is sent

          maximum_cache_ttl: By default, Cloudflare attempts to cache responses for as long as indicated by
              the TTL received from upstream nameservers. This setting sets an upper bound on
              this duration. For caching purposes, higher TTLs will be decreased to the
              maximum value defined by this setting.

              This setting does not affect the TTL value in the DNS response Cloudflare
              returns to clients. Cloudflare will always forward the TTL value received from
              upstream nameservers.

          minimum_cache_ttl: By default, Cloudflare attempts to cache responses for as long as indicated by
              the TTL received from upstream nameservers. This setting sets a lower bound on
              this duration. For caching purposes, lower TTLs will be increased to the minimum
              value defined by this setting.

              This setting does not affect the TTL value in the DNS response Cloudflare
              returns to clients. Cloudflare will always forward the TTL value received from
              upstream nameservers.

              Note that, even with this setting, there is no guarantee that a response will be
              cached for at least the specified duration. Cached responses may be removed
              earlier for capacity or other operational reasons.

          negative_cache_ttl: This setting controls how long DNS Firewall should cache negative responses
              (e.g., NXDOMAIN) from the upstream servers.

              This setting does not affect the TTL value in the DNS response Cloudflare
              returns to clients. Cloudflare will always forward the TTL value received from
              upstream nameservers.

          ratelimit: Maximum number of DNS queries per second that will be forwarded to your upstream
              nameservers. The limit is enforced per server, where each server receives a
              fraction of the configured value. The actual aggregate rate for a data center
              may vary depending on how many servers are present. Responses served from cache
              do not count toward this limit. Set to null to disable rate limiting.

          retries: Number of retries for fetching DNS responses from upstream nameservers (not
              counting the initial attempt)

          extra_headers: Send extra headers

          extra_query: Add additional query parameters to the request

          extra_body: Add additional JSON properties to the request

          timeout: Override the client-level default timeout for this request, in seconds
        """
        if not account_id:
            raise ValueError(f"Expected a non-empty value for `account_id` but received {account_id!r}")
        return await self._post(
            path_template("/accounts/{account_id}/dns_firewall", account_id=account_id),
            body=await async_maybe_transform(
                {
                    "name": name,
                    "upstream_ips": upstream_ips,
                    "attack_mitigation": attack_mitigation,
                    "deprecate_any_requests": deprecate_any_requests,
                    "dns_firewall_ip_count": dns_firewall_ip_count,
                    "ecs_fallback": ecs_fallback,
                    "maximum_cache_ttl": maximum_cache_ttl,
                    "minimum_cache_ttl": minimum_cache_ttl,
                    "negative_cache_ttl": negative_cache_ttl,
                    "ratelimit": ratelimit,
                    "retries": retries,
                },
                dns_firewall_create_params.DNSFirewallCreateParams,
            ),
            options=make_request_options(
                extra_headers=extra_headers,
                extra_query=extra_query,
                extra_body=extra_body,
                timeout=timeout,
                post_parser=ResultWrapper[Optional[DNSFirewallCreateResponse]]._unwrapper,
            ),
            cast_to=cast(Type[Optional[DNSFirewallCreateResponse]], ResultWrapper[DNSFirewallCreateResponse]),
        )

    def list(
        self,
        *,
        account_id: str,
        page: float | Omit = omit,
        per_page: float | Omit = omit,
        # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
        # The extra values given here take precedence over values defined on the client or passed to this method.
        extra_headers: Headers | None = None,
        extra_query: Query | None = None,
        extra_body: Body | None = None,
        timeout: float | httpx.Timeout | None | NotGiven = not_given,
    ) -> AsyncPaginator[DNSFirewallListResponse, AsyncV4PagePaginationArray[DNSFirewallListResponse]]:
        """
        List DNS Firewall clusters for an account

        Args:
          account_id: Identifier.

          page: Page number of paginated results

          per_page: Number of clusters per page

          extra_headers: Send extra headers

          extra_query: Add additional query parameters to the request

          extra_body: Add additional JSON properties to the request

          timeout: Override the client-level default timeout for this request, in seconds
        """
        if not account_id:
            raise ValueError(f"Expected a non-empty value for `account_id` but received {account_id!r}")
        return self._get_api_list(
            path_template("/accounts/{account_id}/dns_firewall", account_id=account_id),
            page=AsyncV4PagePaginationArray[DNSFirewallListResponse],
            options=make_request_options(
                extra_headers=extra_headers,
                extra_query=extra_query,
                extra_body=extra_body,
                timeout=timeout,
                query=maybe_transform(
                    {
                        "page": page,
                        "per_page": per_page,
                    },
                    dns_firewall_list_params.DNSFirewallListParams,
                ),
            ),
            model=DNSFirewallListResponse,
        )

    async def delete(
        self,
        dns_firewall_id: str,
        *,
        account_id: str,
        # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
        # The extra values given here take precedence over values defined on the client or passed to this method.
        extra_headers: Headers | None = None,
        extra_query: Query | None = None,
        extra_body: Body | None = None,
        timeout: float | httpx.Timeout | None | NotGiven = not_given,
    ) -> Optional[DNSFirewallDeleteResponse]:
        """
        Delete a DNS Firewall cluster

        Args:
          account_id: Identifier.

          dns_firewall_id: Identifier.

          extra_headers: Send extra headers

          extra_query: Add additional query parameters to the request

          extra_body: Add additional JSON properties to the request

          timeout: Override the client-level default timeout for this request, in seconds
        """
        if not account_id:
            raise ValueError(f"Expected a non-empty value for `account_id` but received {account_id!r}")
        if not dns_firewall_id:
            raise ValueError(f"Expected a non-empty value for `dns_firewall_id` but received {dns_firewall_id!r}")
        return await self._delete(
            path_template(
                "/accounts/{account_id}/dns_firewall/{dns_firewall_id}",
                account_id=account_id,
                dns_firewall_id=dns_firewall_id,
            ),
            options=make_request_options(
                extra_headers=extra_headers,
                extra_query=extra_query,
                extra_body=extra_body,
                timeout=timeout,
                post_parser=ResultWrapper[Optional[DNSFirewallDeleteResponse]]._unwrapper,
            ),
            cast_to=cast(Type[Optional[DNSFirewallDeleteResponse]], ResultWrapper[DNSFirewallDeleteResponse]),
        )

    async def edit(
        self,
        dns_firewall_id: str,
        *,
        account_id: str,
        attack_mitigation: Optional[AttackMitigationParam] | Omit = omit,
        deprecate_any_requests: bool | Omit = omit,
        ecs_fallback: bool | Omit = omit,
        maximum_cache_ttl: float | Omit = omit,
        minimum_cache_ttl: float | Omit = omit,
        name: str | Omit = omit,
        negative_cache_ttl: Optional[float] | Omit = omit,
        ratelimit: Optional[float] | Omit = omit,
        retries: float | Omit = omit,
        upstream_ips: SequenceNotStr[UpstreamIPs] | Omit = omit,
        # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
        # The extra values given here take precedence over values defined on the client or passed to this method.
        extra_headers: Headers | None = None,
        extra_query: Query | None = None,
        extra_body: Body | None = None,
        timeout: float | httpx.Timeout | None | NotGiven = not_given,
    ) -> Optional[DNSFirewallEditResponse]:
        """
        Modify the configuration of a DNS Firewall cluster

        Args:
          account_id: Identifier.

          dns_firewall_id: Identifier.

          attack_mitigation: Attack mitigation settings

          deprecate_any_requests: Whether to refuse to answer queries for the ANY type

          ecs_fallback: Whether to forward client IP (resolver) subnet if no EDNS Client Subnet is sent

          maximum_cache_ttl: By default, Cloudflare attempts to cache responses for as long as indicated by
              the TTL received from upstream nameservers. This setting sets an upper bound on
              this duration. For caching purposes, higher TTLs will be decreased to the
              maximum value defined by this setting.

              This setting does not affect the TTL value in the DNS response Cloudflare
              returns to clients. Cloudflare will always forward the TTL value received from
              upstream nameservers.

          minimum_cache_ttl: By default, Cloudflare attempts to cache responses for as long as indicated by
              the TTL received from upstream nameservers. This setting sets a lower bound on
              this duration. For caching purposes, lower TTLs will be increased to the minimum
              value defined by this setting.

              This setting does not affect the TTL value in the DNS response Cloudflare
              returns to clients. Cloudflare will always forward the TTL value received from
              upstream nameservers.

              Note that, even with this setting, there is no guarantee that a response will be
              cached for at least the specified duration. Cached responses may be removed
              earlier for capacity or other operational reasons.

          name: DNS Firewall cluster name

          negative_cache_ttl: This setting controls how long DNS Firewall should cache negative responses
              (e.g., NXDOMAIN) from the upstream servers.

              This setting does not affect the TTL value in the DNS response Cloudflare
              returns to clients. Cloudflare will always forward the TTL value received from
              upstream nameservers.

          ratelimit: Maximum number of DNS queries per second that will be forwarded to your upstream
              nameservers. The limit is enforced per server, where each server receives a
              fraction of the configured value. The actual aggregate rate for a data center
              may vary depending on how many servers are present. Responses served from cache
              do not count toward this limit. Set to null to disable rate limiting.

          retries: Number of retries for fetching DNS responses from upstream nameservers (not
              counting the initial attempt)

          extra_headers: Send extra headers

          extra_query: Add additional query parameters to the request

          extra_body: Add additional JSON properties to the request

          timeout: Override the client-level default timeout for this request, in seconds
        """
        if not account_id:
            raise ValueError(f"Expected a non-empty value for `account_id` but received {account_id!r}")
        if not dns_firewall_id:
            raise ValueError(f"Expected a non-empty value for `dns_firewall_id` but received {dns_firewall_id!r}")
        return await self._patch(
            path_template(
                "/accounts/{account_id}/dns_firewall/{dns_firewall_id}",
                account_id=account_id,
                dns_firewall_id=dns_firewall_id,
            ),
            body=await async_maybe_transform(
                {
                    "attack_mitigation": attack_mitigation,
                    "deprecate_any_requests": deprecate_any_requests,
                    "ecs_fallback": ecs_fallback,
                    "maximum_cache_ttl": maximum_cache_ttl,
                    "minimum_cache_ttl": minimum_cache_ttl,
                    "name": name,
                    "negative_cache_ttl": negative_cache_ttl,
                    "ratelimit": ratelimit,
                    "retries": retries,
                    "upstream_ips": upstream_ips,
                },
                dns_firewall_edit_params.DNSFirewallEditParams,
            ),
            options=make_request_options(
                extra_headers=extra_headers,
                extra_query=extra_query,
                extra_body=extra_body,
                timeout=timeout,
                post_parser=ResultWrapper[Optional[DNSFirewallEditResponse]]._unwrapper,
            ),
            cast_to=cast(Type[Optional[DNSFirewallEditResponse]], ResultWrapper[DNSFirewallEditResponse]),
        )

    async def get(
        self,
        dns_firewall_id: str,
        *,
        account_id: str,
        # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
        # The extra values given here take precedence over values defined on the client or passed to this method.
        extra_headers: Headers | None = None,
        extra_query: Query | None = None,
        extra_body: Body | None = None,
        timeout: float | httpx.Timeout | None | NotGiven = not_given,
    ) -> Optional[DNSFirewallGetResponse]:
        """
        Show a single DNS Firewall cluster for an account

        Args:
          account_id: Identifier.

          dns_firewall_id: Identifier.

          extra_headers: Send extra headers

          extra_query: Add additional query parameters to the request

          extra_body: Add additional JSON properties to the request

          timeout: Override the client-level default timeout for this request, in seconds
        """
        if not account_id:
            raise ValueError(f"Expected a non-empty value for `account_id` but received {account_id!r}")
        if not dns_firewall_id:
            raise ValueError(f"Expected a non-empty value for `dns_firewall_id` but received {dns_firewall_id!r}")
        return await self._get(
            path_template(
                "/accounts/{account_id}/dns_firewall/{dns_firewall_id}",
                account_id=account_id,
                dns_firewall_id=dns_firewall_id,
            ),
            options=make_request_options(
                extra_headers=extra_headers,
                extra_query=extra_query,
                extra_body=extra_body,
                timeout=timeout,
                post_parser=ResultWrapper[Optional[DNSFirewallGetResponse]]._unwrapper,
            ),
            cast_to=cast(Type[Optional[DNSFirewallGetResponse]], ResultWrapper[DNSFirewallGetResponse]),
        )


class DNSFirewallResourceWithRawResponse:
    def __init__(self, dns_firewall: DNSFirewallResource) -> None:
        self._dns_firewall = dns_firewall

        self.create = to_raw_response_wrapper(
            dns_firewall.create,
        )
        self.list = to_raw_response_wrapper(
            dns_firewall.list,
        )
        self.delete = to_raw_response_wrapper(
            dns_firewall.delete,
        )
        self.edit = to_raw_response_wrapper(
            dns_firewall.edit,
        )
        self.get = to_raw_response_wrapper(
            dns_firewall.get,
        )

    @cached_property
    def analytics(self) -> AnalyticsResourceWithRawResponse:
        return AnalyticsResourceWithRawResponse(self._dns_firewall.analytics)

    @cached_property
    def reverse_dns(self) -> ReverseDNSResourceWithRawResponse:
        return ReverseDNSResourceWithRawResponse(self._dns_firewall.reverse_dns)


class AsyncDNSFirewallResourceWithRawResponse:
    def __init__(self, dns_firewall: AsyncDNSFirewallResource) -> None:
        self._dns_firewall = dns_firewall

        self.create = async_to_raw_response_wrapper(
            dns_firewall.create,
        )
        self.list = async_to_raw_response_wrapper(
            dns_firewall.list,
        )
        self.delete = async_to_raw_response_wrapper(
            dns_firewall.delete,
        )
        self.edit = async_to_raw_response_wrapper(
            dns_firewall.edit,
        )
        self.get = async_to_raw_response_wrapper(
            dns_firewall.get,
        )

    @cached_property
    def analytics(self) -> AsyncAnalyticsResourceWithRawResponse:
        return AsyncAnalyticsResourceWithRawResponse(self._dns_firewall.analytics)

    @cached_property
    def reverse_dns(self) -> AsyncReverseDNSResourceWithRawResponse:
        return AsyncReverseDNSResourceWithRawResponse(self._dns_firewall.reverse_dns)


class DNSFirewallResourceWithStreamingResponse:
    def __init__(self, dns_firewall: DNSFirewallResource) -> None:
        self._dns_firewall = dns_firewall

        self.create = to_streamed_response_wrapper(
            dns_firewall.create,
        )
        self.list = to_streamed_response_wrapper(
            dns_firewall.list,
        )
        self.delete = to_streamed_response_wrapper(
            dns_firewall.delete,
        )
        self.edit = to_streamed_response_wrapper(
            dns_firewall.edit,
        )
        self.get = to_streamed_response_wrapper(
            dns_firewall.get,
        )

    @cached_property
    def analytics(self) -> AnalyticsResourceWithStreamingResponse:
        return AnalyticsResourceWithStreamingResponse(self._dns_firewall.analytics)

    @cached_property
    def reverse_dns(self) -> ReverseDNSResourceWithStreamingResponse:
        return ReverseDNSResourceWithStreamingResponse(self._dns_firewall.reverse_dns)


class AsyncDNSFirewallResourceWithStreamingResponse:
    def __init__(self, dns_firewall: AsyncDNSFirewallResource) -> None:
        self._dns_firewall = dns_firewall

        self.create = async_to_streamed_response_wrapper(
            dns_firewall.create,
        )
        self.list = async_to_streamed_response_wrapper(
            dns_firewall.list,
        )
        self.delete = async_to_streamed_response_wrapper(
            dns_firewall.delete,
        )
        self.edit = async_to_streamed_response_wrapper(
            dns_firewall.edit,
        )
        self.get = async_to_streamed_response_wrapper(
            dns_firewall.get,
        )

    @cached_property
    def analytics(self) -> AsyncAnalyticsResourceWithStreamingResponse:
        return AsyncAnalyticsResourceWithStreamingResponse(self._dns_firewall.analytics)

    @cached_property
    def reverse_dns(self) -> AsyncReverseDNSResourceWithStreamingResponse:
        return AsyncReverseDNSResourceWithStreamingResponse(self._dns_firewall.reverse_dns)
