# This file was auto-generated by Fern from our API Definition.

from __future__ import annotations

import typing

from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
from ..core.request_options import RequestOptions
from ..types.phone_enum import PhoneEnum
from ..types.phone_feature_enum import PhoneFeatureEnum
from ..types.phone_number_details import PhoneNumberDetails
from ..types.purchased_number import PurchasedNumber
from .raw_client import AsyncRawPhoneNumbersClient, RawPhoneNumbersClient
from .types.phone_details_schema_level import PhoneDetailsSchemaLevel
from .types.phone_numbers_get_response import PhoneNumbersGetResponse
from .types.retrieve_phone_number_details_options import RetrievePhoneNumberDetailsOptions
from .types.search_phone_number_by_digits import SearchPhoneNumberByDigits
from .types.search_phone_number_by_location import SearchPhoneNumberByLocation
from .types.search_phone_number_options import SearchPhoneNumberOptions

if typing.TYPE_CHECKING:
    from .campaign.client import AsyncCampaignClient, CampaignClient
    from .webhook.client import AsyncWebhookClient, WebhookClient
# this is used as the default value for optional parameters
OMIT = typing.cast(typing.Any, ...)


class PhoneNumbersClient:
    def __init__(self, *, client_wrapper: SyncClientWrapper):
        self._raw_client = RawPhoneNumbersClient(client_wrapper=client_wrapper)
        self._client_wrapper = client_wrapper
        self._webhook: typing.Optional[WebhookClient] = None
        self._campaign: typing.Optional[CampaignClient] = None

    @property
    def with_raw_response(self) -> RawPhoneNumbersClient:
        """
        Retrieves a raw implementation of this client that returns raw responses.

        Returns
        -------
        RawPhoneNumbersClient
        """
        return self._raw_client

    def search(
        self,
        *,
        type: typing.Sequence[PhoneEnum],
        features: typing.Optional[typing.Sequence[PhoneFeatureEnum]] = OMIT,
        location: typing.Optional[SearchPhoneNumberByLocation] = OMIT,
        number: typing.Optional[SearchPhoneNumberByDigits] = OMIT,
        options: typing.Optional[SearchPhoneNumberOptions] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> typing.List[PhoneNumberDetails]:
        """
        Search for available phone numbers that match your exact criteria.

        Parameters
        ----------
        type : typing.Sequence[PhoneEnum]
            Types of phone numbers to return in your search.

        features : typing.Optional[typing.Sequence[PhoneFeatureEnum]]

        location : typing.Optional[SearchPhoneNumberByLocation]
            Filter your search by geographic location to find numbers in specific regions. <br>

            Toll-free numbers ignore city and state filters.

        number : typing.Optional[SearchPhoneNumberByDigits]
            Filter your search by digit pattern.

        options : typing.Optional[SearchPhoneNumberOptions]
            Extra search settings to control how many results you get.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        typing.List[PhoneNumberDetails]
            Returns a **list** of available phone numbers that match the search criteria. <br>

            Use our [buy endpoint](./buy) to purchase any amount of phone numbers that you like.

        Examples
        --------
        from rcs import Pinnacle
        from rcs.phone_numbers import (
            SearchPhoneNumberByDigits,
            SearchPhoneNumberByLocation,
            SearchPhoneNumberOptions,
        )

        client = Pinnacle(
            api_key="YOUR_API_KEY",
        )
        client.phone_numbers.search(
            features=["SMS", "MMS"],
            location=SearchPhoneNumberByLocation(
                city="New York",
                national_destination_code="212",
            ),
            number=SearchPhoneNumberByDigits(
                contains="514",
                starts_with="45",
            ),
            options=SearchPhoneNumberOptions(
                limit=4,
            ),
            type=["LOCAL"],
        )
        """
        _response = self._raw_client.search(
            type=type,
            features=features,
            location=location,
            number=number,
            options=options,
            request_options=request_options,
        )
        return _response.data

    def buy(
        self, *, numbers: typing.Sequence[str], request_options: typing.Optional[RequestOptions] = None
    ) -> typing.List[PurchasedNumber]:
        """
        Purchase one or more phone numbers found through the [search endpoint](./search). <br>

        Billing uses your account credits and the numbers are ready for immediate use.

        Parameters
        ----------
        numbers : typing.Sequence[str]
            List of phone numbers you want to purchase, each in international E.164 format. <br>

            All specified numbers must be currently available and will be validated for availability before processing the purchase. <br>

            If any number in the request is unavailable or invalid, no purchases will be made and the request will be voided.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        typing.List[PurchasedNumber]
            Successfully purchased the number(s).

        Examples
        --------
        from rcs import Pinnacle

        client = Pinnacle(
            api_key="YOUR_API_KEY",
        )
        client.phone_numbers.buy(
            numbers=["+18559491727"],
        )
        """
        _response = self._raw_client.buy(numbers=numbers, request_options=request_options)
        return _response.data

    def get(
        self,
        *,
        phone: str,
        level: PhoneDetailsSchemaLevel,
        options: typing.Optional[RetrievePhoneNumberDetailsOptions] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> PhoneNumbersGetResponse:
        """
        Retrieve information about any phone number.

        Parameters
        ----------
        phone : str
            Phone number you want to analyze in E.164 format.

        level : PhoneDetailsSchemaLevel
            Choose how much detail you want in your results:
            - `basic`: Receive essential info like carrier, location, and format.
            - `advanced`: Receive a deeper analysis including fraud risk, detailed location, and enhanced contact info.

        options : typing.Optional[RetrievePhoneNumberDetailsOptions]
            Customize your lookup with additional options.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        PhoneNumbersGetResponse
            Returns detailed information for the requested phone number based on the selected lookup.

        Examples
        --------
        from rcs import Pinnacle
        from rcs.phone_numbers import (
            EnhancedContactInfo,
            RetrievePhoneNumberDetailsOptions,
        )

        client = Pinnacle(
            api_key="YOUR_API_KEY",
        )
        client.phone_numbers.get(
            phone="+11234567890",
            level="advanced",
            options=RetrievePhoneNumberDetailsOptions(
                risk=True,
                enhanced_contact_info=EnhancedContactInfo(
                    context="This is my friend from JZ. He has done a lot in the crypto space.",
                ),
            ),
        )
        """
        _response = self._raw_client.get(phone=phone, level=level, options=options, request_options=request_options)
        return _response.data

    @property
    def webhook(self):
        if self._webhook is None:
            from .webhook.client import WebhookClient  # noqa: E402

            self._webhook = WebhookClient(client_wrapper=self._client_wrapper)
        return self._webhook

    @property
    def campaign(self):
        if self._campaign is None:
            from .campaign.client import CampaignClient  # noqa: E402

            self._campaign = CampaignClient(client_wrapper=self._client_wrapper)
        return self._campaign


class AsyncPhoneNumbersClient:
    def __init__(self, *, client_wrapper: AsyncClientWrapper):
        self._raw_client = AsyncRawPhoneNumbersClient(client_wrapper=client_wrapper)
        self._client_wrapper = client_wrapper
        self._webhook: typing.Optional[AsyncWebhookClient] = None
        self._campaign: typing.Optional[AsyncCampaignClient] = None

    @property
    def with_raw_response(self) -> AsyncRawPhoneNumbersClient:
        """
        Retrieves a raw implementation of this client that returns raw responses.

        Returns
        -------
        AsyncRawPhoneNumbersClient
        """
        return self._raw_client

    async def search(
        self,
        *,
        type: typing.Sequence[PhoneEnum],
        features: typing.Optional[typing.Sequence[PhoneFeatureEnum]] = OMIT,
        location: typing.Optional[SearchPhoneNumberByLocation] = OMIT,
        number: typing.Optional[SearchPhoneNumberByDigits] = OMIT,
        options: typing.Optional[SearchPhoneNumberOptions] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> typing.List[PhoneNumberDetails]:
        """
        Search for available phone numbers that match your exact criteria.

        Parameters
        ----------
        type : typing.Sequence[PhoneEnum]
            Types of phone numbers to return in your search.

        features : typing.Optional[typing.Sequence[PhoneFeatureEnum]]

        location : typing.Optional[SearchPhoneNumberByLocation]
            Filter your search by geographic location to find numbers in specific regions. <br>

            Toll-free numbers ignore city and state filters.

        number : typing.Optional[SearchPhoneNumberByDigits]
            Filter your search by digit pattern.

        options : typing.Optional[SearchPhoneNumberOptions]
            Extra search settings to control how many results you get.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        typing.List[PhoneNumberDetails]
            Returns a **list** of available phone numbers that match the search criteria. <br>

            Use our [buy endpoint](./buy) to purchase any amount of phone numbers that you like.

        Examples
        --------
        import asyncio

        from rcs import AsyncPinnacle
        from rcs.phone_numbers import (
            SearchPhoneNumberByDigits,
            SearchPhoneNumberByLocation,
            SearchPhoneNumberOptions,
        )

        client = AsyncPinnacle(
            api_key="YOUR_API_KEY",
        )


        async def main() -> None:
            await client.phone_numbers.search(
                features=["SMS", "MMS"],
                location=SearchPhoneNumberByLocation(
                    city="New York",
                    national_destination_code="212",
                ),
                number=SearchPhoneNumberByDigits(
                    contains="514",
                    starts_with="45",
                ),
                options=SearchPhoneNumberOptions(
                    limit=4,
                ),
                type=["LOCAL"],
            )


        asyncio.run(main())
        """
        _response = await self._raw_client.search(
            type=type,
            features=features,
            location=location,
            number=number,
            options=options,
            request_options=request_options,
        )
        return _response.data

    async def buy(
        self, *, numbers: typing.Sequence[str], request_options: typing.Optional[RequestOptions] = None
    ) -> typing.List[PurchasedNumber]:
        """
        Purchase one or more phone numbers found through the [search endpoint](./search). <br>

        Billing uses your account credits and the numbers are ready for immediate use.

        Parameters
        ----------
        numbers : typing.Sequence[str]
            List of phone numbers you want to purchase, each in international E.164 format. <br>

            All specified numbers must be currently available and will be validated for availability before processing the purchase. <br>

            If any number in the request is unavailable or invalid, no purchases will be made and the request will be voided.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        typing.List[PurchasedNumber]
            Successfully purchased the number(s).

        Examples
        --------
        import asyncio

        from rcs import AsyncPinnacle

        client = AsyncPinnacle(
            api_key="YOUR_API_KEY",
        )


        async def main() -> None:
            await client.phone_numbers.buy(
                numbers=["+18559491727"],
            )


        asyncio.run(main())
        """
        _response = await self._raw_client.buy(numbers=numbers, request_options=request_options)
        return _response.data

    async def get(
        self,
        *,
        phone: str,
        level: PhoneDetailsSchemaLevel,
        options: typing.Optional[RetrievePhoneNumberDetailsOptions] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> PhoneNumbersGetResponse:
        """
        Retrieve information about any phone number.

        Parameters
        ----------
        phone : str
            Phone number you want to analyze in E.164 format.

        level : PhoneDetailsSchemaLevel
            Choose how much detail you want in your results:
            - `basic`: Receive essential info like carrier, location, and format.
            - `advanced`: Receive a deeper analysis including fraud risk, detailed location, and enhanced contact info.

        options : typing.Optional[RetrievePhoneNumberDetailsOptions]
            Customize your lookup with additional options.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        PhoneNumbersGetResponse
            Returns detailed information for the requested phone number based on the selected lookup.

        Examples
        --------
        import asyncio

        from rcs import AsyncPinnacle
        from rcs.phone_numbers import (
            EnhancedContactInfo,
            RetrievePhoneNumberDetailsOptions,
        )

        client = AsyncPinnacle(
            api_key="YOUR_API_KEY",
        )


        async def main() -> None:
            await client.phone_numbers.get(
                phone="+11234567890",
                level="advanced",
                options=RetrievePhoneNumberDetailsOptions(
                    risk=True,
                    enhanced_contact_info=EnhancedContactInfo(
                        context="This is my friend from JZ. He has done a lot in the crypto space.",
                    ),
                ),
            )


        asyncio.run(main())
        """
        _response = await self._raw_client.get(
            phone=phone, level=level, options=options, request_options=request_options
        )
        return _response.data

    @property
    def webhook(self):
        if self._webhook is None:
            from .webhook.client import AsyncWebhookClient  # noqa: E402

            self._webhook = AsyncWebhookClient(client_wrapper=self._client_wrapper)
        return self._webhook

    @property
    def campaign(self):
        if self._campaign is None:
            from .campaign.client import AsyncCampaignClient  # noqa: E402

            self._campaign = AsyncCampaignClient(client_wrapper=self._client_wrapper)
        return self._campaign
