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

import typing
from json.decoder import JSONDecodeError

from ..core.api_error import ApiError
from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
from ..core.http_response import AsyncHttpResponse, HttpResponse
from ..core.jsonable_encoder import jsonable_encoder
from ..core.request_options import RequestOptions
from ..core.serialization import convert_and_respect_annotation_metadata
from ..core.unchecked_base_model import construct_type
from .types.add_phone_numbers_request_inbound_config import AddPhoneNumbersRequestInboundConfig
from .types.add_phone_numbers_request_outbound_config import AddPhoneNumbersRequestOutboundConfig
from .types.add_phone_numbers_request_provider import AddPhoneNumbersRequestProvider
from .types.add_phone_numbers_response import AddPhoneNumbersResponse
from .types.get_phone_numbers_response import GetPhoneNumbersResponse
from .types.list_phone_numbers_response_item import ListPhoneNumbersResponseItem
from .types.update_phone_numbers_request_inbound_config import UpdatePhoneNumbersRequestInboundConfig
from .types.update_phone_numbers_request_outbound_config import UpdatePhoneNumbersRequestOutboundConfig
from .types.update_phone_numbers_response import UpdatePhoneNumbersResponse

# this is used as the default value for optional parameters
OMIT = typing.cast(typing.Any, ...)


class RawPhoneNumbersClient:
    def __init__(self, *, client_wrapper: SyncClientWrapper):
        self._client_wrapper = client_wrapper

    def list(
        self, *, request_options: typing.Optional[RequestOptions] = None
    ) -> HttpResponse[typing.List[ListPhoneNumbersResponseItem]]:
        """
        Retrieve a list of all imported phone numbers under the current account.

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

        Returns
        -------
        HttpResponse[typing.List[ListPhoneNumbersResponseItem]]
            Request was successful. The response body contains a JSON array of phone number configurations.
        """
        _response = self._client_wrapper.httpx_client.request(
            "v2/phone-numbers",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    typing.List[ListPhoneNumbersResponseItem],
                    construct_type(
                        type_=typing.List[ListPhoneNumbersResponseItem],  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def add(
        self,
        *,
        provider: AddPhoneNumbersRequestProvider,
        phone_number: str,
        label: str,
        inbound_config: AddPhoneNumbersRequestInboundConfig,
        outbound_config: AddPhoneNumbersRequestOutboundConfig,
        inbound: typing.Optional[bool] = OMIT,
        outbound: typing.Optional[bool] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[AddPhoneNumbersResponse]:
        """
        Import a pre-configured phone number that can be used for inbound or outbound calls.

        Parameters
        ----------
        provider : AddPhoneNumbersRequestProvider
            Number provider:
            - `byo`: BYO (Bring Your Own)
            - `twilio`: Twilio

        phone_number : str
            Telephone number in E.164 format.

        label : str
            A label used to identify the number.

        inbound_config : AddPhoneNumbersRequestInboundConfig
            SIP inbound call configuration.

        outbound_config : AddPhoneNumbersRequestOutboundConfig
            SIP outbound call configuration.

        inbound : typing.Optional[bool]
            Whether the number supports inbound calls.

        outbound : typing.Optional[bool]
            Whether the number supports outbound calls.

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

        Returns
        -------
        HttpResponse[AddPhoneNumbersResponse]
            Request was successful. The response body contains the result of the request.
        """
        _response = self._client_wrapper.httpx_client.request(
            "v2/phone-numbers",
            method="POST",
            json={
                "provider": provider,
                "phone_number": phone_number,
                "label": label,
                "inbound": inbound,
                "outbound": outbound,
                "inbound_config": convert_and_respect_annotation_metadata(
                    object_=inbound_config, annotation=AddPhoneNumbersRequestInboundConfig, direction="write"
                ),
                "outbound_config": convert_and_respect_annotation_metadata(
                    object_=outbound_config, annotation=AddPhoneNumbersRequestOutboundConfig, direction="write"
                ),
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    AddPhoneNumbersResponse,
                    construct_type(
                        type_=AddPhoneNumbersResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def get(
        self, phone_number: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> HttpResponse[GetPhoneNumbersResponse]:
        """
        Retrieve detailed information for a specific phone number.

        Parameters
        ----------
        phone_number : str
            Telephone number in E.164 format. For example, +11234567890.

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

        Returns
        -------
        HttpResponse[GetPhoneNumbersResponse]
            Request was successful. The response body contains the result of the request.
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v2/phone-numbers/{jsonable_encoder(phone_number)}",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    GetPhoneNumbersResponse,
                    construct_type(
                        type_=GetPhoneNumbersResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def delete(
        self, phone_number: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> HttpResponse[None]:
        """
        Remove an imported phone number from the system.

        After calling this endpoint, the number stops receiving calls routed through this system. To delete the number from the service provider, remove it in the service provider's console.
        > This operation only removes the number configuration from the Agora system; the number stored with the phone service provider is not deleted.

        Parameters
        ----------
        phone_number : str
            Telephone number in E.164 format. For example, +11234567890.

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

        Returns
        -------
        HttpResponse[None]
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v2/phone-numbers/{jsonable_encoder(phone_number)}",
            method="DELETE",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return HttpResponse(response=_response, data=None)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    def update(
        self,
        phone_number: str,
        *,
        inbound_config: typing.Optional[UpdatePhoneNumbersRequestInboundConfig] = OMIT,
        outbound_config: typing.Optional[UpdatePhoneNumbersRequestOutboundConfig] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[UpdatePhoneNumbersResponse]:
        """
        Update the configuration for a phone number.

        Parameters
        ----------
        phone_number : str
            Telephone number in E.164 format. For example, +11234567890.

        inbound_config : typing.Optional[UpdatePhoneNumbersRequestInboundConfig]
            Update inbound call configuration. Passing `null` will clear the configuration.

        outbound_config : typing.Optional[UpdatePhoneNumbersRequestOutboundConfig]
            Update outbound call configuration. Passing `null` will clear the configuration.

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

        Returns
        -------
        HttpResponse[UpdatePhoneNumbersResponse]
            Request was successful. The response body contains the result of the request.
        """
        _response = self._client_wrapper.httpx_client.request(
            f"v2/phone-numbers/{jsonable_encoder(phone_number)}",
            method="PATCH",
            json={
                "inbound_config": convert_and_respect_annotation_metadata(
                    object_=inbound_config,
                    annotation=typing.Optional[UpdatePhoneNumbersRequestInboundConfig],
                    direction="write",
                ),
                "outbound_config": convert_and_respect_annotation_metadata(
                    object_=outbound_config,
                    annotation=typing.Optional[UpdatePhoneNumbersRequestOutboundConfig],
                    direction="write",
                ),
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    UpdatePhoneNumbersResponse,
                    construct_type(
                        type_=UpdatePhoneNumbersResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)


class AsyncRawPhoneNumbersClient:
    def __init__(self, *, client_wrapper: AsyncClientWrapper):
        self._client_wrapper = client_wrapper

    async def list(
        self, *, request_options: typing.Optional[RequestOptions] = None
    ) -> AsyncHttpResponse[typing.List[ListPhoneNumbersResponseItem]]:
        """
        Retrieve a list of all imported phone numbers under the current account.

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

        Returns
        -------
        AsyncHttpResponse[typing.List[ListPhoneNumbersResponseItem]]
            Request was successful. The response body contains a JSON array of phone number configurations.
        """
        _response = await self._client_wrapper.httpx_client.request(
            "v2/phone-numbers",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    typing.List[ListPhoneNumbersResponseItem],
                    construct_type(
                        type_=typing.List[ListPhoneNumbersResponseItem],  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def add(
        self,
        *,
        provider: AddPhoneNumbersRequestProvider,
        phone_number: str,
        label: str,
        inbound_config: AddPhoneNumbersRequestInboundConfig,
        outbound_config: AddPhoneNumbersRequestOutboundConfig,
        inbound: typing.Optional[bool] = OMIT,
        outbound: typing.Optional[bool] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[AddPhoneNumbersResponse]:
        """
        Import a pre-configured phone number that can be used for inbound or outbound calls.

        Parameters
        ----------
        provider : AddPhoneNumbersRequestProvider
            Number provider:
            - `byo`: BYO (Bring Your Own)
            - `twilio`: Twilio

        phone_number : str
            Telephone number in E.164 format.

        label : str
            A label used to identify the number.

        inbound_config : AddPhoneNumbersRequestInboundConfig
            SIP inbound call configuration.

        outbound_config : AddPhoneNumbersRequestOutboundConfig
            SIP outbound call configuration.

        inbound : typing.Optional[bool]
            Whether the number supports inbound calls.

        outbound : typing.Optional[bool]
            Whether the number supports outbound calls.

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

        Returns
        -------
        AsyncHttpResponse[AddPhoneNumbersResponse]
            Request was successful. The response body contains the result of the request.
        """
        _response = await self._client_wrapper.httpx_client.request(
            "v2/phone-numbers",
            method="POST",
            json={
                "provider": provider,
                "phone_number": phone_number,
                "label": label,
                "inbound": inbound,
                "outbound": outbound,
                "inbound_config": convert_and_respect_annotation_metadata(
                    object_=inbound_config, annotation=AddPhoneNumbersRequestInboundConfig, direction="write"
                ),
                "outbound_config": convert_and_respect_annotation_metadata(
                    object_=outbound_config, annotation=AddPhoneNumbersRequestOutboundConfig, direction="write"
                ),
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    AddPhoneNumbersResponse,
                    construct_type(
                        type_=AddPhoneNumbersResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def get(
        self, phone_number: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> AsyncHttpResponse[GetPhoneNumbersResponse]:
        """
        Retrieve detailed information for a specific phone number.

        Parameters
        ----------
        phone_number : str
            Telephone number in E.164 format. For example, +11234567890.

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

        Returns
        -------
        AsyncHttpResponse[GetPhoneNumbersResponse]
            Request was successful. The response body contains the result of the request.
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v2/phone-numbers/{jsonable_encoder(phone_number)}",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    GetPhoneNumbersResponse,
                    construct_type(
                        type_=GetPhoneNumbersResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def delete(
        self, phone_number: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> AsyncHttpResponse[None]:
        """
        Remove an imported phone number from the system.

        After calling this endpoint, the number stops receiving calls routed through this system. To delete the number from the service provider, remove it in the service provider's console.
        > This operation only removes the number configuration from the Agora system; the number stored with the phone service provider is not deleted.

        Parameters
        ----------
        phone_number : str
            Telephone number in E.164 format. For example, +11234567890.

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

        Returns
        -------
        AsyncHttpResponse[None]
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v2/phone-numbers/{jsonable_encoder(phone_number)}",
            method="DELETE",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                return AsyncHttpResponse(response=_response, data=None)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)

    async def update(
        self,
        phone_number: str,
        *,
        inbound_config: typing.Optional[UpdatePhoneNumbersRequestInboundConfig] = OMIT,
        outbound_config: typing.Optional[UpdatePhoneNumbersRequestOutboundConfig] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[UpdatePhoneNumbersResponse]:
        """
        Update the configuration for a phone number.

        Parameters
        ----------
        phone_number : str
            Telephone number in E.164 format. For example, +11234567890.

        inbound_config : typing.Optional[UpdatePhoneNumbersRequestInboundConfig]
            Update inbound call configuration. Passing `null` will clear the configuration.

        outbound_config : typing.Optional[UpdatePhoneNumbersRequestOutboundConfig]
            Update outbound call configuration. Passing `null` will clear the configuration.

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

        Returns
        -------
        AsyncHttpResponse[UpdatePhoneNumbersResponse]
            Request was successful. The response body contains the result of the request.
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"v2/phone-numbers/{jsonable_encoder(phone_number)}",
            method="PATCH",
            json={
                "inbound_config": convert_and_respect_annotation_metadata(
                    object_=inbound_config,
                    annotation=typing.Optional[UpdatePhoneNumbersRequestInboundConfig],
                    direction="write",
                ),
                "outbound_config": convert_and_respect_annotation_metadata(
                    object_=outbound_config,
                    annotation=typing.Optional[UpdatePhoneNumbersRequestOutboundConfig],
                    direction="write",
                ),
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    UpdatePhoneNumbersResponse,
                    construct_type(
                        type_=UpdatePhoneNumbersResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            _response_json = _response.json()
        except JSONDecodeError:
            raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
        raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
